/usr/share/pyshared/PyMetrics/processargs.py is in pymetrics 0.8.1-6.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 | """ Process command line arguments.
Usage:
>>> pa = ProcessArgs( 'file1.py', 'file2.py', '/home/files/file3.py' )
>>> pa = ProcessArgs( "inFile1.py", sqlFileName='sqlF1.sql', genCsvSw=False,genKwCntSw=True )
>>> pa = ProcessArgs() #doctest +NORMALIZE_WHITESPACE +ELLIPSIS
python PyMetrics [ options ] pgm1.py [ pgm2.py ... ]
<BLANKLINE>
Complexity metrics are computed for the Python input files
pgm1.py, pgm2.py, etc. At least one file name is required,
else this message appears.
<BLANKLINE>
Three types of output can be produced:
<BLANKLINE>
* Standard output for a quick summary of the main metrics.
* A text file containing SQL commands necessary to build a SQL table
in the database of your choice.
* A text file containing Comma-Separated Values (CSV) formatted data
necessary to load into most spreadsheet programs.
PLEASE NOTE: multi-line literals have the new-line character
replaced with the character "\\n" in the output text.
<BLANKLINE>
Capitalized options negate the default option.
<BLANKLINE>
options:
--version show program's version number and exit
-h, --help show this help message and exit
-s SQLFILENAME, --sql=SQLFILENAME
name of output SQL command file. (Default is
metricData.sql)
-t SQLTOKENTABLENAME, --tokentable=SQLTOKENTABLENAME
name of output SQL token table. (Default is
metricTokens)
-m SQLMETRICSTABLENAME, --metricstable=SQLMETRICSTABLENAME
name of output SQL metrics table. (Default is
metricData)
-c CSVFILENAME, --csv=CSVFILENAME
name of output CSV data file. (Default is
metricData.csv)
-f INFILELIST, --files=INFILELIST
File containing list of path names to modules for
analysis.
-i INCLUDEMETRICSSTR, --include=INCLUDEMETRICSSTR
list of metrics to include in run. This is a comma
separated list of metric module names with no
whitespace. Optionally, you can specify the class name
of the metric by following the module name with a
colon (:) and the metric class name. (Default metrics
are 'simple:SimpleMetric,mccabe:McCabeMetric,
sloc:SLOCMetric'. Default metric class name for metric
module 'wxYz' is 'WxYzMetric' when only module name
given -- note capitalized metric class name.)
-l LIBNAME, --library=LIBNAME
user-defined name applied to collection of modules
(Default is '')
-e, --exists assume SQL tables exist and does not generate creation
code. Using this option sets option -N. (Default is
False)
-N, --noold create new command output files and tables after
deleting old results, if any. Ignored if -e is set.
(Default is False)
-B, --nobasic suppress production of Basic metrics (Default is
False)
-S, --nosql suppress production of output SQL command text file.
(Default is False)
-C, --nocsv suppress production of CSV output text file. (Default
is False)
-H, --noheadings suppress heading line in csv file. (Default is False)
-k, --kwcnt generate keyword counts. (Default is False)
-K, --nokwcnt suppress keyword counts. (Default is True)
-q, --quiet suppress normal summary output to stdout. (Default is
False)
-z, --zero display zero or empty values in output to stdout.
(Default is to suppress zero/empty output)
-v, --verbose Produce verbose output - more -v's produce more
output. (Default is no verbose output to stdout)
-d, --debug Provide debug output, not usually generated - internal
use only
<BLANKLINE>
No program file names given.
<BLANKLINE>
$Id: processargs.py,v 1.4 2008/07/24 04:28:12 rcharney Exp $
"""
__version__ = "$Revision: 1.3 $"[11:-2]
__author__ = 'Reg. Charney <pymetrics@charneyday.com>'
import sys
from optparse import OptionParser, BadOptionError
from doctestsw import *
usageStr = """python PyMetrics [ options ] pgm1.py [ pgm2.py ... ]
Complexity metrics are computed for the Python input files
pgm1.py, pgm2.py, etc. At least one file name is required,
else this message appears.
Three types of output can be produced:
* Standard output for a quick summary of the main metrics.
* A text file containing SQL commands necessary to build a SQL table
in the database of your choice.
* A text file containing Comma-Separated Values (CSV) formatted data
necessary to load into most spreadsheet programs.
PLEASE NOTE: multi-line literals have the new-line character
replaced with the character "\\n" in the output text.
Capitalized options negate the default option.
"""
class PyMetricsOptionParser( OptionParser ):
""" Subclass OptionParser so I can override default error handler."""
def __init__( self, *args, **kwds ):
""" Just call super class's __init__ since we aren't making changes here."""
OptionParser.__init__( self, *args, **kwds )
def error( self, msg ):
""" Explicitly raise BadOptionError so calling program can handle it."""
raise BadOptionError( msg )
class ProcessArgsError( Exception ): pass
class ProcessArgs( object ):
""" Process command line arguments."""
def __init__( self,
*pArgs,
**pKwds
):
""" Initial processing of arguments."""
# precedence for defaults, parameters, and command line arguments/keywords
# is:
#
# command line parameters/keywords take precedence over
# parameters used to instantiate ProcessArgs that takes precedence over
# default values for keywords.
#
# This implies we set completed options with defaults first
# then override completed options with parameters
# then override completed options with command line args/keywords
#
# default values for possible parameters
libName = ''
sqlFileName = "metricData.sql"
sqlTokenTableName = "metricTokens"
sqlMetricsTableName = "metricData"
csvFileName = "metricData.csv"
inFileList = None
includeMetricsStr = 'simple:SimpleMetric,mccabe:McCabeMetric,sloc:SLOCMetric'
excludeMetricsStr = None
debugSw = False
debugSw = False
quietSw = False
zeroSw = False
genBasicSw = True
genKwCntSw = False
genSqlSw = True
genCsvSw = True
genHdrSw = True
genAppendSw = True
genNewSw = False
genExistsSw = False
verbose = 0
self.__dict__.update( locals() )
del( self.__dict__['self'] ) # remove recursive self from self.__dict__
self.__dict__.update( pKwds )
del( self.__dict__['pKwds'] ) # remove redundant pKwds in self.__dict__
# set up option parser
parser = PyMetricsOptionParser( '', version="%prog 0.8.1" )
parser.add_option("-s", "--sql",
dest="sqlFileName",
default=self.sqlFileName,
help="name of output SQL command file. (Default is %s)" % self.sqlFileName )
parser.add_option("-t", "--tokentable",
dest="sqlTokenTableName",
default=self.sqlTokenTableName,
help="name of output SQL token table. (Default is %s)" % self.sqlTokenTableName )
parser.add_option("-m", "--metricstable",
dest="sqlMetricsTableName",
default=self.sqlMetricsTableName,
help="name of output SQL metrics table. (Default is %s)" % self.sqlMetricsTableName )
parser.add_option("-c", "--csv",
dest="csvFileName",
default=self.csvFileName,
help="name of output CSV data file. (Default is %s)" % self.csvFileName )
parser.add_option("-f", "--files",
dest="inFileList",
default=self.inFileList,
help="File containing list of path names to modules for analysis." )
parser.add_option("-i", "--include",
dest="includeMetricsStr",
default=self.includeMetricsStr,
help="list of metrics to include in run. This is a comma separated list of metric module names with no whitespace. Optionally, you can specify the class name of the metric by following the module name with a colon (:) and the metric class name. (Default metrics are 'simple:SimpleMetric,mccabe:McCabeMetric,sloc:SLOCMetric'. Default metric class name for metric module 'wxYz' is 'WxYzMetric' when only module name given -- note capitalized metric class name.)" )
parser.add_option("-l", "--library",
dest="libName",
default=self.libName,
help="user-defined name applied to collection of modules (Default is '')" )
parser.add_option("-e", "--exists",
action="store_true",
dest="genExistsSw",
default=self.genExistsSw,
help="assume SQL tables exist and does not generate creation code. Using this option sets option -N. (Default is %s)" % (self.genExistsSw) )
parser.add_option("-N", "--noold",
action="store_true",
dest="genNewSw",
default=self.genNewSw,
help="create new command output files and tables after deleting old results, if any. Ignored if -e is set. (Default is %s)" % (self.genNewSw) )
parser.add_option("-B", "--nobasic",
action="store_false",
dest="genBasicSw",
default=self.genBasicSw,
help="suppress production of Basic metrics (Default is %s)" % (not self.genBasicSw) )
parser.add_option("-S", "--nosql",
action="store_false",
dest="genSqlSw",
default=self.genSqlSw,
help="suppress production of output SQL command text file. (Default is %s)" % (not self.genSqlSw) )
parser.add_option("-C", "--nocsv",
action="store_false",
dest="genCsvSw",
default=self.genCsvSw,
help="suppress production of CSV output text file. (Default is %s)" % (not self.genCsvSw) )
parser.add_option("-H", "--noheadings",
action="store_false",
dest="genHdrSw",
default=self.genHdrSw,
help="suppress heading line in csv file. (Default is %s)" % (not self.genHdrSw) )
parser.add_option("-k", "--kwcnt",
action="store_true",
dest="genKwCntSw",
default=self.genKwCntSw,
help="generate keyword counts. (Default is %s)" % (self.genKwCntSw,) )
parser.add_option("-K", "--nokwcnt",
action="store_false",
dest="genKwCntSw",
default=self.genKwCntSw,
help="suppress keyword counts. (Default is %s)" % (not self.genKwCntSw) )
parser.add_option("-q", "--quiet",
action="store_true",
dest="quietSw",
default=self.quietSw,
help="suppress normal summary output to stdout. (Default is %s)" % (self.quietSw) )
parser.add_option("-z", "--zero",
action="store_true",
dest="zeroSw",
default=self.zeroSw,
help="display zero or empty values in output to stdout. (Default is to suppress zero/empty output)" )
parser.add_option("-v", "--verbose",
action="count",
dest="verbose",
default=self.verbose,
help="Produce verbose output - more -v's produce more output. (Default is no verbose output to stdout)")
parser.add_option("-d", "--debug",
action="store_true",
dest="debugSw",
default=self.debugSw,
help="Provide debug output, not usually generated - internal use only")
# parse the command line/arguments for this instance
try:
(options, args) = parser.parse_args()
except BadOptionError, e:
sys.stderr.writelines( "\nBadOptionError: %s\n" % str( e ) )
sys.stderr.writelines( "\nThe valid options are:\n\n" )
sys.stderr.writelines( parser.format_help() )
sys.exit( 1 )
# augment parameter values from instantiation with
# command line values.
# the command line parameter values take precidence
# over values in program.
args.extend( pArgs )
# convert command line arguments into instance values
self.__dict__.update( options.__dict__ )
if self.inFileList:
try:
inF = open( self.inFileList )
files = inF.read().split()
inF.close()
args.extend( files )
except IOError, e:
raise ProcessArgsError( e )
self.inFileNames = args
self.includeMetrics = self.processIncludeMetrics( self.includeMetricsStr )
if len( args ) < 1:
print usageStr
print parser.format_help()
e = "No program file names given.\n"
# because of what I believe to be a bug in the doctest module,
# which makes it mishandle exceptions, I have 'faked' the handling
# of raising an exception and just return
if doctestSw:
print e
return
else:
raise ProcessArgsError( e )
so = None
if self.genSqlSw and self.sqlFileName:
# Try opening command file for input. If OK, then file exists.
# Else, the commamd file does not exist to create SQL table and
# this portion of the command file must be generated as if new
# table was to be created.
#
# NOTE: This assumption can be dangerous. If the table does exist
# but the command file is out of sync with the table, then a valid
# table can be deleted and recreated, thus losing the old data.
# The workaround for this is to examine the SQL database for the
# table and only create the table, if needed.
try:
if self.sqlFileName:
self.so = open( self.sqlFileName, "r" )
self.so.close()
except IOError:
self.genNewSw = True
try:
mode = "a"
if self.genNewSw:
mode = "w"
so = open( self.sqlFileName, mode ) # check to see that we can write file
so.close()
except IOError, e:
sys.stderr.writelines( str(e) + " -- No SQL command file will be generated\n" )
self.genSqlSw = False
so = None
co = None
if self.genCsvSw and self.csvFileName:
try:
mode = "a"
if self.genNewSw:
mode = "w"
co = open( self.csvFileName, mode ) # check we will be able to write file
co.close()
except IOError, e:
sys.stderr.writelines( str(e) + " -- No CSV output file will be generated\n" )
self.genCsvSw = False
co = None
if self.genExistsSw:
# Assuming that table already exists, means concatenating
# data is not needed - we only want new data in SQL command file.
self.genNewSw = True
def conflictHandler( self, *args, **kwds ):
print "args=%s" % args
print "kwds=%s" % kwds
def processIncludeMetrics( self, includeMetricsStr ):
includeMetrics = []
try:
metricList = includeMetricsStr.split( ',' )
for a in metricList:
s = a.split( ':' )
if len( s ) == 2: # both metric class and module name given
includeMetrics.append( s )
elif len( s ) == 1:
# only the module name given. Generate default metric
# class name by capitalizing first letter of module
# name and appending "Metric" so the default metric
# class name for module wxYz is WxYzMetric.
if s[0]:
defName = s[0][0].upper() + s[0][1:] + 'Metric'
includeMetrics.append( (s[0], defName) )
else:
raise ProcessArgsError("Missing metric module name")
else:
raise ProcessArgsError("Malformed items in includeMetric string")
except AttributeError, e:
e = ( "Invalid list of metric names: %s" %
includeMetricsStr )
raise ProcessArgsError( e )
return includeMetrics
def testpa( pa ):
""" Test of ProcessArgs.
Usage:
>>> pa=ProcessArgs('inFile.py')
>>> testpa(pa) #doctest: +NORMALIZE_WHITESPACE +ELLIPSIS
Arguments processed:
sqlFileName=metricData.sql
sqlTokenTableName=metricTokens
sqlMetricsTableName=metricData
csvFileName=metricData.csv
Include Metric Modules=simple:SimpleMetric,mccabe:McCabeMetric
quietSw=False
genCsvSw=True
genHdrSw=True
genKwCntSw=False
verbose=...
Metrics to be used are:
Module simple contains metric class SimpleMetric
Module mccabe contains metric class McCabeMetric
Input files:
inFile.py
>>>
"""
print """
Arguments processed:
\tsqlFileName=%s
\tsqlTokenTableName=%s
\tsqlMetricsTableName=%s
\tcsvFileName=%s
\tinclude Metric Modules=%s
\tquietSw=%s
\tgenNewSw=%s
\tgenExistsSw=%s
\tgenSqlSw=%s
\tgenCsvSw=%s
\tgenHdrSw=%s
\tgenKwCntSw=%s
\tverbose=%s""" % (
pa.sqlFileName,
pa.sqlTokenTableName,
pa.sqlMetricsTableName,
pa.csvFileName,
pa.includeMetricsStr,
pa.quietSw,
pa.genNewSw,
pa.genExistsSw,
pa.genSqlSw,
pa.genCsvSw,
pa.genHdrSw,
pa.genKwCntSw,
pa.verbose)
print "Metrics to be used are:"
for m,n in pa.includeMetrics:
print "\tModule %s contains metric class %s" % (m,n)
if pa.inFileNames:
print "Input files:"
for f in pa.inFileNames:
print "\t%s" % f
if __name__ == "__main__":
# ignore doctestsw.doctestSw if this is run as a standalone
# module. Instead, look at the first argument on the command
# line. If it is "doctest", set doctestSw = True and delete
# the parameter "doctest" from sys.argv, thus leaving things
# as _normal_.
if len(sys.argv) > 1 and sys.argv[1] == 'doctest':
doctestSw = True
sys.argv[1:] = sys.argv[2:]
import doctest
doctest.testmod( sys.modules[__name__] )
sys.exit( 0 )
print "=== ProcessArgs: %s ===" % ("'file1.py', 'file2.py', '/home/files/file3.py'",)
try:
pa = ProcessArgs( 'file1.py', 'file2.py', '/home/files/file3.py' )
testpa( pa )
except ProcessArgsError, e:
sys.stderr.writelines( str( e ) )
print
print "=== ProcessArgs: %s ===" % ("inFile1.py, sqlFileName='sqlF1.sql', genCsvSw=False,genKwCntSw=True",)
try:
pa = ProcessArgs( "inFile1.py", sqlFileName='sqlF1.sql', genCsvSw=False,genKwCntSw=True )
testpa( pa )
except ProcessArgsError, e:
sys.stderr.writelines( str( e ) )
print
print "=== ProcessArgs: %s ===" % ("No arguments",)
try:
pa = ProcessArgs()
testpa( pa )
except ProcessArgsError, e:
sys.stderr.writelines( str( e ) )
print
sys.exit( 0 )
|