mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-05-23 22:02:27 +00:00
python-3.6.zip added from Github
README.cosmo contains the necessary links.
This commit is contained in:
parent
75fc601ff5
commit
0c4c56ff39
4219 changed files with 1968626 additions and 0 deletions
642
third_party/python/Tools/pybench/CommandLine.py
vendored
Normal file
642
third_party/python/Tools/pybench/CommandLine.py
vendored
Normal file
|
@ -0,0 +1,642 @@
|
|||
""" CommandLine - Get and parse command line options
|
||||
|
||||
NOTE: This still is very much work in progress !!!
|
||||
|
||||
Different version are likely to be incompatible.
|
||||
|
||||
TODO:
|
||||
|
||||
* Incorporate the changes made by (see Inbox)
|
||||
* Add number range option using srange()
|
||||
|
||||
"""
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
__copyright__ = """\
|
||||
Copyright (c), 1997-2006, Marc-Andre Lemburg (mal@lemburg.com)
|
||||
Copyright (c), 2000-2006, eGenix.com Software GmbH (info@egenix.com)
|
||||
See the documentation for further information on copyrights,
|
||||
or contact the author. All Rights Reserved.
|
||||
"""
|
||||
|
||||
__version__ = '1.2'
|
||||
|
||||
import sys, getopt, glob, os, re, traceback
|
||||
|
||||
### Helpers
|
||||
|
||||
def _getopt_flags(options):
|
||||
|
||||
""" Convert the option list to a getopt flag string and long opt
|
||||
list
|
||||
|
||||
"""
|
||||
s = []
|
||||
l = []
|
||||
for o in options:
|
||||
if o.prefix == '-':
|
||||
# short option
|
||||
s.append(o.name)
|
||||
if o.takes_argument:
|
||||
s.append(':')
|
||||
else:
|
||||
# long option
|
||||
if o.takes_argument:
|
||||
l.append(o.name+'=')
|
||||
else:
|
||||
l.append(o.name)
|
||||
return ''.join(s), l
|
||||
|
||||
def invisible_input(prompt='>>> '):
|
||||
|
||||
""" Get raw input from a terminal without echoing the characters to
|
||||
the terminal, e.g. for password queries.
|
||||
|
||||
"""
|
||||
import getpass
|
||||
entry = getpass.getpass(prompt)
|
||||
if entry is None:
|
||||
raise KeyboardInterrupt
|
||||
return entry
|
||||
|
||||
def fileopen(name, mode='wb', encoding=None):
|
||||
|
||||
""" Open a file using mode.
|
||||
|
||||
Default mode is 'wb' meaning to open the file for writing in
|
||||
binary mode. If encoding is given, I/O to and from the file is
|
||||
transparently encoded using the given encoding.
|
||||
|
||||
Files opened for writing are chmod()ed to 0600.
|
||||
|
||||
"""
|
||||
if name == 'stdout':
|
||||
return sys.stdout
|
||||
elif name == 'stderr':
|
||||
return sys.stderr
|
||||
elif name == 'stdin':
|
||||
return sys.stdin
|
||||
else:
|
||||
if encoding is not None:
|
||||
import codecs
|
||||
f = codecs.open(name, mode, encoding)
|
||||
else:
|
||||
f = open(name, mode)
|
||||
if 'w' in mode:
|
||||
os.chmod(name, 0o600)
|
||||
return f
|
||||
|
||||
def option_dict(options):
|
||||
|
||||
""" Return a dictionary mapping option names to Option instances.
|
||||
"""
|
||||
d = {}
|
||||
for option in options:
|
||||
d[option.name] = option
|
||||
return d
|
||||
|
||||
# Alias
|
||||
getpasswd = invisible_input
|
||||
|
||||
_integerRE = re.compile(r'\s*(-?\d+)\s*$')
|
||||
_integerRangeRE = re.compile(r'\s*(-?\d+)\s*-\s*(-?\d+)\s*$')
|
||||
|
||||
def srange(s,
|
||||
|
||||
integer=_integerRE,
|
||||
integerRange=_integerRangeRE):
|
||||
|
||||
""" Converts a textual representation of integer numbers and ranges
|
||||
to a Python list.
|
||||
|
||||
Supported formats: 2,3,4,2-10,-1 - -3, 5 - -2
|
||||
|
||||
Values are appended to the created list in the order specified
|
||||
in the string.
|
||||
|
||||
"""
|
||||
l = []
|
||||
append = l.append
|
||||
for entry in s.split(','):
|
||||
m = integer.match(entry)
|
||||
if m:
|
||||
append(int(m.groups()[0]))
|
||||
continue
|
||||
m = integerRange.match(entry)
|
||||
if m:
|
||||
start,end = map(int,m.groups())
|
||||
l[len(l):] = range(start,end+1)
|
||||
return l
|
||||
|
||||
def abspath(path,
|
||||
|
||||
expandvars=os.path.expandvars,expanduser=os.path.expanduser,
|
||||
join=os.path.join,getcwd=os.getcwd):
|
||||
|
||||
""" Return the corresponding absolute path for path.
|
||||
|
||||
path is expanded in the usual shell ways before
|
||||
joining it with the current working directory.
|
||||
|
||||
"""
|
||||
try:
|
||||
path = expandvars(path)
|
||||
except AttributeError:
|
||||
pass
|
||||
try:
|
||||
path = expanduser(path)
|
||||
except AttributeError:
|
||||
pass
|
||||
return join(getcwd(), path)
|
||||
|
||||
### Option classes
|
||||
|
||||
class Option:
|
||||
|
||||
""" Option base class. Takes no argument.
|
||||
|
||||
"""
|
||||
default = None
|
||||
helptext = ''
|
||||
prefix = '-'
|
||||
takes_argument = 0
|
||||
has_default = 0
|
||||
tab = 15
|
||||
|
||||
def __init__(self,name,help=None):
|
||||
|
||||
if not name[:1] == '-':
|
||||
raise TypeError('option names must start with "-"')
|
||||
if name[1:2] == '-':
|
||||
self.prefix = '--'
|
||||
self.name = name[2:]
|
||||
else:
|
||||
self.name = name[1:]
|
||||
if help:
|
||||
self.help = help
|
||||
|
||||
def __str__(self):
|
||||
|
||||
o = self
|
||||
name = o.prefix + o.name
|
||||
if o.takes_argument:
|
||||
name = name + ' arg'
|
||||
if len(name) > self.tab:
|
||||
name = name + '\n' + ' ' * (self.tab + 1 + len(o.prefix))
|
||||
else:
|
||||
name = '%-*s ' % (self.tab, name)
|
||||
description = o.help
|
||||
if o.has_default:
|
||||
description = description + ' (%s)' % o.default
|
||||
return '%s %s' % (name, description)
|
||||
|
||||
class ArgumentOption(Option):
|
||||
|
||||
""" Option that takes an argument.
|
||||
|
||||
An optional default argument can be given.
|
||||
|
||||
"""
|
||||
def __init__(self,name,help=None,default=None):
|
||||
|
||||
# Basemethod
|
||||
Option.__init__(self,name,help)
|
||||
|
||||
if default is not None:
|
||||
self.default = default
|
||||
self.has_default = 1
|
||||
self.takes_argument = 1
|
||||
|
||||
class SwitchOption(Option):
|
||||
|
||||
""" Options that can be on or off. Has an optional default value.
|
||||
|
||||
"""
|
||||
def __init__(self,name,help=None,default=None):
|
||||
|
||||
# Basemethod
|
||||
Option.__init__(self,name,help)
|
||||
|
||||
if default is not None:
|
||||
self.default = default
|
||||
self.has_default = 1
|
||||
|
||||
### Application baseclass
|
||||
|
||||
class Application:
|
||||
|
||||
""" Command line application interface with builtin argument
|
||||
parsing.
|
||||
|
||||
"""
|
||||
# Options the program accepts (Option instances)
|
||||
options = []
|
||||
|
||||
# Standard settings; these are appended to options in __init__
|
||||
preset_options = [SwitchOption('-v',
|
||||
'generate verbose output'),
|
||||
SwitchOption('-h',
|
||||
'show this help text'),
|
||||
SwitchOption('--help',
|
||||
'show this help text'),
|
||||
SwitchOption('--debug',
|
||||
'enable debugging'),
|
||||
SwitchOption('--copyright',
|
||||
'show copyright'),
|
||||
SwitchOption('--examples',
|
||||
'show examples of usage')]
|
||||
|
||||
# The help layout looks like this:
|
||||
# [header] - defaults to ''
|
||||
#
|
||||
# [synopsis] - formatted as '<self.name> %s' % self.synopsis
|
||||
#
|
||||
# options:
|
||||
# [options] - formatted from self.options
|
||||
#
|
||||
# [version] - formatted as 'Version:\n %s' % self.version, if given
|
||||
#
|
||||
# [about] - defaults to ''
|
||||
#
|
||||
# Note: all fields that do not behave as template are formatted
|
||||
# using the instances dictionary as substitution namespace,
|
||||
# e.g. %(name)s will be replaced by the applications name.
|
||||
#
|
||||
|
||||
# Header (default to program name)
|
||||
header = ''
|
||||
|
||||
# Name (defaults to program name)
|
||||
name = ''
|
||||
|
||||
# Synopsis (%(name)s is replaced by the program name)
|
||||
synopsis = '%(name)s [option] files...'
|
||||
|
||||
# Version (optional)
|
||||
version = ''
|
||||
|
||||
# General information printed after the possible options (optional)
|
||||
about = ''
|
||||
|
||||
# Examples of usage to show when the --examples option is given (optional)
|
||||
examples = ''
|
||||
|
||||
# Copyright to show
|
||||
copyright = __copyright__
|
||||
|
||||
# Apply file globbing ?
|
||||
globbing = 1
|
||||
|
||||
# Generate debug output ?
|
||||
debug = 0
|
||||
|
||||
# Generate verbose output ?
|
||||
verbose = 0
|
||||
|
||||
# Internal errors to catch
|
||||
InternalError = BaseException
|
||||
|
||||
# Instance variables:
|
||||
values = None # Dictionary of passed options (or default values)
|
||||
# indexed by the options name, e.g. '-h'
|
||||
files = None # List of passed filenames
|
||||
optionlist = None # List of passed options
|
||||
|
||||
def __init__(self,argv=None):
|
||||
|
||||
# Setup application specs
|
||||
if argv is None:
|
||||
argv = sys.argv
|
||||
self.filename = os.path.split(argv[0])[1]
|
||||
if not self.name:
|
||||
self.name = os.path.split(self.filename)[1]
|
||||
else:
|
||||
self.name = self.name
|
||||
if not self.header:
|
||||
self.header = self.name
|
||||
else:
|
||||
self.header = self.header
|
||||
|
||||
# Init .arguments list
|
||||
self.arguments = argv[1:]
|
||||
|
||||
# Setup Option mapping
|
||||
self.option_map = option_dict(self.options)
|
||||
|
||||
# Append preset options
|
||||
for option in self.preset_options:
|
||||
if not option.name in self.option_map:
|
||||
self.add_option(option)
|
||||
|
||||
# Init .files list
|
||||
self.files = []
|
||||
|
||||
# Start Application
|
||||
rc = 0
|
||||
try:
|
||||
# Process startup
|
||||
rc = self.startup()
|
||||
if rc is not None:
|
||||
raise SystemExit(rc)
|
||||
|
||||
# Parse command line
|
||||
rc = self.parse()
|
||||
if rc is not None:
|
||||
raise SystemExit(rc)
|
||||
|
||||
# Start application
|
||||
rc = self.main()
|
||||
if rc is None:
|
||||
rc = 0
|
||||
|
||||
except SystemExit as rcException:
|
||||
rc = rcException
|
||||
pass
|
||||
|
||||
except KeyboardInterrupt:
|
||||
print()
|
||||
print('* User Break')
|
||||
print()
|
||||
rc = 1
|
||||
|
||||
except self.InternalError:
|
||||
print()
|
||||
print('* Internal Error (use --debug to display the traceback)')
|
||||
if self.debug:
|
||||
print()
|
||||
traceback.print_exc(20, sys.stdout)
|
||||
elif self.verbose:
|
||||
print(' %s: %s' % sys.exc_info()[:2])
|
||||
print()
|
||||
rc = 1
|
||||
|
||||
raise SystemExit(rc)
|
||||
|
||||
def add_option(self, option):
|
||||
|
||||
""" Add a new Option instance to the Application dynamically.
|
||||
|
||||
Note that this has to be done *before* .parse() is being
|
||||
executed.
|
||||
|
||||
"""
|
||||
self.options.append(option)
|
||||
self.option_map[option.name] = option
|
||||
|
||||
def startup(self):
|
||||
|
||||
""" Set user defined instance variables.
|
||||
|
||||
If this method returns anything other than None, the
|
||||
process is terminated with the return value as exit code.
|
||||
|
||||
"""
|
||||
return None
|
||||
|
||||
def exit(self, rc=0):
|
||||
|
||||
""" Exit the program.
|
||||
|
||||
rc is used as exit code and passed back to the calling
|
||||
program. It defaults to 0 which usually means: OK.
|
||||
|
||||
"""
|
||||
raise SystemExit(rc)
|
||||
|
||||
def parse(self):
|
||||
|
||||
""" Parse the command line and fill in self.values and self.files.
|
||||
|
||||
After having parsed the options, the remaining command line
|
||||
arguments are interpreted as files and passed to .handle_files()
|
||||
for processing.
|
||||
|
||||
As final step the option handlers are called in the order
|
||||
of the options given on the command line.
|
||||
|
||||
"""
|
||||
# Parse arguments
|
||||
self.values = values = {}
|
||||
for o in self.options:
|
||||
if o.has_default:
|
||||
values[o.prefix+o.name] = o.default
|
||||
else:
|
||||
values[o.prefix+o.name] = 0
|
||||
flags,lflags = _getopt_flags(self.options)
|
||||
try:
|
||||
optlist,files = getopt.getopt(self.arguments,flags,lflags)
|
||||
if self.globbing:
|
||||
l = []
|
||||
for f in files:
|
||||
gf = glob.glob(f)
|
||||
if not gf:
|
||||
l.append(f)
|
||||
else:
|
||||
l[len(l):] = gf
|
||||
files = l
|
||||
self.optionlist = optlist
|
||||
self.files = files + self.files
|
||||
except getopt.error as why:
|
||||
self.help(why)
|
||||
sys.exit(1)
|
||||
|
||||
# Call file handler
|
||||
rc = self.handle_files(self.files)
|
||||
if rc is not None:
|
||||
sys.exit(rc)
|
||||
|
||||
# Call option handlers
|
||||
for optionname, value in optlist:
|
||||
|
||||
# Try to convert value to integer
|
||||
try:
|
||||
value = int(value)
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
# Find handler and call it (or count the number of option
|
||||
# instances on the command line)
|
||||
handlername = 'handle' + optionname.replace('-', '_')
|
||||
try:
|
||||
handler = getattr(self, handlername)
|
||||
except AttributeError:
|
||||
if value == '':
|
||||
# count the number of occurrences
|
||||
if optionname in values:
|
||||
values[optionname] = values[optionname] + 1
|
||||
else:
|
||||
values[optionname] = 1
|
||||
else:
|
||||
values[optionname] = value
|
||||
else:
|
||||
rc = handler(value)
|
||||
if rc is not None:
|
||||
raise SystemExit(rc)
|
||||
|
||||
# Apply final file check (for backward compatibility)
|
||||
rc = self.check_files(self.files)
|
||||
if rc is not None:
|
||||
sys.exit(rc)
|
||||
|
||||
def check_files(self,filelist):
|
||||
|
||||
""" Apply some user defined checks on the files given in filelist.
|
||||
|
||||
This may modify filelist in place. A typical application
|
||||
is checking that at least n files are given.
|
||||
|
||||
If this method returns anything other than None, the
|
||||
process is terminated with the return value as exit code.
|
||||
|
||||
"""
|
||||
return None
|
||||
|
||||
def help(self,note=''):
|
||||
|
||||
self.print_header()
|
||||
if self.synopsis:
|
||||
print('Synopsis:')
|
||||
# To remain backward compatible:
|
||||
try:
|
||||
synopsis = self.synopsis % self.name
|
||||
except (NameError, KeyError, TypeError):
|
||||
synopsis = self.synopsis % self.__dict__
|
||||
print(' ' + synopsis)
|
||||
print()
|
||||
self.print_options()
|
||||
if self.version:
|
||||
print('Version:')
|
||||
print(' %s' % self.version)
|
||||
print()
|
||||
if self.about:
|
||||
about = self.about % self.__dict__
|
||||
print(about.strip())
|
||||
print()
|
||||
if note:
|
||||
print('-'*72)
|
||||
print('Note:',note)
|
||||
print()
|
||||
|
||||
def notice(self,note):
|
||||
|
||||
print('-'*72)
|
||||
print('Note:',note)
|
||||
print('-'*72)
|
||||
print()
|
||||
|
||||
def print_header(self):
|
||||
|
||||
print('-'*72)
|
||||
print(self.header % self.__dict__)
|
||||
print('-'*72)
|
||||
print()
|
||||
|
||||
def print_options(self):
|
||||
|
||||
options = self.options
|
||||
print('Options and default settings:')
|
||||
if not options:
|
||||
print(' None')
|
||||
return
|
||||
int = [x for x in options if x.prefix == '--']
|
||||
short = [x for x in options if x.prefix == '-']
|
||||
items = short + int
|
||||
for o in options:
|
||||
print(' ',o)
|
||||
print()
|
||||
|
||||
#
|
||||
# Example handlers:
|
||||
#
|
||||
# If a handler returns anything other than None, processing stops
|
||||
# and the return value is passed to sys.exit() as argument.
|
||||
#
|
||||
|
||||
# File handler
|
||||
def handle_files(self,files):
|
||||
|
||||
""" This may process the files list in place.
|
||||
"""
|
||||
return None
|
||||
|
||||
# Short option handler
|
||||
def handle_h(self,arg):
|
||||
|
||||
self.help()
|
||||
return 0
|
||||
|
||||
def handle_v(self, value):
|
||||
|
||||
""" Turn on verbose output.
|
||||
"""
|
||||
self.verbose = 1
|
||||
|
||||
# Handlers for long options have two underscores in their name
|
||||
def handle__help(self,arg):
|
||||
|
||||
self.help()
|
||||
return 0
|
||||
|
||||
def handle__debug(self,arg):
|
||||
|
||||
self.debug = 1
|
||||
# We don't want to catch internal errors:
|
||||
class NoErrorToCatch(Exception): pass
|
||||
self.InternalError = NoErrorToCatch
|
||||
|
||||
def handle__copyright(self,arg):
|
||||
|
||||
self.print_header()
|
||||
copyright = self.copyright % self.__dict__
|
||||
print(copyright.strip())
|
||||
print()
|
||||
return 0
|
||||
|
||||
def handle__examples(self,arg):
|
||||
|
||||
self.print_header()
|
||||
if self.examples:
|
||||
print('Examples:')
|
||||
print()
|
||||
examples = self.examples % self.__dict__
|
||||
print(examples.strip())
|
||||
print()
|
||||
else:
|
||||
print('No examples available.')
|
||||
print()
|
||||
return 0
|
||||
|
||||
def main(self):
|
||||
|
||||
""" Override this method as program entry point.
|
||||
|
||||
The return value is passed to sys.exit() as argument. If
|
||||
it is None, 0 is assumed (meaning OK). Unhandled
|
||||
exceptions are reported with exit status code 1 (see
|
||||
__init__ for further details).
|
||||
|
||||
"""
|
||||
return None
|
||||
|
||||
# Alias
|
||||
CommandLine = Application
|
||||
|
||||
def _test():
|
||||
|
||||
class MyApplication(Application):
|
||||
header = 'Test Application'
|
||||
version = __version__
|
||||
options = [Option('-v','verbose')]
|
||||
|
||||
def handle_v(self,arg):
|
||||
print('VERBOSE, Yeah !')
|
||||
|
||||
cmd = MyApplication()
|
||||
if not cmd.values['-h']:
|
||||
cmd.help()
|
||||
print('files:',cmd.files)
|
||||
print('Bye...')
|
||||
|
||||
if __name__ == '__main__':
|
||||
_test()
|
Loading…
Add table
Add a link
Reference in a new issue