class DependencyResolver(object): def __init__(self, path, options): logging.debug("Creating DependencyResolver") self.graph = DAG() self.root = path self.opts = options def scan(self): for root, dirs, files in os.walk(self.root): for name in files: (base, ext) = os.path.splitext(name) if ext in ['.css', '.js']: data = self.scanfile(os.path.join(root, name)) for module in data[ 'module' ]: self.graph.addNode( Module( module=module, filename=data['filename'], package=data['package'], requires=data['requires'] ) ) for module in self.graph.nodes(): self.graph.addEdgesFromNode(module.id(), module.requirements()) def scanfile(self, path): logging.debug( "Scanning file: %s" % path ) metadata = { "filename": path, "package": [], "module": [], "requires": [] } with open( path, 'r' ) as f: in_comment = False for line in f: if in_comment: if re.search( "\*\/", line ): in_comment = False else: tags = re.search( "@(?P<name>\w+)\s+(?P<value>.+)\s*$", line ) if tags: (name, value) = (tags.group( 'name' ), re.split( '\s*,\s*', tags.group( 'value' ))) if metadata.has_key( name ): metadata[ name ].extend(value) else: if re.match( "\s*\/\*\*", line ): in_comment = True logging.debug( " - Result: %s" % metadata ) return metadata
class TestDAG(unittest.TestCase): def setUp(self): self.graph = DAG() # # Insertion # def test_insertion(self): self.assertEqual( len(self.graph.nodes()), 0 ) self.graph.addNode(MockNode('id1')) self.assertTrue( self.graph.contains( 'id1' ) ) self.assertRaises(DuplicateInsertionError, lambda: self.graph.addNode(MockNode('id1'))) def test_edgeinsertion(self): self.graph.addNode(MockNode('id1')) self.graph.addNode(MockNode('id2')) self.assertRaises(NodeNotExists, lambda: self.graph.addEdge('id1', 'id3')) self.assertRaises(NodeNotExists, lambda: self.graph.addEdge('id3', 'id1')) self.graph.addEdge('id1', 'id2') self.assertEquals(self.graph.neighbors('id1'), [ 'id2' ]) self.assertEquals(self.graph.neighbors('id2'), []) # # Cycle Detection # def test_cycledetection_simple(self): self.graph.addNode(MockNode('id1')) self.graph.addNode(MockNode('id2')) self.graph.addEdge('id1','id2') self.assertRaises(CyclicInsertionError, lambda: self.graph.addEdge('id2','id1')) def test_cycledetection_complex(self): prev = None for x in range( 100 ): self.graph.addNode(MockNode(x)) if prev is not None: self.graph.addEdge(prev, x) prev = x self.assertRaises(CyclicInsertionError, lambda: self.graph.addEdge(99, 0)) # # Topological Sort # def test_topologicalsort_empty(self): self.assertEquals( [], self.graph.topologicalSort(self.graph.nodes())) def test_topologicalsort_one(self): self.graph.addNode(MockNode('id1')) self.assertEquals( ['id1'], self.graph.topologicalSort(self.graph.nodes())) def test_topologicalsort_two(self): self.graph.addNode(MockNode('id1')) self.graph.addNode(MockNode('id2')) self.graph.addEdge('id1','id2') self.assertEquals( ['id2', 'id1'], self.graph.topologicalSort(self.graph.nodes())) def test_topologicalsort_many(self): prev = None list = [] for x in range( 100 ): self.graph.addNode(MockNode(x)) if prev is not None: self.graph.addEdge(prev, x) prev = x list.append( x ) list.reverse() self.assertEquals( list, self.graph.topologicalSort(self.graph.nodes()))