summaryrefslogtreecommitdiffstats
path: root/utils
diff options
context:
space:
mode:
authorGeorge Karpenkov <ekarpenkov@apple.com>2017-10-02 17:59:12 +0000
committerGeorge Karpenkov <ekarpenkov@apple.com>2017-10-02 17:59:12 +0000
commit86395f102e4891217829140100433c3ede93a0ef (patch)
tree09f25bf9142b5e924d21b6f0c87bc5addca3edcb /utils
parent3ee23996d9b525f4b8508b5c0f329aa9d3117b54 (diff)
[Analyzer] Make testing scripts flake8 compliant
Differential Review: https://reviews.llvm.org/D38213 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@314692 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'utils')
-rwxr-xr-xutils/analyzer/CmpRuns.py74
-rwxr-xr-xutils/analyzer/SATestAdd.py39
-rwxr-xr-xutils/analyzer/SATestBuild.py392
-rwxr-xr-xutils/analyzer/SATestUpdateDiffs.py26
-rw-r--r--utils/analyzer/SumTimerInfo.py78
-rwxr-xr-xutils/analyzer/ubiviz87
6 files changed, 397 insertions, 299 deletions
diff --git a/utils/analyzer/CmpRuns.py b/utils/analyzer/CmpRuns.py
index 065c7de1b3..2c0ed6aae3 100755
--- a/utils/analyzer/CmpRuns.py
+++ b/utils/analyzer/CmpRuns.py
@@ -6,8 +6,8 @@ which reports have been added, removed, or changed.
This is designed to support automated testing using the static analyzer, from
two perspectives:
- 1. To monitor changes in the static analyzer's reports on real code bases, for
- regression testing.
+ 1. To monitor changes in the static analyzer's reports on real code bases,
+ for regression testing.
2. For use by end users who want to integrate regular static analyzer testing
into a buildbot like environment.
@@ -29,6 +29,7 @@ Usage:
import os
import plistlib
+
# Information about analysis run:
# path - the analysis output directory
# root - the name of the root directory, which will be disregarded when
@@ -39,6 +40,7 @@ class SingleRunInfo:
self.root = root.rstrip("/\\")
self.verboseLog = verboseLog
+
class AnalysisDiagnostic:
def __init__(self, data, report, htmlReport):
self._data = data
@@ -50,7 +52,7 @@ class AnalysisDiagnostic:
root = self._report.run.root
fileName = self._report.files[self._loc['file']]
if fileName.startswith(root) and len(root) > 0:
- return fileName[len(root)+1:]
+ return fileName[len(root) + 1:]
return fileName
def getLine(self):
@@ -65,12 +67,12 @@ class AnalysisDiagnostic:
def getDescription(self):
return self._data['description']
- def getIssueIdentifier(self) :
+ def getIssueIdentifier(self):
id = self.getFileName() + "+"
- if 'issue_context' in self._data :
- id += self._data['issue_context'] + "+"
- if 'issue_hash_content_of_line_in_context' in self._data :
- id += str(self._data['issue_hash_content_of_line_in_context'])
+ if 'issue_context' in self._data:
+ id += self._data['issue_context'] + "+"
+ if 'issue_hash_content_of_line_in_context' in self._data:
+ id += str(self._data['issue_hash_content_of_line_in_context'])
return id
def getReport(self):
@@ -88,18 +90,21 @@ class AnalysisDiagnostic:
def getRawData(self):
return self._data
+
class CmpOptions:
def __init__(self, verboseLog=None, rootA="", rootB=""):
self.rootA = rootA
self.rootB = rootB
self.verboseLog = verboseLog
+
class AnalysisReport:
def __init__(self, run, files):
self.run = run
self.files = files
self.diagnostics = []
+
class AnalysisRun:
def __init__(self, info):
self.path = info.path
@@ -120,14 +125,14 @@ class AnalysisRun:
# reports. Assume that all reports were created using the same
# clang version (this is always true and is more efficient).
if 'clang_version' in data:
- if self.clang_version == None:
+ if self.clang_version is None:
self.clang_version = data.pop('clang_version')
else:
data.pop('clang_version')
# Ignore/delete empty reports.
if not data['files']:
- if deleteEmpty == True:
+ if deleteEmpty:
os.remove(p)
return
@@ -144,8 +149,7 @@ class AnalysisRun:
report = AnalysisReport(self, data.pop('files'))
diagnostics = [AnalysisDiagnostic(d, report, h)
- for d,h in zip(data.pop('diagnostics'),
- htmlFiles)]
+ for d, h in zip(data.pop('diagnostics'), htmlFiles)]
assert not data
@@ -154,15 +158,21 @@ class AnalysisRun:
self.diagnostics.extend(diagnostics)
-# Backward compatibility API.
-def loadResults(path, opts, root = "", deleteEmpty=True):
+def loadResults(path, opts, root="", deleteEmpty=True):
+ """
+ Backwards compatibility API.
+ """
return loadResultsFromSingleRun(SingleRunInfo(path, root, opts.verboseLog),
deleteEmpty)
-# Load results of the analyzes from a given output folder.
-# - info is the SingleRunInfo object
-# - deleteEmpty specifies if the empty plist files should be deleted
+
def loadResultsFromSingleRun(info, deleteEmpty=True):
+ """
+ # Load results of the analyzes from a given output folder.
+ # - info is the SingleRunInfo object
+ # - deleteEmpty specifies if the empty plist files should be deleted
+
+ """
path = info.path
run = AnalysisRun(info)
@@ -178,9 +188,11 @@ def loadResultsFromSingleRun(info, deleteEmpty=True):
return run
-def cmpAnalysisDiagnostic(d) :
+
+def cmpAnalysisDiagnostic(d):
return d.getIssueIdentifier()
+
def compareResults(A, B):
"""
compareResults - Generate a relation from diagnostics in run A to
@@ -199,12 +211,12 @@ def compareResults(A, B):
neqB = []
eltsA = list(A.diagnostics)
eltsB = list(B.diagnostics)
- eltsA.sort(key = cmpAnalysisDiagnostic)
- eltsB.sort(key = cmpAnalysisDiagnostic)
+ eltsA.sort(key=cmpAnalysisDiagnostic)
+ eltsB.sort(key=cmpAnalysisDiagnostic)
while eltsA and eltsB:
a = eltsA.pop()
b = eltsB.pop()
- if (a.getIssueIdentifier() == b.getIssueIdentifier()) :
+ if (a.getIssueIdentifier() == b.getIssueIdentifier()):
res.append((a, b, 0))
elif a.getIssueIdentifier() > b.getIssueIdentifier():
eltsB.append(b)
@@ -215,11 +227,11 @@ def compareResults(A, B):
neqA.extend(eltsA)
neqB.extend(eltsB)
- # FIXME: Add fuzzy matching. One simple and possible effective idea would be
- # to bin the diagnostics, print them in a normalized form (based solely on
- # the structure of the diagnostic), compute the diff, then use that as the
- # basis for matching. This has the nice property that we don't depend in any
- # way on the diagnostic format.
+ # FIXME: Add fuzzy matching. One simple and possible effective idea would
+ # be to bin the diagnostics, print them in a normalized form (based solely
+ # on the structure of the diagnostic), compute the diff, then use that as
+ # the basis for matching. This has the nice property that we don't depend
+ # in any way on the diagnostic format.
for a in neqA:
res.append((a, None, None))
@@ -228,6 +240,7 @@ def compareResults(A, B):
return res
+
def dumpScanBuildResultsDiff(dirA, dirB, opts, deleteEmpty=True):
# Load the run results.
resultsA = loadResults(dirA, opts, opts.rootA, deleteEmpty)
@@ -242,7 +255,7 @@ def dumpScanBuildResultsDiff(dirA, dirB, opts, deleteEmpty=True):
diff = compareResults(resultsA, resultsB)
foundDiffs = 0
for res in diff:
- a,b,confidence = res
+ a, b, confidence = res
if a is None:
print "ADDED: %r" % b.getReadableName()
foundDiffs += 1
@@ -277,6 +290,7 @@ def dumpScanBuildResultsDiff(dirA, dirB, opts, deleteEmpty=True):
return foundDiffs, len(resultsA.diagnostics), len(resultsB.diagnostics)
+
def main():
from optparse import OptionParser
parser = OptionParser("usage: %prog [options] [dir A] [dir B]")
@@ -287,7 +301,8 @@ def main():
help="Prefix to ignore on source files for directory B",
action="store", type=str, default="")
parser.add_option("", "--verbose-log", dest="verboseLog",
- help="Write additional information to LOG [default=None]",
+ help="Write additional information to LOG \
+ [default=None]",
action="store", type=str, default=None,
metavar="LOG")
(opts, args) = parser.parse_args()
@@ -295,9 +310,10 @@ def main():
if len(args) != 2:
parser.error("invalid number of arguments")
- dirA,dirB = args
+ dirA, dirB = args
dumpScanBuildResultsDiff(dirA, dirB, opts)
+
if __name__ == '__main__':
main()
diff --git a/utils/analyzer/SATestAdd.py b/utils/analyzer/SATestAdd.py
index ce5739e7d0..4c3e35cdcb 100755
--- a/utils/analyzer/SATestAdd.py
+++ b/utils/analyzer/SATestAdd.py
@@ -27,15 +27,17 @@ the Repository Directory.
- CachedSource/ - An optional directory containing the source of the
project being analyzed. If present,
download_project.sh will not be called.
- - changes_for_analyzer.patch - An optional patch file for any local changes
+ - changes_for_analyzer.patch - An optional patch file for any local
+ changes
(e.g., to adapt to newer version of clang)
that should be applied to CachedSource
before analysis. To construct this patch,
run the the download script to download
the project to CachedSource, copy the
CachedSource to another directory (for
- example, PatchedSource) and make any needed
- modifications to the the copied source.
+ example, PatchedSource) and make any
+ needed modifications to the the copied
+ source.
Then run:
diff -ur CachedSource PatchedSource \
> changes_for_analyzer.patch
@@ -46,18 +48,21 @@ import os
import csv
import sys
-def isExistingProject(PMapFile, projectID) :
+
+def isExistingProject(PMapFile, projectID):
PMapReader = csv.reader(PMapFile)
for I in PMapReader:
if projectID == I[0]:
return True
return False
-# Add a new project for testing: build it and add to the Project Map file.
-# Params:
-# Dir is the directory where the sources are.
-# ID is a short string used to identify a project.
-def addNewProject(ID, BuildMode) :
+
+def addNewProject(ID, BuildMode):
+ """
+ Add a new project for testing: build it and add to the Project Map file.
+ :param ID: is a short string used to identify a project.
+ """
+
CurDir = os.path.abspath(os.curdir)
Dir = SATestBuild.getProjectDir(ID)
if not os.path.exists(Dir):
@@ -69,29 +74,29 @@ def addNewProject(ID, BuildMode) :
# Add the project ID to the project map.
ProjectMapPath = os.path.join(CurDir, SATestBuild.ProjectMapFile)
+
if os.path.exists(ProjectMapPath):
- PMapFile = open(ProjectMapPath, "r+b")
+ FileMode = "r+b"
else:
print "Warning: Creating the Project Map file!!"
- PMapFile = open(ProjectMapPath, "w+b")
- try:
- if (isExistingProject(PMapFile, ID)) :
+ FileMode = "w+b"
+
+ with open(ProjectMapPath, FileMode) as PMapFile:
+ if (isExistingProject(PMapFile, ID)):
print >> sys.stdout, 'Warning: Project with ID \'', ID, \
'\' already exists.'
print >> sys.stdout, "Reference output has been regenerated."
else:
PMapWriter = csv.writer(PMapFile)
- PMapWriter.writerow( (ID, int(BuildMode)) );
+ PMapWriter.writerow((ID, int(BuildMode)))
print "The project map is updated: ", ProjectMapPath
- finally:
- PMapFile.close()
# TODO: Add an option not to build.
# TODO: Set the path to the Repository directory.
if __name__ == '__main__':
if len(sys.argv) < 2 or sys.argv[1] in ('-h', '--help'):
- print >> sys.stderr, 'Add a new project for testing to static analyzer'\
+ print >> sys.stderr, 'Add a new project for testing to the analyzer'\
'\nUsage: ', sys.argv[0],\
'project_ID <mode>\n' \
'mode: 0 for single file project, ' \
diff --git a/utils/analyzer/SATestBuild.py b/utils/analyzer/SATestBuild.py
index c735996c3b..26c519543e 100755
--- a/utils/analyzer/SATestBuild.py
+++ b/utils/analyzer/SATestBuild.py
@@ -3,8 +3,8 @@
"""
Static Analyzer qualification infrastructure.
-The goal is to test the analyzer against different projects, check for failures,
-compare results, and measure performance.
+The goal is to test the analyzer against different projects,
+check for failures, compare results, and measure performance.
Repository Directory will contain sources of the projects as well as the
information on how to build them and the expected output.
@@ -20,7 +20,8 @@ Note that the build tree must be inside the project dir.
To test the build of the analyzer one would:
- Copy over a copy of the Repository Directory. (TODO: Prefer to ensure that
- the build directory does not pollute the repository to min network traffic).
+ the build directory does not pollute the repository to min network
+ traffic).
- Build all projects, until error. Produce logs to report errors.
- Compare results.
@@ -60,69 +61,78 @@ import multiprocessing
#------------------------------------------------------------------------------
-def which(command, paths = None):
- """which(command, [paths]) - Look up the given command in the paths string
- (or the PATH environment variable, if unspecified)."""
+def which(command, paths=None):
+ """which(command, [paths]) - Look up the given command in the paths string
+ (or the PATH environment variable, if unspecified)."""
- if paths is None:
- paths = os.environ.get('PATH','')
+ if paths is None:
+ paths = os.environ.get('PATH', '')
- # Check for absolute match first.
- if os.path.exists(command):
- return command
+ # Check for absolute match first.
+ if os.path.exists(command):
+ return command
- # Would be nice if Python had a lib function for this.
- if not paths:
- paths = os.defpath
+ # Would be nice if Python had a lib function for this.
+ if not paths:
+ paths = os.defpath
- # Get suffixes to search.
- # On Cygwin, 'PATHEXT' may exist but it should not be used.
- if os.pathsep == ';':
- pathext = os.environ.get('PATHEXT', '').split(';')
- else:
- pathext = ['']
+ # Get suffixes to search.
+ # On Cygwin, 'PATHEXT' may exist but it should not be used.
+ if os.pathsep == ';':
+ pathext = os.environ.get('PATHEXT', '').split(';')
+ else:
+ pathext = ['']
+
+ # Search the paths...
+ for path in paths.split(os.pathsep):
+ for ext in pathext:
+ p = os.path.join(path, command + ext)
+ if os.path.exists(p):
+ return p
- # Search the paths...
- for path in paths.split(os.pathsep):
- for ext in pathext:
- p = os.path.join(path, command + ext)
- if os.path.exists(p):
- return p
+ return None
- return None
-# Make sure we flush the output after every print statement.
class flushfile(object):
+ """
+ Wrapper to flush the output after every print statement.
+ """
def __init__(self, f):
self.f = f
+
def write(self, x):
self.f.write(x)
self.f.flush()
+
sys.stdout = flushfile(sys.stdout)
+
def getProjectMapPath():
ProjectMapPath = os.path.join(os.path.abspath(os.curdir),
ProjectMapFile)
if not os.path.exists(ProjectMapPath):
print "Error: Cannot find the Project Map file " + ProjectMapPath +\
- "\nRunning script for the wrong directory?"
+ "\nRunning script for the wrong directory?"
sys.exit(-1)
return ProjectMapPath
+
def getProjectDir(ID):
return os.path.join(os.path.abspath(os.curdir), ID)
-def getSBOutputDirName(IsReferenceBuild) :
- if IsReferenceBuild == True :
+
+def getSBOutputDirName(IsReferenceBuild):
+ if IsReferenceBuild:
return SBOutputDirReferencePrefix + SBOutputDirName
- else :
+ else:
return SBOutputDirName
#------------------------------------------------------------------------------
# Configuration setup.
#------------------------------------------------------------------------------
+
# Find Clang for static analysis.
if 'CC' in os.environ:
Clang = os.environ['CC']
@@ -160,9 +170,10 @@ DiffsSummaryFileName = "diffs.txt"
SBOutputDirName = "ScanBuildResults"
SBOutputDirReferencePrefix = "Ref"
-# The name of the directory storing the cached project source. If this directory
-# does not exist, the download script will be executed. That script should
-# create the "CachedSource" directory and download the project source into it.
+# The name of the directory storing the cached project source. If this
+# directory does not exist, the download script will be executed.
+# That script should create the "CachedSource" directory and download the
+# project source into it.
CachedSourceDirName = "CachedSource"
# The name of the directory containing the source code that will be analyzed.
@@ -178,7 +189,7 @@ PatchfileName = "changes_for_analyzer.patch"
# The list of checkers used during analyzes.
# Currently, consists of all the non-experimental checkers, plus a few alpha
# checkers we don't want to regress on.
-Checkers=",".join([
+Checkers = ",".join([
"alpha.unix.SimpleStream",
"alpha.security.taint",
"cplusplus.NewDeleteLeaks",
@@ -197,46 +208,60 @@ Verbose = 1
# Test harness logic.
#------------------------------------------------------------------------------
-# Run pre-processing script if any.
+
def runCleanupScript(Dir, PBuildLogFile):
+ """
+ Run pre-processing script if any.
+ """
Cwd = os.path.join(Dir, PatchedSourceDirName)
ScriptPath = os.path.join(Dir, CleanupScript)
runScript(ScriptPath, PBuildLogFile, Cwd)
-# Run the script to download the project, if it exists.
+
def runDownloadScript(Dir, PBuildLogFile):
+ """
+ Run the script to download the project, if it exists.
+ """
ScriptPath = os.path.join(Dir, DownloadScript)
runScript(ScriptPath, PBuildLogFile, Dir)
-# Run the provided script if it exists.
+
def runScript(ScriptPath, PBuildLogFile, Cwd):
+ """
+ Run the provided script if it exists.
+ """
if os.path.exists(ScriptPath):
try:
if Verbose == 1:
print " Executing: %s" % (ScriptPath,)
- check_call("chmod +x '%s'" % ScriptPath, cwd = Cwd,
- stderr=PBuildLogFile,
- stdout=PBuildLogFile,
- shell=True)
- check_call("'%s'" % ScriptPath, cwd = Cwd, stderr=PBuildLogFile,
- stdout=PBuildLogFile,
- shell=True)
+ check_call("chmod +x '%s'" % ScriptPath, cwd=Cwd,
+ stderr=PBuildLogFile,
+ stdout=PBuildLogFile,
+ shell=True)
+ check_call("'%s'" % ScriptPath, cwd=Cwd,
+ stderr=PBuildLogFile,
+ stdout=PBuildLogFile,
+ shell=True)
except:
- print "Error: Running %s failed. See %s for details." % (ScriptPath,
- PBuildLogFile.name)
+ print "Error: Running %s failed. See %s for details." % (
+ ScriptPath, PBuildLogFile.name)
sys.exit(-1)
-# Download the project and apply the local patchfile if it exists.
+
def downloadAndPatch(Dir, PBuildLogFile):
+ """
+ Download the project and apply the local patchfile if it exists.
+ """
CachedSourceDirPath = os.path.join(Dir, CachedSourceDirName)
# If the we don't already have the cached source, run the project's
# download script to download it.
if not os.path.exists(CachedSourceDirPath):
- runDownloadScript(Dir, PBuildLogFile)
- if not os.path.exists(CachedSourceDirPath):
- print "Error: '%s' not found after download." % (CachedSourceDirPath)
- exit(-1)
+ runDownloadScript(Dir, PBuildLogFile)
+ if not os.path.exists(CachedSourceDirPath):
+ print "Error: '%s' not found after download." % (
+ CachedSourceDirPath)
+ exit(-1)
PatchedSourceDirPath = os.path.join(Dir, PatchedSourceDirName)
@@ -248,6 +273,7 @@ def downloadAndPatch(Dir, PBuildLogFile):
shutil.copytree(CachedSourceDirPath, PatchedSourceDirPath, symlinks=True)
applyPatch(Dir, PBuildLogFile)
+
def applyPatch(Dir, PBuildLogFile):
PatchfilePath = os.path.join(Dir, PatchfileName)
PatchedSourceDirPath = os.path.join(Dir, PatchedSourceDirName)
@@ -258,30 +284,33 @@ def applyPatch(Dir, PBuildLogFile):
print " Applying patch."
try:
check_call("patch -p1 < '%s'" % (PatchfilePath),
- cwd = PatchedSourceDirPath,
- stderr=PBuildLogFile,
- stdout=PBuildLogFile,
- shell=True)
+ cwd=PatchedSourceDirPath,
+ stderr=PBuildLogFile,
+ stdout=PBuildLogFile,
+ shell=True)
except:
print "Error: Patch failed. See %s for details." % (PBuildLogFile.name)
sys.exit(-1)
-# Build the project with scan-build by reading in the commands and
-# prefixing them with the scan-build options.
+
def runScanBuild(Dir, SBOutputDir, PBuildLogFile):
+ """
+ Build the project with scan-build by reading in the commands and
+ prefixing them with the scan-build options.
+ """
BuildScriptPath = os.path.join(Dir, BuildScript)
if not os.path.exists(BuildScriptPath):
print "Error: build script is not defined: %s" % BuildScriptPath
sys.exit(-1)
AllCheckers = Checkers
- if os.environ.has_key('SA_ADDITIONAL_CHECKERS'):
+ if 'SA_ADDITIONAL_CHECKERS' in os.environ:
AllCheckers = AllCheckers + ',' + os.environ['SA_ADDITIONAL_CHECKERS']
# Run scan-build from within the patched source directory.
SBCwd = os.path.join(Dir, PatchedSourceDirName)
- SBOptions = "--use-analyzer '%s' " % Clang
+ SBOptions = "--use-analyzer '%s' " % Clang
SBOptions += "-plist-html -o '%s' " % SBOutputDir
SBOptions += "-enable-checker " + AllCheckers + " "
SBOptions += "--keep-empty "
@@ -294,7 +323,7 @@ def runScanBuild(Dir, SBOutputDir, PBuildLogFile):
for Command in SBCommandFile:
Command = Command.strip()
if len(Command) == 0:
- continue;
+ continue
# If using 'make', auto imply a -jX argument
# to speed up analysis. xcodebuild will
# automatically use the maximum number of cores.
@@ -304,42 +333,45 @@ def runScanBuild(Dir, SBOutputDir, PBuildLogFile):
SBCommand = SBPrefix + Command
if Verbose == 1:
print " Executing: %s" % (SBCommand,)
- check_call(SBCommand, cwd = SBCwd, stderr=PBuildLogFile,
- stdout=PBuildLogFile,
- shell=True)
+ check_call(SBCommand, cwd=SBCwd,
+ stderr=PBuildLogFile,
+ stdout=PBuildLogFile,
+ shell=True)
except:
- print "Error: scan-build failed. See ",PBuildLogFile.name,\
+ print "Error: scan-build failed. See ", PBuildLogFile.name,\
" for details."
raise
+
def hasNoExtension(FileName):
(Root, Ext) = os.path.splitext(FileName)
- if ((Ext == "")) :
- return True
- return False
+ return (Ext == "")
+
def isValidSingleInputFile(FileName):
(Root, Ext) = os.path.splitext(FileName)
- if ((Ext == ".i") | (Ext == ".ii") |
- (Ext == ".c") | (Ext == ".cpp") |
- (Ext == ".m") | (Ext == "")) :
- return True
- return False
-
-# Get the path to the SDK for the given SDK name. Returns None if
-# the path cannot be determined.
+ return Ext in (".i", ".ii", ".c", ".cpp", ".m", "")
+
+
def getSDKPath(SDKName):
+ """
+ Get the path to the SDK for the given SDK name. Returns None if
+ the path cannot be determined.
+ """
if which("xcrun") is None:
return None
Cmd = "xcrun --sdk " + SDKName + " --show-sdk-path"
return check_output(Cmd, shell=True).rstrip()
-# Run analysis on a set of preprocessed files.
+
def runAnalyzePreprocessed(Dir, SBOutputDir, Mode):
+ """
+ Run analysis on a set of preprocessed files.
+ """
if os.path.exists(os.path.join(Dir, BuildScript)):
print "Error: The preprocessed files project should not contain %s" % \
- BuildScript
+ BuildScript
raise Exception()
CmdPrefix = Clang + " -cc1 "
@@ -348,17 +380,18 @@ def runAnalyzePreprocessed(Dir, SBOutputDir, Mode):
# with the OS X SDK.
SDKPath = getSDKPath("macosx")
if SDKPath is not None:
- CmdPrefix += "-isysroot " + SDKPath + " "
+ CmdPrefix += "-isysroot " + SDKPath + " "
CmdPrefix += "-analyze -analyzer-output=plist -w "
- CmdPrefix += "-analyzer-checker=" + Checkers +" -fcxx-exceptions -fblocks "
+ CmdPrefix += "-analyzer-checker=" + Checkers
+ CmdPrefix += " -fcxx-exceptions -fblocks "
- if (Mode == 2) :
+ if (Mode == 2):
CmdPrefix += "-std=c++11 "
PlistPath = os.path.join(Dir, SBOutputDir, "date")
- FailPath = os.path.join(PlistPath, "failures");
- os.makedirs(FailPath);
+ FailPath = os.path.join(PlistPath, "failures")
+ os.makedirs(FailPath)
for FullFileName in glob.glob(Dir + "/*"):
FileName = os.path.basename(FullFileName)
@@ -367,7 +400,7 @@ def runAnalyzePreprocessed(Dir, SBOutputDir, Mode):
# Only run the analyzes on supported files.
if (hasNoExtension(FileName)):
continue
- if (isValidSingleInputFile(FileName) == False):
+ if (not isValidSingleInputFile(FileName)):
print "Error: Invalid single input file %s." % (FullFileName,)
raise Exception()
@@ -378,44 +411,47 @@ def runAnalyzePreprocessed(Dir, SBOutputDir, Mode):
try:
if Verbose == 1:
print " Executing: %s" % (Command,)
- check_call(Command, cwd = Dir, stderr=LogFile,
- stdout=LogFile,
- shell=True)
+ check_call(Command, cwd=Dir, stderr=LogFile,
+ stdout=LogFile,
+ shell=True)
except CalledProcessError, e:
print "Error: Analyzes of %s failed. See %s for details." \
- "Error code %d." % \
- (FullFileName, LogFile.name, e.returncode)
+ "Error code %d." % (
+ FullFileName, LogFile.name, e.returncode)
Failed = True
finally:
LogFile.close()
# If command did not fail, erase the log file.
- if Failed == False:
- os.remove(LogFile.name);
+ if not Failed:
+ os.remove(LogFile.name)
+
def getBuildLogPath(SBOutputDir):
- return os.path.join(SBOutputDir, LogFolderName, BuildLogName)
+ return os.path.join(SBOutputDir, LogFolderName, BuildLogName)
+
def removeLogFile(SBOutputDir):
- BuildLogPath = getBuildLogPath(SBOutputDir)
- # Clean up the log file.
- if (os.path.exists(BuildLogPath)) :
- RmCommand = "rm '%s'" % BuildLogPath
- if Verbose == 1:
- print " Executing: %s" % (RmCommand,)
- check_call(RmCommand, shell=True)
+ BuildLogPath = getBuildLogPath(SBOutputDir)
+ # Clean up the log file.
+ if (os.path.exists(BuildLogPath)):
+ RmCommand = "rm '%s'" % BuildLogPath
+ if Verbose == 1:
+ print " Executing: %s" % (RmCommand,)
+ check_call(RmCommand, shell=True)
+
def buildProject(Dir, SBOutputDir, ProjectBuildMode, IsReferenceBuild):
TBegin = time.time()
BuildLogPath = getBuildLogPath(SBOutputDir)
print "Log file: %s" % (BuildLogPath,)
- print "Output directory: %s" %(SBOutputDir, )
+ print "Output directory: %s" % (SBOutputDir, )
removeLogFile(SBOutputDir)
# Clean up scan build results.
- if (os.path.exists(SBOutputDir)) :
+ if (os.path.exists(SBOutputDir)):
RmCommand = "rm -r '%s'" % SBOutputDir
if Verbose == 1:
print " Executing: %s" % (RmCommand,)
@@ -437,7 +473,8 @@ def buildProject(Dir, SBOutputDir, ProjectBuildMode, IsReferenceBuild):
normalizeReferenceResults(Dir, SBOutputDir, ProjectBuildMode)
print "Build complete (time: %.2f). See the log for more details: %s" % \
- ((time.time()-TBegin), BuildLogPath)
+ ((time.time() - TBegin), BuildLogPath)
+
def normalizeReferenceResults(Dir, SBOutputDir, ProjectBuildMode):
"""
@@ -452,15 +489,19 @@ def normalizeReferenceResults(Dir, SBOutputDir, ProjectBuildMode):
PathPrefix = Dir
if (ProjectBuildMode == 1):
PathPrefix = os.path.join(Dir, PatchedSourceDirName)
- Paths = [SourceFile[len(PathPrefix)+1:]\
- if SourceFile.startswith(PathPrefix)\
- else SourceFile for SourceFile in Data['files']]
+ Paths = [SourceFile[len(PathPrefix) + 1:]
+ if SourceFile.startswith(PathPrefix)
+ else SourceFile for SourceFile in Data['files']]
Data['files'] = Paths
plistlib.writePlist(Data, Plist)
-# A plist file is created for each call to the analyzer(each source file).
-# We are only interested on the once that have bug reports, so delete the rest.
+
def CleanUpEmptyPlists(SBOutputDir):
+ """
+ A plist file is created for each call to the analyzer(each source file).
+ We are only interested on the once that have bug reports,
+ so delete the rest.
+ """
for F in glob.glob(SBOutputDir + "/*/*.plist"):
P = os.path.join(SBOutputDir, F)
@@ -470,55 +511,66 @@ def CleanUpEmptyPlists(SBOutputDir):
os.remove(P)
continue
-# Given the scan-build output directory, checks if the build failed
-# (by searching for the failures directories). If there are failures, it
-# creates a summary file in the output directory.
+
def checkBuild(SBOutputDir):
+ """
+ Given the scan-build output directory, checks if the build failed
+ (by searching for the failures directories). If there are failures, it
+ creates a summary file in the output directory.
+
+ """
# Check if there are failures.
Failures = glob.glob(SBOutputDir + "/*/failures/*.stderr.txt")
- TotalFailed = len(Failures);
+ TotalFailed = len(Failures)
if TotalFailed == 0:
CleanUpEmptyPlists(SBOutputDir)
Plists = glob.glob(SBOutputDir + "/*/*.plist")
print "Number of bug reports (non-empty plist files) produced: %d" %\
- len(Plists)
- return;
+ len(Plists)
+ return
# Create summary file to display when the build fails.
- SummaryPath = os.path.join(SBOutputDir, LogFolderName, FailuresSummaryFileName)
+ SummaryPath = os.path.join(
+ SBOutputDir, LogFolderName, FailuresSummaryFileName)
if (Verbose > 0):
print " Creating the failures summary file %s" % (SummaryPath,)
with open(SummaryPath, "w+") as SummaryLog:
SummaryLog.write("Total of %d failures discovered.\n" % (TotalFailed,))
if TotalFailed > NumOfFailuresInSummary:
- SummaryLog.write("See the first %d below.\n"
- % (NumOfFailuresInSummary,))
+ SummaryLog.write("See the first %d below.\n" % (
+ NumOfFailuresInSummary,))
# TODO: Add a line "See the results folder for more."
Idx = 0
for FailLogPathI in Failures:
if Idx >= NumOfFailuresInSummary:
- break;
+ break
Idx += 1
- SummaryLog.write("\n-- Error #%d -----------\n" % (Idx,));
+ SummaryLog.write("\n-- Error #%d -----------\n" % (Idx,))
with open(FailLogPathI, "r") as FailLogI:
- shutil.copyfileobj(FailLogI, SummaryLog);
+ shutil.copyfileobj(FailLogI, SummaryLog)
print "Error: analysis failed. See ", SummaryPath
sys.exit(-1)
-# Auxiliary object to discard stdout.
+
class Discarder(object):
+ """
+ Auxiliary object to discard stdout.
+ """
def write(self, text):
- pass # do nothing
-
-# Compare the warnings produced by scan-build.
-# Strictness defines the success criteria for the test:
-# 0 - success if there are no crashes or analyzer failure.
-# 1 - success if there are no difference in the number of reported bugs.
-# 2 - success if all the bug reports are identical.
-def runCmpResults(Dir, Strictness = 0):
+ pass # do nothing
+
+
+def runCmpResults(Dir, Strictness=0):
+ """
+ Compare the warnings produced by scan-build.
+ Strictness defines the success criteria for the test:
+ 0 - success if there are no crashes or analyzer failure.
+ 1 - success if there are no difference in the number of reported bugs.
+ 2 - success if all the bug reports are identical.
+ """
TBegin = time.time()
RefDir = os.path.join(Dir, SBOutputDirReferencePrefix + SBOutputDirName)
@@ -559,29 +611,35 @@ def runCmpResults(Dir, Strictness = 0):
DiffsPath = os.path.join(NewDir, DiffsSummaryFileName)
PatchedSourceDirPath = os.path.join(Dir, PatchedSourceDirName)
Opts = CmpRuns.CmpOptions(DiffsPath, "", PatchedSourceDirPath)
- # Discard everything coming out of stdout (CmpRun produces a lot of them).
+ # Discard everything coming out of stdout
+ # (CmpRun produces a lot of them).
OLD_STDOUT = sys.stdout
sys.stdout = Discarder()
# Scan the results, delete empty plist files.
NumDiffs, ReportsInRef, ReportsInNew = \
CmpRuns.dumpScanBuildResultsDiff(RefDir, NewDir, Opts, False)
sys.stdout = OLD_STDOUT
- if (NumDiffs > 0) :
+ if (NumDiffs > 0):
print "Warning: %r differences in diagnostics. See %s" % \
(NumDiffs, DiffsPath,)
if Strictness >= 2 and NumDiffs > 0:
print "Error: Diffs found in strict mode (2)."
sys.exit(-1)
elif Strictness >= 1 and ReportsInRef != ReportsInNew:
- print "Error: The number of results are different in strict mode (1)."
+ print "Error: The number of results are different in "\
+ "strict mode (1)."
sys.exit(-1)
- print "Diagnostic comparison complete (time: %.2f)." % (time.time()-TBegin)
+ print "Diagnostic comparison complete (time: %.2f)." % (
+ time.time() - TBegin)
return (NumDiffs > 0)
+
def cleanupReferenceResults(SBOutputDir):
- # Delete html, css, and js files from reference results. These can
- # include multiple copies of the benchmark source and so get very large.
+ """
+ Delete html, css, and js files from reference results. These can
+ include multiple copies of the benchmark source and so get very large.
+ """
Extensions = ["html", "css", "js"]
for E in Extensions:
for F in glob.glob("%s/*/*.%s" % (SBOutputDir, E)):
@@ -592,6 +650,7 @@ def cleanupReferenceResults(SBOutputDir):
# Remove the log file. It leaks absolute path names.
removeLogFile(SBOutputDir)
+
def updateSVN(Mode, PMapFile):
"""
svn delete or svn add (depending on `Mode`) all folders defined in the file
@@ -625,7 +684,8 @@ def updateSVN(Mode, PMapFile):
print "Error: SVN update failed."
sys.exit(-1)
-def testProject(ID, ProjectBuildMode, IsReferenceBuild=False, Strictness = 0):
+
+def testProject(ID, ProjectBuildMode, IsReferenceBuild=False, Strictness=0):
print " \n\n--- Building project %s" % (ID,)
TBegin = time.time()
@@ -648,72 +708,80 @@ def testProject(ID, ProjectBuildMode, IsReferenceBuild=False, Strictness = 0):
runCmpResults(Dir, Strictness)
print "Completed tests for project %s (time: %.2f)." % \
- (ID, (time.time()-TBegin))
+ (ID, (time.time() - TBegin))
+
def isCommentCSVLine(Entries):
- # Treat CSV lines starting with a '#' as a comment.
+ """
+ Treat CSV lines starting with a '#' as a comment.
+ """
return len(Entries) > 0 and Entries[0].startswith("#")
+
def projectFileHandler():
return open(getProjectMapPath(), "rb")
+
def iterateOverProjects(PMapFile):
"""
Iterate over all projects defined in the project file handler `PMapFile`
from the start.
"""
PMapFile.seek(0)
- try:
- for I in csv.reader(PMapFile):
- if (isCommentCSVLine(I)):
- continue
- yield I
- except:
- print "Error occurred. Premature termination."
- raise
+ for I in csv.reader(PMapFile):
+ if (isCommentCSVLine(I)):
+ continue
+ yield I
+
def validateProjectFile(PMapFile):
"""
Validate project file.
"""
for I in iterateOverProjects(PMapFile):
- if (len(I) != 2) :
+ if (len(I) != 2):
print "Error: Rows in the ProjectMapFile should have 2 entries."
raise Exception()
if (not ((I[1] == "0") | (I[1] == "1") | (I[1] == "2"))):
print "Error: Second entry in the ProjectMapFile should be 0" \
- " (single file), 1 (project), or 2(single file c++11)."
+ " (single file), 1 (project), or 2(single file c++11)."
raise Exception()
-def testAll(IsReferenceBuild = False, UpdateSVN = False, Strictness = 0):
+
+def testAll(IsReferenceBuild=False, UpdateSVN=False, Strictness=0):
with projectFileHandler() as PMapFile:
validateProjectFile(PMapFile)
# When we are regenerating the reference results, we might need to
# update svn. Remove reference results from SVN.
- if UpdateSVN == True:
- assert(IsReferenceBuild == True);
- updateSVN("delete", PMapFile);
+ if UpdateSVN:
+ assert(IsReferenceBuild)
+ updateSVN("delete", PMapFile)
# Test the projects.
for (ProjName, ProjBuildMode) in iterateOverProjects(PMapFile):
- testProject(ProjName, int(ProjBuildMode), IsReferenceBuild, Strictness)
+ testProject(
+ ProjName, int(ProjBuildMode), IsReferenceBuild, Strictness)
# Re-add reference results to SVN.
- if UpdateSVN == True:
- updateSVN("add", PMapFile);
+ if UpdateSVN:
+ updateSVN("add", PMapFile)
+
if __name__ == '__main__':
# Parse command line arguments.
- Parser = argparse.ArgumentParser(description='Test the Clang Static Analyzer.')
+ Parser = argparse.ArgumentParser(
+ description='Test the Clang Static Analyzer.')
Parser.add_argument('--strictness', dest='strictness', type=int, default=0,
- help='0 to fail on runtime errors, 1 to fail when the number\
- of found bugs are different from the reference, 2 to \
- fail on any difference from the reference. Default is 0.')
- Parser.add_argument('-r', dest='regenerate', action='store_true', default=False,
- help='Regenerate reference output.')
+ help='0 to fail on runtime errors, 1 to fail when the \
+ number of found bugs are different from the \
+ reference, 2 to fail on any difference from the \
+ reference. Default is 0.')
+ Parser.add_argument('-r', dest='regenerate', action='store_true',
+ default=False, help='Regenerate reference output.')
Parser.add_argument('-rs', dest='update_reference', action='store_true',
- default=False, help='Regenerate reference output and update svn.')
+ default=False,
+ help='Regenerate reference output and update svn.')
Args = Parser.parse_args()
IsReference = False
diff --git a/utils/analyzer/SATestUpdateDiffs.py b/utils/analyzer/SATestUpdateDiffs.py
index df836b10f8..9b5b7064ce 100755
--- a/utils/analyzer/SATestUpdateDiffs.py
+++ b/utils/analyzer/SATestUpdateDiffs.py
@@ -11,18 +11,23 @@ import os
import sys
Verbose = 1
+
+
def runCmd(Command):
if Verbose:
print "Executing %s" % Command
check_call(Command, shell=True)
+
def updateReferenceResults(ProjName, ProjBuildMode):
ProjDir = SATestBuild.getProjectDir(ProjName)
- RefResultsPath = os.path.join(ProjDir,
- SATestBuild.getSBOutputDirName(IsReferenceBuild=True))
- CreatedResultsPath = os.path.join(ProjDir,
- SATestBuild.getSBOutputDirName(IsReferenceBuild=False))
+ RefResultsPath = os.path.join(
+ ProjDir,
+ SATestBuild.getSBOutputDirName(IsReferenceBuild=True))
+ CreatedResultsPath = os.path.join(
+ ProjDir,
+ SATestBuild.getSBOutputDirName(IsReferenceBuild=False))
if not os.path.exists(CreatedResultsPath):
print >> sys.stderr, "New results not found, was SATestBuild.py "\
@@ -36,29 +41,34 @@ def updateReferenceResults(ProjName, ProjBuildMode):
runCmd('cp -r "%s" "%s"' % (CreatedResultsPath, RefResultsPath,))
# Run cleanup script.
- with open(SATestBuild.getBuildLogPath(RefResultsPath), "wb+") as PBuildLogFile:
+ BuildLogPath = SATestBuild.getBuildLogPath(RefResultsPath)
+ with open(BuildLogPath, "wb+") as PBuildLogFile:
SATestBuild.runCleanupScript(ProjDir, PBuildLogFile)
- SATestBuild.normalizeReferenceResults(ProjDir, RefResultsPath, ProjBuildMode)
+ SATestBuild.normalizeReferenceResults(
+ ProjDir, RefResultsPath, ProjBuildMode)
# Clean up the generated difference results.
SATestBuild.cleanupReferenceResults(RefResultsPath)
# Remove the created .diffs file before adding.
- runCmd('rm -f "%s/*/%s"' % (RefResultsPath, SATestBuild.DiffsSummaryFileName))
+ runCmd('rm -f "%s/*/%s"' % (
+ RefResultsPath, SATestBuild.DiffsSummaryFileName))
runCmd('git add "%s"' % (RefResultsPath,))
+
def main(argv):
if len(argv) == 2 and argv[1] in ('-h', '--help'):
print >> sys.stderr, "Update static analyzer reference results based "\
"\non the previous run of SATestBuild.py.\n"\
- "\nN.B.: Assumes that SATestBuild.py was just run."
+ "\nN.B.: Assumes that SATestBuild.py was just run"
sys.exit(-1)
with SATestBuild.projectFileHandler() as f:
for (ProjName, ProjBuildMode) in SATestBuild.iterateOverProjects(f):
updateReferenceResults(ProjName, int(ProjBuildMode))
+
if __name__ == '__main__':
main(sys.argv)
diff --git a/utils/analyzer/SumTimerInfo.py b/utils/analyzer/SumTimerInfo.py
index 0c3585bbc2..50e1cb854f 100644
--- a/utils/analyzer/SumTimerInfo.py
+++ b/utils/analyzer/SumTimerInfo.py
@@ -5,11 +5,8 @@ Script to Summarize statistics in the scan-build output.
Statistics are enabled by passing '-internal-stats' option to scan-build
(or '-analyzer-stats' to the analyzer).
-
"""
-import string
-from operator import itemgetter
import sys
if __name__ == '__main__':
@@ -31,44 +28,42 @@ if __name__ == '__main__':
NumInlinedCallSites = 0
NumBifurcatedCallSites = 0
MaxCFGSize = 0
- Mode = 1
for line in f:
- if ("Miscellaneous Ungrouped Timers" in line) :
- Mode = 1
- if (("Analyzer Total Time" in line) and (Mode == 1)) :
- s = line.split()
- Time = Time + float(s[6])
- Count = Count + 1
- if (float(s[6]) > MaxTime) :
- MaxTime = float(s[6])
- if ((("warning generated." in line) or ("warnings generated" in line)) and Mode == 1) :
- s = line.split()
- Warnings = Warnings + int(s[0])
- if (("The # of functions analysed (as top level)" in line) and (Mode == 1)) :
- s = line.split()
- FunctionsAnalyzed = FunctionsAnalyzed + int(s[0])
- if (("The % of reachable basic blocks" in line) and (Mode == 1)) :
- s = line.split()
- ReachableBlocks = ReachableBlocks + int(s[0])
- if (("The # of times we reached the max number of steps" in line) and (Mode == 1)) :
- s = line.split()
- ReachedMaxSteps = ReachedMaxSteps + int(s[0])
- if (("The maximum number of basic blocks in a function" in line) and (Mode == 1)) :
- s = line.split()
- if (MaxCFGSize < int(s[0])) :
- MaxCFGSize = int(s[0])
- if (("The # of steps executed" in line) and (Mode == 1)) :
- s = line.split()
- NumSteps = NumSteps + int(s[0])
- if (("The # of times we inlined a call" in line) and (Mode == 1)) :
- s = line.split()
- NumInlinedCallSites = NumInlinedCallSites + int(s[0])
- if (("The # of times we split the path due to imprecise dynamic dispatch info" in line) and (Mode == 1)) :
- s = line.split()
- NumBifurcatedCallSites = NumBifurcatedCallSites + int(s[0])
- if ((") Total" in line) and (Mode == 1)) :
- s = line.split()
- TotalTime = TotalTime + float(s[6])
+ if ("Analyzer Total Time" in line):
+ s = line.split()
+ Time = Time + float(s[6])
+ Count = Count + 1
+ if (float(s[6]) > MaxTime):
+ MaxTime = float(s[6])
+ if ("warning generated." in line) or ("warnings generated" in line):
+ s = line.split()
+ Warnings = Warnings + int(s[0])
+ if "The # of functions analysed (as top level)" in line:
+ s = line.split()
+ FunctionsAnalyzed = FunctionsAnalyzed + int(s[0])
+ if "The % of reachable basic blocks" in line:
+ s = line.split()
+ ReachableBlocks = ReachableBlocks + int(s[0])
+ if "The # of times we reached the max number of steps" in line:
+ s = line.split()
+ ReachedMaxSteps = ReachedMaxSteps + int(s[0])
+ if "The maximum number of basic blocks in a function" in line:
+ s = line.split()
+ if MaxCFGSize < int(s[0]):
+ MaxCFGSize = int(s[0])
+ if "The # of steps executed" in line:
+ s = line.split()
+ NumSteps = NumSteps + int(s[0])
+ if "The # of times we inlined a call" in line:
+ s = line.split()
+ NumInlinedCallSites = NumInlinedCallSites + int(s[0])
+ if "The # of times we split the path due \
+ to imprecise dynamic dispatch info" in line:
+ s = line.split()
+ NumBifurcatedCallSites = NumBifurcatedCallSites + int(s[0])
+ if ") Total" in line:
+ s = line.split()
+ TotalTime = TotalTime + float(s[6])
print "TU Count %d" % (Count)
print "Time %f" % (Time)
@@ -77,7 +72,8 @@ if __name__ == '__main__':
print "Reachable Blocks %d" % (ReachableBlocks)
print "Reached Max Steps %d" % (ReachedMaxSteps)
print "Number of Steps %d" % (NumSteps)
- print "Number of Inlined calls %d (bifurcated %d)" % (NumInlinedCallSites, NumBifurcatedCallSites)
+ print "Number of Inlined calls %d (bifurcated %d)" % (
+ NumInlinedCallSites, NumBifurcatedCallSites)
print "MaxTime %f" % (MaxTime)
print "TotalTime %f" % (TotalTime)
print "Max CFG Size %d" % (MaxCFGSize)
diff --git a/utils/analyzer/ubiviz b/utils/analyzer/ubiviz
index 9d821c3c10..137e130fe7 100755
--- a/utils/analyzer/ubiviz
+++ b/utils/analyzer/ubiviz
@@ -5,69 +5,72 @@
# This file is distributed under the University of Illinois Open Source
# License. See LICENSE.TXT for details.
#
-##===----------------------------------------------------------------------===##
+##===--------------------------------------------------------------------===##
#
# This script reads visualization data emitted by the static analyzer for
# display in Ubigraph.
#
-##===----------------------------------------------------------------------===##
+##===--------------------------------------------------------------------===##
import xmlrpclib
import sys
+
def Error(message):
print >> sys.stderr, 'ubiviz: ' + message
sys.exit(1)
+
def StreamData(filename):
- file = open(filename)
- for ln in file:
- yield eval(ln)
- file.close()
+ file = open(filename)
+ for ln in file:
+ yield eval(ln)
+ file.close()
+
def Display(G, data):
- action = data[0]
- if action == 'vertex':
- vertex = data[1]
- G.new_vertex_w_id(vertex)
- for attribute in data[2:]:
- G.set_vertex_attribute(vertex, attribute[0], attribute[1])
- elif action == 'edge':
- src = data[1]
- dst = data[2]
- edge = G.new_edge(src,dst)
- for attribute in data[3:]:
- G.set_edge_attribute(edge, attribute[0], attribute[1])
- elif action == "vertex_style":
- style_id = data[1]
- parent_id = data[2]
- G.new_vertex_style_w_id(style_id, parent_id)
- for attribute in data[3:]:
- G.set_vertex_style_attribute(style_id, attribute[0], attribute[1])
- elif action == "vertex_style_attribute":
- style_id = data[1]
- for attribute in data[2:]:
- G.set_vertex_style_attribute(style_id, attribute[0], attribute[1])
- elif action == "change_vertex_style":
- vertex_id = data[1]
- style_id = data[2]
- G.change_vertex_style(vertex_id,style_id)
+ action = data[0]
+ if action == 'vertex':
+ vertex = data[1]
+ G.new_vertex_w_id(vertex)
+ for attribute in data[2:]:
+ G.set_vertex_attribute(vertex, attribute[0], attribute[1])
+ elif action == 'edge':
+ src = data[1]
+ dst = data[2]
+ edge = G.new_edge(src, dst)
+ for attribute in data[3:]:
+ G.set_edge_attribute(edge, attribute[0], attribute[1])
+ elif action == "vertex_style":
+ style_id = data[1]
+ parent_id = data[2]
+ G.new_vertex_style_w_id(style_id, parent_id)
+ for attribute in data[3:]:
+ G.set_vertex_style_attribute(style_id, attribute[0], attribute[1])
+ elif action == "vertex_style_attribute":
+ style_id = data[1]
+ for attribute in data[2:]:
+ G.set_vertex_style_attribute(style_id, attribute[0], attribute[1])
+ elif action == "change_vertex_style":
+ vertex_id = data[1]
+ style_id = data[2]
+ G.change_vertex_style(vertex_id, style_id)
+
def main(args):
- if len(args) == 0:
- Error('no input files')
+ if len(args) == 0:
+ Error('no input files')
- server = xmlrpclib.Server('http://127.0.0.1:20738/RPC2')
- G = server.ubigraph
+ server = xmlrpclib.Server('http://127.0.0.1:20738/RPC2')
+ G = server.ubigraph
- for arg in args:
- G.clear()
- for x in StreamData(arg):
- Display(G,x)
+ for arg in args:
+ G.clear()
+ for x in StreamData(arg):
+ Display(G, x)
- sys.exit(0)
+ sys.exit(0)
if __name__ == '__main__':
main(sys.argv[1:])
-