def testSaveLoad(self): test_conf = os.path.join(test_path, 'test.conf') dm = DumbManager() dm._location = test_conf s = WorkflowScene(dm) ws = QtCore.QSettings(test_conf, QtCore.QSettings.IniFormat) ds1 = DumbStep() ds1._identifier = '1' ds1._name = 'a' ds2 = DumbStep() ds2._identifier = '2' ds2._name = 'b' item1 = MetaStep(ds1) item2 = MetaStep(ds2) s.addItem(item1) s.addItem(item2) s.saveState(ws) del ws self.assertTrue(os.path.exists(test_conf)) file_content = open(test_conf).read() self.assertIn('Point(0 0)', file_content) self.assertIn('name=a', file_content) self.assertIn('name=b', file_content) self.assertNotIn('selected=false', file_content) os.remove(test_conf)
def testItemAPI(self): item = MetaStep(DumbStep()) s = WorkflowScene(DumbManager()) s.addItem(item) self.assertEqual(len(s._items), 1) s.setItemPos(item, QtCore.QPoint(344, 404)) self.assertEqual(s._items[item]._pos.x(), 344) self.assertEqual(s._items[item]._pos.y(), 404) s.setItemSelected(item, False) self.assertFalse(s._items[item]._selected) s.removeItem(item) self.assertEqual(len(s._items), 0)
def setUp(self): self._s = WorkflowScene(DumbManager()) self._nodes = [] self._nodes.append(MetaStep(DumbStep())) self._nodes.append(MetaStep(DumbStep())) self._nodes.append(MetaStep(DumbStep())) self._nodes.append(MetaStep(DumbStep())) self._nodes.append(MetaStep(DumbStep())) self._nodes.append(MetaStep(DumbStep())) self._nodes.append(MetaStep(DumbStep()))
def __init__(self): ''' Constructor ''' self.name = 'WorkflowManager' # self.widget = None # self.widgetIndex = -1 self._location = '' self._workspace_location = None self._conf_filename = None self._previousLocation = None self._saveStateIndex = 0 self._currentStateIndex = 0 self._title = None self._scene = WorkflowScene(self)
class WorkflowDependencyGraphTestCase(unittest.TestCase): def assertIn(self, a, b, *args, **kwargs): ''''Python < v2.7 compatibility. Assert "a" in "b"''' try: f = super(WorkflowDependencyGraphTestCase, self).assertIn except AttributeError: self.assertTrue(a in b, *args, **kwargs) else: f(a, b, *args, **kwargs) def assertNotIn(self, a, b, *args, **kwargs): ''''Python < v2.7 compatibility. Assert "a" NOT in "b"''' try: f = super(WorkflowDependencyGraphTestCase, self).assertNotIn except AttributeError: self.assertFalse(a in b, *args, **kwargs) else: f(a, b, *args, **kwargs) def assertLess(self, a, b, *args, **kwargs): ''''Python < v2.7 compatibility. Assert "a" less "b"''' try: f = super(WorkflowDependencyGraphTestCase, self).assertLess except AttributeError: self.assertTrue(a < b, *args, **kwargs) else: f(a, b, *args, **kwargs) def setUp(self): self._s = WorkflowScene(DumbManager()) self._nodes = [] self._nodes.append(MetaStep(DumbStep())) self._nodes.append(MetaStep(DumbStep())) self._nodes.append(MetaStep(DumbStep())) self._nodes.append(MetaStep(DumbStep())) self._nodes.append(MetaStep(DumbStep())) self._nodes.append(MetaStep(DumbStep())) self._nodes.append(MetaStep(DumbStep())) def tearDown(self): self._s.clear() self._nodes = [] def testCreate(self): g = WorkflowDependencyGraph(self._s) self.assertTrue(g != None) def testGraph1(self): g = WorkflowDependencyGraph(self._s) c1 = Connection(self._nodes[0], 0, self._nodes[1], 0) self._s.addItem(self._nodes[0]) self._s.addItem(self._nodes[1]) self._s.addItem(c1) self.assertTrue(g.canExecute()) self.assertEqual(len(g._topologicalOrder), 2) self.assertEqual(g._topologicalOrder[0], self._nodes[0]) self.assertEqual(g._topologicalOrder[1], self._nodes[1]) def testGraph2(self): g = WorkflowDependencyGraph(self._s) c1 = Connection(self._nodes[0], 0, self._nodes[1], 0) c2 = Connection(self._nodes[1], 0, self._nodes[2], 0) self._s.addItem(self._nodes[0]) self._s.addItem(self._nodes[1]) self._s.addItem(self._nodes[2]) self._s.addItem(c1) self._s.addItem(c2) self.assertTrue(g.canExecute()) self.assertEqual(len(g._topologicalOrder), 3) self.assertEqual(g._topologicalOrder[0], self._nodes[0]) self.assertEqual(g._topologicalOrder[1], self._nodes[1]) self.assertEqual(g._topologicalOrder[2], self._nodes[2]) def testGraph3(self): g = WorkflowDependencyGraph(self._s) c1 = Connection(self._nodes[0], 0, self._nodes[1], 0) c2 = Connection(self._nodes[1], 0, self._nodes[2], 0) c3 = Connection(self._nodes[2], 0, self._nodes[3], 0) self._s.addItem(self._nodes[0]) self._s.addItem(self._nodes[1]) self._s.addItem(self._nodes[2]) self._s.addItem(self._nodes[3]) self._s.addItem(c3) self._s.addItem(c1) self._s.addItem(c2) self.assertTrue(g.canExecute()) self.assertEqual(len(g._topologicalOrder), 4) self.assertEqual(g._topologicalOrder[0], self._nodes[0]) self.assertEqual(g._topologicalOrder[1], self._nodes[1]) self.assertEqual(g._topologicalOrder[2], self._nodes[2]) self.assertEqual(g._topologicalOrder[3], self._nodes[3]) def testGraph4(self): g = WorkflowDependencyGraph(self._s) c1 = Connection(self._nodes[0], 0, self._nodes[1], 0) c2 = Connection(self._nodes[1], 0, self._nodes[2], 0) c3 = Connection(self._nodes[2], 0, self._nodes[3], 0) self._s.addItem(self._nodes[0]) self._s.addItem(self._nodes[1]) self._s.addItem(self._nodes[2]) self._s.addItem(self._nodes[3]) self._s.addItem(self._nodes[4]) self._s.addItem(self._nodes[5]) self._s.addItem(c3) self._s.addItem(c1) self._s.addItem(c2) nodes = g._findAllConnectedNodes() self.assertEqual(4, len(nodes)) self.assertIn(self._nodes[0], nodes) self.assertIn(self._nodes[1], nodes) self.assertIn(self._nodes[2], nodes) self.assertIn(self._nodes[3], nodes) self.assertNotIn(self._nodes[4], nodes) self.assertNotIn(self._nodes[5], nodes) def testGraph5(self): g = WorkflowDependencyGraph(self._s) c1 = Connection(self._nodes[0], 0, self._nodes[2], 0) c2 = Connection(self._nodes[1], 0, self._nodes[2], 0) c3 = Connection(self._nodes[2], 0, self._nodes[3], 0) c4 = Connection(self._nodes[2], 0, self._nodes[4], 0) self._s.addItem(self._nodes[0]) self._s.addItem(self._nodes[1]) self._s.addItem(self._nodes[2]) self._s.addItem(self._nodes[3]) self._s.addItem(self._nodes[4]) self._s.addItem(self._nodes[5]) self._s.addItem(c1) self._s.addItem(c2) self._s.addItem(c3) self._s.addItem(c4) nodes = g._findAllConnectedNodes() self.assertEqual(5, len(nodes)) self.assertIn(self._nodes[0], nodes) self.assertIn(self._nodes[1], nodes) self.assertIn(self._nodes[2], nodes) self.assertIn(self._nodes[3], nodes) self.assertIn(self._nodes[4], nodes) self.assertNotIn(self._nodes[5], nodes) graph = g._calculateDependencyGraph() self.assertFalse(g._nodeIsDestination(graph, self._nodes[0])) self.assertFalse(g._nodeIsDestination(graph, self._nodes[1])) self.assertTrue(g._nodeIsDestination(graph, self._nodes[2])) self.assertTrue(g._nodeIsDestination(graph, self._nodes[3])) self.assertTrue(g._nodeIsDestination(graph, self._nodes[4])) self.assertFalse(g._nodeIsDestination(graph, self._nodes[5])) starting_set = g._findStartingSet(graph, nodes) self.assertEqual(2, len(starting_set)) self.assertIn(self._nodes[0], starting_set) self.assertIn(self._nodes[1], starting_set) self.assertNotIn(self._nodes[2], starting_set) self.assertNotIn(self._nodes[3], starting_set) self.assertNotIn(self._nodes[4], starting_set) self.assertNotIn(self._nodes[5], starting_set) order = g._determineTopologicalOrder(graph, starting_set) self.assertEqual(5, len(order)) index0 = order.index(self._nodes[0]) index1 = order.index(self._nodes[1]) index2 = order.index(self._nodes[2]) index3 = order.index(self._nodes[3]) index4 = order.index(self._nodes[4]) self.assertLess(index1, index2) self.assertLess(index0, index2) self.assertLess(index2, index3) self.assertLess(index2, index4) def testGraph6(self): g = WorkflowDependencyGraph(self._s) c1 = Connection(self._nodes[0], 0, self._nodes[2], 0) c2 = Connection(self._nodes[1], 0, self._nodes[2], 0) c3 = Connection(self._nodes[2], 0, self._nodes[3], 0) c4 = Connection(self._nodes[2], 0, self._nodes[4], 0) c5 = Connection(self._nodes[6], 0, self._nodes[0], 0) c6 = Connection(self._nodes[6], 0, self._nodes[1], 0) self._s.addItem(self._nodes[0]) self._s.addItem(self._nodes[1]) self._s.addItem(self._nodes[2]) self._s.addItem(self._nodes[3]) self._s.addItem(self._nodes[4]) self._s.addItem(self._nodes[5]) self._s.addItem(self._nodes[6]) self._s.addItem(c1) self._s.addItem(c2) self._s.addItem(c3) self._s.addItem(c4) self._s.addItem(c5) self._s.addItem(c6) nodes = g._findAllConnectedNodes() self.assertEqual(6, len(nodes)) graph = g._calculateDependencyGraph() starting_set = g._findStartingSet(graph, nodes) self.assertEqual(1, len(starting_set)) order = g._determineTopologicalOrder(graph, starting_set) self.assertEqual(6, len(order)) index0 = order.index(self._nodes[6]) index1 = order.index(self._nodes[1]) self.assertLess(index0, index1) def testGraph7(self): ''' Testing independent graphs ''' g = WorkflowDependencyGraph(self._s) c1 = Connection(self._nodes[0], 0, self._nodes[2], 0) c2 = Connection(self._nodes[1], 0, self._nodes[2], 0) c3 = Connection(self._nodes[2], 0, self._nodes[3], 0) c4 = Connection(self._nodes[2], 0, self._nodes[4], 0) c5 = Connection(self._nodes[6], 0, self._nodes[5], 0) self._s.addItem(self._nodes[0]) self._s.addItem(self._nodes[1]) self._s.addItem(self._nodes[2]) self._s.addItem(self._nodes[3]) self._s.addItem(self._nodes[4]) self._s.addItem(self._nodes[5]) self._s.addItem(self._nodes[6]) self._s.addItem(c1) self._s.addItem(c2) self._s.addItem(c3) self._s.addItem(c4) self._s.addItem(c5) nodes = g._findAllConnectedNodes() self.assertEqual(7, len(nodes)) graph = g._calculateDependencyGraph() starting_set = g._findStartingSet(graph, nodes) self.assertEqual(3, len(starting_set)) order = g._determineTopologicalOrder(graph, starting_set) self.assertEqual(7, len(order)) def testGraph8(self): ''' Testing graph with loop ''' g = WorkflowDependencyGraph(self._s) c1 = Connection(self._nodes[0], 0, self._nodes[1], 0) c2 = Connection(self._nodes[1], 0, self._nodes[2], 0) c3 = Connection(self._nodes[2], 0, self._nodes[3], 0) c4 = Connection(self._nodes[3], 0, self._nodes[4], 0) c5 = Connection(self._nodes[3], 0, self._nodes[5], 0) c6 = Connection(self._nodes[5], 0, self._nodes[6], 0) c7 = Connection(self._nodes[6], 0, self._nodes[2], 0) self._s.addItem(self._nodes[0]) self._s.addItem(self._nodes[1]) self._s.addItem(self._nodes[2]) self._s.addItem(self._nodes[3]) self._s.addItem(self._nodes[4]) self._s.addItem(self._nodes[5]) self._s.addItem(self._nodes[6]) self._s.addItem(c1) self._s.addItem(c2) self._s.addItem(c3) self._s.addItem(c4) self._s.addItem(c5) self._s.addItem(c6) self._s.addItem(c7) nodes = g._findAllConnectedNodes() self.assertEqual(7, len(nodes)) graph = g._calculateDependencyGraph() starting_set = g._findStartingSet(graph, nodes) self.assertEqual(1, len(starting_set)) order = g._determineTopologicalOrder(graph, starting_set) self.assertEqual(0, len(order)) def testExecute(self): g = WorkflowDependencyGraph(self._s) c1 = Connection(self._nodes[0], 0, self._nodes[2], 0) c2 = Connection(self._nodes[1], 0, self._nodes[2], 1) c3 = Connection(self._nodes[1], 1, self._nodes[2], 2) c4 = Connection(self._nodes[2], 0, self._nodes[3], 0) self._s.addItem(self._nodes[0]) self._s.addItem(self._nodes[1]) self._s.addItem(self._nodes[2]) self._s.addItem(self._nodes[3]) self._s.addItem(c1) self._s.addItem(c2) self._s.addItem(c3) self._s.addItem(c4) g.canExecute() for _ in range(len(g._topologicalOrder)): g.execute()
class WorkflowManager(object): ''' This class manages (models?) the workflow. ''' def __init__(self): ''' Constructor ''' self.name = 'WorkflowManager' # self.widget = None # self.widgetIndex = -1 self._location = '' self._workspace_location = None self._conf_filename = None self._previousLocation = None self._saveStateIndex = 0 self._currentStateIndex = 0 self._title = None self._scene = WorkflowScene(self) def title(self): self._title = info.APPLICATION_NAME if self._location: self._title = self._title + ' - ' + self._location if self._saveStateIndex != self._currentStateIndex: self._title = self._title + ' *' return self._title # Why set/get? all _prefix are public anyway, just use attributes... # if they need to be modified they can be turned into properties def setLocation(self, location): self._location = location def location(self): return self._location def setPreviousLocation(self, location): self._previousLocation = location def previousLocation(self): return self._previousLocation def scene(self): return self._scene def undoStackIndexChanged(self, index): self._currentStateIndex = index def identifierOccursCount(self, identifier): return self._scene.identifierOccursCount(identifier) def execute(self): self._scene.execute() def isModified(self): return self._saveStateIndex != self._currentStateIndex def new(self, location): ''' Create a new workflow at the given location. The location is a directory, it must exist it will not be created. A file '.workflow.conf' is created in the directory at 'location' which holds information relating to the workflow. ''' if location is None: raise WorkflowError('No location given to create new Workflow.') if not os.path.exists(location): raise WorkflowError('Location %s does not exist.' % location) self._location = location wf = _getWorkflowConfiguration(location) wf.setValue('version', info.VERSION_STRING) # self._title = info.APPLICATION_NAME + ' - ' + location self._scene.clear() def exists(self, location): ''' Determines whether a workflow exists in the given location. Returns True if a valid workflow exists, False otherwise. ''' if location is None: return False if not os.path.exists(location): return False wf = _getWorkflowConfiguration(location) if wf.contains('version'): return True return False def load(self, location): ''' Open a workflow from the given location. :param location: ''' if location is None: raise WorkflowError('No location given to open Workflow.') if not os.path.exists(location): raise WorkflowError('Location %s does not exist' % location) wf = _getWorkflowConfiguration(location) if not wf.contains('version'): raise WorkflowError('The given Workflow configuration file is not valid.') workflow_version = versionTuple(wf.value('version')) software_version = versionTuple(info.VERSION_STRING) if not workflow_version[0:2] == software_version[0:2]: # compare first two elements of version (major, minor) raise WorkflowError( 'Major/Minor version number mismatch - ' 'application version: %s; workflow version: %s.' % (info.VERSION_STRING, wf.value('version')) ) if not workflow_version[2] <= software_version[2]: raise WorkflowError( 'Patch version number of the workflow cannot be newer than ' 'application - ' 'application version: %s; workflow version: %s' % (info.VERSION_STRING, wf.value('version')) ) self._location = location # wf = _getWorkflowConfiguration() self._scene.loadState(wf) self._saveStateIndex = self._currentStateIndex = 0 # self._title = info.APPLICATION_NAME + ' - ' + location def save(self): wf = _getWorkflowConfiguration(self._location) self._scene.saveState(wf) self._saveStateIndex = self._currentStateIndex af = _getWorkflowMetaAbsoluteFilename(self._location) f = open(af, 'w') f.write(serializeWorkflowAnnotation()) self._scene.saveAnnotation(f) f.close() # self._title = info.APPLICATION_NAME + ' - ' + self._location def close(self): ''' Close the current workflow ''' self._location = '' self._saveStateIndex = self._currentStateIndex = 0 # self._title = info.APPLICATION_NAME def isWorkflowOpen(self): return True # not self._location == None def writeSettings(self, settings): settings.beginGroup(self.name) settings.setValue(_PREVIOUS_LOCATION_STRING, self._previousLocation) settings.endGroup() def readSettings(self, settings): settings.beginGroup(self.name) self._previousLocation = settings.value(_PREVIOUS_LOCATION_STRING, '') settings.endGroup()