#!/usr/bin/python
# -*- coding: iso-8859-1 -*-
#
# Copyright (C) 2004 Nicolas Girard < bobert at dlfp dot org >
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
import os,sys,re
from os.path import join
from itertools import ifilter
from sets import Set
class Finder:
"""Parcourt une hiérarchie de répertoires à partir de startDirectory"""
def __init__(self,startDirectory):
self.walker = os.walk(startDirectory)
def walk(self):
while 1:
root, dirs, files = self.walker.next()
for file in files:
yield (root,file)
def phpFiles(self):
isPhp = lambda (r,f):f.endswith('.php') or f.endswith('.php3')
return ifilter(isPhp,self.walk())
def find(dir):
return Finder(dir)
class PhpFile:
include = re.compile(".*include\s*\(['\"](\S+)['\"]\)\s*;")
def __init__(self,dir,name):
(self.dir,self.name)=(dir,name)
def includes(self):
f=open(join(self.dir,self.name),'r')
lines=f.readlines()
f.close()
for line in lines:
if PhpFile.include.match(line):
yield PhpFile.include.match(line).group(1).split('/')[-1]
class Node:
def __init__(self,name,labels=[],children=Set()):
(self.name,self.labels,self.children,self.nodes)=(name,labels,children,None)
def mergeWith(self,node):
self.labels+=node.labels
def label(self):
return "\\n".join(self.labels)
def edges(self):
return "\n".join(map(lambda child,s=self:"%s -> %s"%(s.name,child.name),self.children))
def __eq__(self,other):
return self.name==other.name
def __str__(self):
return "%s [label=\"%s\"]\n%s"%(self.name,self.label(),self.edges())
def rank(self):
"""calcule le nombre de parents du noeud"""
return sum(map(lambda o,s=self,:s in o.children,self.nodes))
def isExcluded(self):
return self.rank()==0 and len(self.children)==0
class Graph:
def __init__(self,ranksep=2,nodesep=0.5,minlen=1.5,concentrate=True,nodes=[]):
self.nodes=nodes
self.head="""
digraph Schema {
node[shape=box];
concentrate=%s;
ranksep=%f;
nodesep=%f;
edge[minlen=%f];\n"""%(concentrate,ranksep,nodesep,minlen)
self.foot="}\n"
def append(self,node):
node.nodes=self.nodes
self.nodes.append(node)
def __getitem__(self,nodeName):
res=filter(lambda node,n=nodeName:node.name==n,self.nodes)
if len(res)==1:
return res[0]
else:
return None
def checkChildren(self):
"""On supprime les fichiers inclus ne correspondant pas à un fichier trouvé
et les doublons"""
for node in self.nodes:
node.children = filter(lambda ch,fath=node:ch and fath!=ch,
map(lambda c,s=self:self[c],node.children))
def removeExcluded(self):
"""supprime les noeuds exclus du graphe"""
for excluded in filter(Node.isExcluded,self.nodes):
self.nodes.remove(excluded)
def clusterize(self):
"""Regroupe les fichers non-inclus par d'autres, et incluant les mêmes fichiers"""
nodes = filter(lambda n:n.rank()==0,self.nodes)
for node in nodes:
(node.clustered,node.removed)=(False,False)
for node in nodes:
ch = node.children[:]
for other in nodes:
if other == node or other.clustered or other.removed:
continue
if ch==other.children:
node.mergeWith(other)
node.clustered=True
other.removed=True
for node in filter(lambda n:n.removed,nodes):
self.nodes.remove(node)
def __str__(self):
for i in range(len(self.nodes)):
self.nodes[i].name="node%d"%i
return self.head+"\n".join(map(str,self.nodes))+self.foot
usage="""
php2dot - Génère un script dot des relations d'inclusion entre fichiers PHP
Syntaxe: php2dot startDir
startDir : répertoire de recherche des fichiers PHP.
La recherche est récursive.
Synopsis:
php2dot startDir > graph.dot
dot -Tpng -ograph.png graph.dot
Limitation:
Les noms des fichiers PHP trouvés doivent être distincts
"""
if __name__=="__main__":
if len(sys.argv)==1:
print usage
sys.exit(0)
startDir=sys.argv[1]
graph = Graph()
for (dir,name) in find(startDir).phpFiles():
phpFile = PhpFile(dir,name)
if not graph[name]:
graph.append(Node(name,[name],phpFile.includes()))
graph.checkChildren()
graph.removeExcluded()
graph.clusterize()
print graph
[^] # php2dot
Posté par bobert . En réponse au message graphe des liaisons entre fichiers. Évalué à 2.
#!/usr/bin/python # -*- coding: iso-8859-1 -*- # # Copyright (C) 2004 Nicolas Girard < bobert at dlfp dot org > # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. import os,sys,re from os.path import join from itertools import ifilter from sets import Set class Finder: """Parcourt une hiérarchie de répertoires à partir de startDirectory""" def __init__(self,startDirectory): self.walker = os.walk(startDirectory) def walk(self): while 1: root, dirs, files = self.walker.next() for file in files: yield (root,file) def phpFiles(self): isPhp = lambda (r,f):f.endswith('.php') or f.endswith('.php3') return ifilter(isPhp,self.walk()) def find(dir): return Finder(dir) class PhpFile: include = re.compile(".*include\s*\(['\"](\S+)['\"]\)\s*;") def __init__(self,dir,name): (self.dir,self.name)=(dir,name) def includes(self): f=open(join(self.dir,self.name),'r') lines=f.readlines() f.close() for line in lines: if PhpFile.include.match(line): yield PhpFile.include.match(line).group(1).split('/')[-1] class Node: def __init__(self,name,labels=[],children=Set()): (self.name,self.labels,self.children,self.nodes)=(name,labels,children,None) def mergeWith(self,node): self.labels+=node.labels def label(self): return "\\n".join(self.labels) def edges(self): return "\n".join(map(lambda child,s=self:"%s -> %s"%(s.name,child.name),self.children)) def __eq__(self,other): return self.name==other.name def __str__(self): return "%s [label=\"%s\"]\n%s"%(self.name,self.label(),self.edges()) def rank(self): """calcule le nombre de parents du noeud""" return sum(map(lambda o,s=self,:s in o.children,self.nodes)) def isExcluded(self): return self.rank()==0 and len(self.children)==0 class Graph: def __init__(self,ranksep=2,nodesep=0.5,minlen=1.5,concentrate=True,nodes=[]): self.nodes=nodes self.head=""" digraph Schema { node[shape=box]; concentrate=%s; ranksep=%f; nodesep=%f; edge[minlen=%f];\n"""%(concentrate,ranksep,nodesep,minlen) self.foot="}\n" def append(self,node): node.nodes=self.nodes self.nodes.append(node) def __getitem__(self,nodeName): res=filter(lambda node,n=nodeName:node.name==n,self.nodes) if len(res)==1: return res[0] else: return None def checkChildren(self): """On supprime les fichiers inclus ne correspondant pas à un fichier trouvé et les doublons""" for node in self.nodes: node.children = filter(lambda ch,fath=node:ch and fath!=ch, map(lambda c,s=self:self[c],node.children)) def removeExcluded(self): """supprime les noeuds exclus du graphe""" for excluded in filter(Node.isExcluded,self.nodes): self.nodes.remove(excluded) def clusterize(self): """Regroupe les fichers non-inclus par d'autres, et incluant les mêmes fichiers""" nodes = filter(lambda n:n.rank()==0,self.nodes) for node in nodes: (node.clustered,node.removed)=(False,False) for node in nodes: ch = node.children[:] for other in nodes: if other == node or other.clustered or other.removed: continue if ch==other.children: node.mergeWith(other) node.clustered=True other.removed=True for node in filter(lambda n:n.removed,nodes): self.nodes.remove(node) def __str__(self): for i in range(len(self.nodes)): self.nodes[i].name="node%d"%i return self.head+"\n".join(map(str,self.nodes))+self.foot usage=""" php2dot - Génère un script dot des relations d'inclusion entre fichiers PHP Syntaxe: php2dot startDir startDir : répertoire de recherche des fichiers PHP. La recherche est récursive. Synopsis: php2dot startDir > graph.dot dot -Tpng -ograph.png graph.dot Limitation: Les noms des fichiers PHP trouvés doivent être distincts """ if __name__=="__main__": if len(sys.argv)==1: print usage sys.exit(0) startDir=sys.argv[1] graph = Graph() for (dir,name) in find(startDir).phpFiles(): phpFile = PhpFile(dir,name) if not graph[name]: graph.append(Node(name,[name],phpFile.includes())) graph.checkChildren() graph.removeExcluded() graph.clusterize() print graph