class ClientOptions(options.ConchOptions): synopsis = """Usage: cftp [options] [user@]host cftp [options] [user@]host[:dir[/]] cftp [options] [user@]host[:file [localfile]] """ longdesc = ("cftp is a client for logging into a remote machine and " "executing commands to send and receive file information") optParameters = [ ['buffersize', 'B', 32768, 'Size of the buffer to use for sending/receiving.'], ['batchfile', 'b', None, 'File to read commands from, or \'-\' for stdin.'], ['requests', 'R', 5, 'Number of requests to make before waiting for a reply.'], ['subsystem', 's', 'sftp', 'Subsystem/server program to connect to.']] compData = usage.Completions( descriptions={ "buffersize": "Size of send/receive buffer (default: 32768)"}, extraActions=[usage.CompleteUserAtHost(), usage.CompleteFiles(descr="local file")]) def parseArgs(self, host, localPath=None): self['remotePath'] = '' if ':' in host: host, self['remotePath'] = host.split(':', 1) self['remotePath'].rstrip('/') self['host'] = host self['localPath'] = localPath
class ClientOptions(options.ConchOptions): synopsis = """Usage: cftp [options] [user@]host cftp [options] [user@]host[:dir[/]] cftp [options] [user@]host[:file [localfile]] """ longdesc = ( "cftp is a client for logging into a remote machine and " "executing commands to send and receive file information" ) optParameters: List[List[Optional[Union[str, int]]]] = [ ["buffersize", "B", 32768, "Size of the buffer to use for sending/receiving."], ["batchfile", "b", None, "File to read commands from, or '-' for stdin."], ["requests", "R", 5, "Number of requests to make before waiting for a reply."], ["subsystem", "s", "sftp", "Subsystem/server program to connect to."], ] compData = usage.Completions( descriptions={"buffersize": "Size of send/receive buffer (default: 32768)"}, extraActions=[ usage.CompleteUserAtHost(), usage.CompleteFiles(descr="local file"), ], ) def parseArgs(self, host, localPath=None): self["remotePath"] = "" if ":" in host: host, self["remotePath"] = host.split(":", 1) self["remotePath"].rstrip("/") self["host"] = host self["localPath"] = localPath
class Options(usage.Options): synopsis = "[loki options]" optParameters = [[ "proxy", "p", None, "strports description of the port to " "start the proxy server on." ], [ "ui", "u", None, "strports description of the port to ", "start the administrative ui server on." ], ["tricks", "t", None, "path to YAML tricks file."]] compData = usage.Completions( optActions={"config": usage.CompleteFiles("*.yml")}) def postOptions(self): if self['proxy'] is None: self['proxy'] = 'tcp:8080' if self['ui'] is None: self['ui'] = 'tcp:8181' if self['tricks'] is not None: (self['requestTricks'], self['responseTricks']) = load_tricks(file(self['tricks'], 'r'))
class MyOptions(usage.Options): optFlags = [["unsigned", "u"]] optParameters = [ ["tapfile", "t", "twistd.tap"], [ "maintainer", "m", "", "The maintainer's name and email in a specific format: " "'John Doe <*****@*****.**>'" ], ["protocol", "p", ""], ["description", "e", ""], ["long_description", "l", ""], ["set-version", "V", "1.0"], ["debfile", "d", None], [ "type", "y", "tap", "Type of configuration: 'tap', 'xml', " "'source' or 'python' for .tac files" ] ] compData = usage.Completions( optActions={ "type": usage.CompleteList(["tap", "xml", "source", "python"]), "debfile": usage.CompleteFiles("*.deb") }) def postOptions(self): if not self["maintainer"]: raise usage.UsageError("maintainer must be specified.")
def test_files(self): """ CompleteFiles produces zsh shell-code that completes file names according to a glob. """ c = usage.CompleteFiles() got = c._shellCode('some-option', usage._ZSH) self.assertEqual(got, ':some-option (*):_files -g "*"') c = usage.CompleteFiles('*.py') got = c._shellCode('some-option', usage._ZSH) self.assertEqual(got, ':some-option (*.py):_files -g "*.py"') c = usage.CompleteFiles('*.py', descr="some action", repeat=True) got = c._shellCode('some-option', usage._ZSH) self.assertEqual(got, '*:some action (*.py):_files -g "*.py"')
class ServerOptions(app.ServerOptions): synopsis = "Usage: twistd [options]" optFlags = [ ["nodaemon", "n", "don't daemonize, don't use default umask of 0077"], ["originalname", None, "Don't try to change the process name"], ["syslog", None, "Log to syslog, not to file"], [ "euid", "", "Set only effective user-id rather than real user-id. " "(This option has no effect unless the server is running as " "root, in which case it means not to shed all privileges " "after binding ports, retaining the option to regain " "privileges in cases such as spawning processes. " "Use with caution.)", ], ] optParameters = [ ["prefix", None, "twisted", "use the given prefix when syslogging"], ["pidfile", "", "twistd.pid", "Name of the pidfile"], ["chroot", None, None, "Chroot to a supplied directory before running"], ["uid", "u", None, "The uid to run as.", uidFromString], [ "gid", "g", None, "The gid to run as. If not specified, the default gid " "associated with the specified --uid is used.", gidFromString, ], ["umask", None, None, "The (octal) file creation mask to apply.", _umask], ] compData = usage.Completions( optActions={ "pidfile": usage.CompleteFiles("*.pid"), "chroot": usage.CompleteDirs(descr="chroot directory"), "gid": usage.CompleteGroups(descr="gid to run as"), "uid": usage.CompleteUsernames(descr="uid to run as"), "prefix": usage.Completer(descr="syslog prefix"), }, ) def opt_version(self): """ Print version information and exit. """ print( "twistd (the Twisted daemon) {}".format(copyright.version), file=self.stdout ) print(copyright.copyright, file=self.stdout) sys.exit() def postOptions(self): app.ServerOptions.postOptions(self) if self["pidfile"]: self["pidfile"] = os.path.abspath(self["pidfile"])
class Options(usage.Options): synopsis = """%s [options] [path to test].py """ % (os.path.basename(sys.argv[0]), ) longdesc = ("ooniprobe loads and executes a suite or a set of suites of" " network tests. These are loaded from modules, packages and" " files listed on the command line") optFlags = [["help", "h"], ["resume", "r"], ["no-collector", "n"]] optParameters = [ ["reportfile", "o", None, "report file name"], [ "testdeck", "i", None, "Specify as input a test deck: a yaml file containig the tests to run an their arguments" ], [ "collector", "c", 'httpo://nkvphnp3p6agi5qq.onion', "Address of the collector of test results. default: httpo://nkvphnp3p6agi5qq.onion" ], ["logfile", "l", None, "log file name"], ["pcapfile", "O", None, "pcap file name"], ["parallelism", "p", "10", "input parallelism"], ] compData = usage.Completions(extraActions=[ usage.CompleteFiles( "*.py", descr="file | module | package | TestCase | testMethod", repeat=True) ], ) tracer = None def __init__(self): self['test'] = None usage.Options.__init__(self) def opt_asciilulz(self): from ooni.utils import logo print logo.getlogo() def opt_spew(self): """ Print an insanely verbose log of everything that happens. Useful when debugging freezes or locks in complex code. """ sys.settrace(spewer) def parseArgs(self, *args): if self['testdeck']: return try: self['test_file'] = args[0] self['subargs'] = args[1:] except: raise usage.UsageError("No test filename specified!")
class ServerOptions(app.ServerOptions): synopsis = "Usage: twistd [options]" optFlags = [ ['nodaemon', 'n', "don't daemonize, don't use default umask of 0077"], ['originalname', None, "Don't try to change the process name"], ['syslog', None, "Log to syslog, not to file"], [ 'euid', '', "Set only effective user-id rather than real user-id. " "(This option has no effect unless the server is running as " "root, in which case it means not to shed all privileges " "after binding ports, retaining the option to regain " "privileges in cases such as spawning processes. " "Use with caution.)" ], ] optParameters = [ ['prefix', None, 'twisted', "use the given prefix when syslogging"], ['pidfile', '', 'twistd.pid', "Name of the pidfile"], [ 'chroot', None, None, 'Chroot to a supplied directory before running' ], ['uid', 'u', None, "The uid to run as.", uidFromString], ['gid', 'g', None, "The gid to run as.", gidFromString], [ 'umask', None, None, "The (octal) file creation mask to apply.", _umask ], ] compData = usage.Completions(optActions={ "pidfile": usage.CompleteFiles("*.pid"), "chroot": usage.CompleteDirs(descr="chroot directory"), "gid": usage.CompleteGroups(descr="gid to run as"), "uid": usage.CompleteUsernames(descr="uid to run as"), "prefix": usage.Completer(descr="syslog prefix"), }, ) def opt_version(self): """Print version information and exit. """ print 'twistd (the Twisted daemon) %s' % copyright.version print copyright.copyright sys.exit() def postOptions(self): app.ServerOptions.postOptions(self) if self['pidfile']: self['pidfile'] = os.path.abspath(self['pidfile'])
class Options(usage.Options, app.ReactorSelectionMixin): synopsis = """%s [options] [path to test].py """ % (os.path.basename(sys.argv[0]), ) longdesc = ("ooniprobe loads and executes a suite or a set of suites of" " network tests. These are loaded from modules, packages and" " files listed on the command line") optFlags = [ ["help", "h"], [ 'debug-stacktraces', 'B', 'Report deferred creation and callback stack traces' ], ] optParameters = [ ["reportfile", "o", None, "report file name"], [ "collector", "c", None, "Address of the collector of test results. (example: http://127.0.0.1:8888)" ], ["logfile", "l", None, "log file name"], ["pcapfile", "p", None, "pcap file name"] ] compData = usage.Completions(extraActions=[ usage.CompleteFiles( "*.py", descr="file | module | package | TestCase | testMethod", repeat=True) ], ) tracer = None def __init__(self): self['test'] = None usage.Options.__init__(self) def opt_asciilulz(self): from ooni.utils import logo print logo.getlogo() def opt_spew(self): """ Print an insanely verbose log of everything that happens. Useful when debugging freezes or locks in complex code. """ sys.settrace(spewer) def parseArgs(self, *args): try: self['test'] = args[0] self['subArgs'] = args[1:] except: raise usage.UsageError("No test filename specified!")
class ConvertOptions(usage.Options): synopsis = "Usage: tapconvert [options]" optParameters = [ ['in', 'i', None, "The filename of the tap to read from"], ['out', 'o', None, "A filename to write the tap to"], [ 'typein', 'f', 'guess', "The format to use; this can be 'guess', 'python', " "'pickle', 'xml', or 'source'." ], [ 'typeout', 't', 'source', "The output format to use; this can be 'pickle', 'xml', or 'source'." ], ] optFlags = [[ 'decrypt', 'd', "The specified tap/aos/xml file is encrypted." ], ['encrypt', 'e', "Encrypt file before writing"]] compData = usage.Completions( optActions={ "typein": usage.CompleteList(["guess", "python", "pickle", "xml", "source"]), "typeout": usage.CompleteList(["pickle", "xml", "source"]), "in": usage.CompleteFiles(descr="tap file to read from"), "out": usage.CompleteFiles(descr="tap file to write to"), }) def postOptions(self): if self['in'] is None: raise usage.UsageError("%s\nYou must specify the input filename." % self) if self["typein"] == "guess": try: self["typein"] = sob.guessType(self["in"]) except KeyError: raise usage.UsageError("Could not guess type for '%s'" % self["typein"])
class Options(usage.Options): optParameters = [['rpc', 'r', '/etc/rpc', 'RPC procedure table file'], [ 'file', 'f', '/etc/inetd.conf', 'Service configuration file' ]] optFlags = [['nointernal', 'i', "Don't run internal services"]] compData = usage.Completions( optActions={"file": usage.CompleteFiles('*.conf')})
class Options(usage.Options): synopsis = "[-i <interface>] [-p <port>] [-l <file>]" optParameters = [["interface", "i", "127.0.0.1", "local interface to which we listen"], ["port", "p", 1080, "Port on which to listen"], ["log", "l", None, "file to log connection data to"]] compData = usage.Completions( optActions={"log": usage.CompleteFiles("*.log"), "interface": usage.CompleteNetInterfaces()} ) longdesc = "Makes a SOCKSv4 server."
class Options(usage.Options): synopsis = """{} [options] source.py """.format(os.path.basename(sys.argv[0]), ) optParameters = [ ("stylesheet", "s", None, "URL of stylesheet to link to."), ] compData = usage.Completions( extraActions=[usage.CompleteFiles("*.py", descr="source python file")]) def parseArgs(self, filename): self["filename"] = filename
class Options(usage.Options): synopsis = """%s [options] source.py """ % (os.path.basename(sys.argv[0]), ) optParameters = [ ('stylesheet', 's', None, "URL of stylesheet to link to."), ] compData = usage.Completions( extraActions=[usage.CompleteFiles('*.py', descr='source python file')]) def parseArgs(self, filename): self['filename'] = filename
class MyOptions(usage.Options): optFlags = [['quiet', 'q']] optParameters = [ ["tapfile", "t", "twistd.tap"], ["maintainer", "m", "tap2rpm"], ["protocol", "p", None], ["description", "e", None], ["long_description", "l", "Automatically created by tap2rpm"], ["set-version", "V", "1.0"], ["rpmfile", "r", None], ["type", "y", "tap", "type of configuration: 'tap', 'xml, " "'source' or 'python'"], ] compData = usage.Completions( optActions={"type": usage.CompleteList(["tap", "xml", "source", "python"]), "rpmfile": usage.CompleteFiles("*.rpm")} ) def postOptions(self): """ Calculate the default values for certain command-line options. """ # Options whose defaults depend on other parameters. if self['protocol'] is None: base_tapfile = os.path.basename(self['tapfile']) self['protocol'] = os.path.splitext(base_tapfile)[0] if self['description'] is None: self['description'] = "A TCP server for %s" % (self['protocol'],) if self['rpmfile'] is None: self['rpmfile'] = 'twisted-%s' % (self['protocol'],) # Values that aren't options, but are calculated from options and are # handy to have around. self['twistd_option'] = type_dict[self['type']] self['release-name'] = '%s-%s' % (self['rpmfile'], self['set-version']) def opt_unsigned(self): """ Generate an unsigned rather than a signed RPM. (DEPRECATED; unsigned is the default) """ msg = deprecate.getDeprecationWarningString( self.opt_unsigned, versions.Version("Twisted", 12, 1, 0)) warnings.warn(msg, category=DeprecationWarning, stacklevel=2) # Maintain the -u short flag opt_u = opt_unsigned
class Options(usage.Options): longdesc = "lore converts documentation formats." optFlags = [ ["plain", 'p', "Report filenames without progress bar"], ["null", 'n', "Do not report filenames"], ["number", 'N', "Add chapter/section numbers to section headings"], ] optParameters = [ ["input", "i", 'lore'], [ "inputext", "e", ".xhtml", "The extension that your Lore input files have" ], ["docsdir", "d", None], ["linkrel", "l", ''], ["output", "o", 'html'], [ "index", "x", None, "The base filename you want to give your index file" ], ["book", "b", None, "The book file to generate a book from"], [ "prefixurl", None, "", "The prefix to stick on to relative links; only useful when processing directories" ], ] compData = usage.Completions( extraActions=[usage.CompleteFiles(descr="files", repeat=True)]) def __init__(self, *args, **kw): usage.Options.__init__(self, *args, **kw) self.config = {} def opt_config(self, s): if '=' in s: k, v = s.split('=', 1) self.config[k] = v else: self.config[s] = 1 def parseArgs(self, *files): self['files'] = files
class CheckConfigOptions(base.SubcommandOptions): subcommandFunction = "buildbot.scripts.checkconfig.checkconfig" optFlags = [ ['quiet', 'q', "Don't display error messages or tracebacks"], ] # on tab completion, suggest files as first argument if hasattr(usage, 'Completions'): # only set completion suggestion if running with # twisted version (>=11.1.0) that supports it compData = usage.Completions(extraActions=[usage.CompleteFiles()]) def getSynopsis(self): return "Usage:\t\tbuildbot checkconfig [configFile]\n" + \ "\t\tIf not specified, the config file specified in " + \ "'buildbot.tac' from the current directory will be used" def parseArgs(self, *args): if len(args) >= 1: self['configFile'] = args[0]
class Options(usage.Options): """ To use it, create a file named `sample-inetd.conf` with: 8123 stream tcp wait some_user /bin/cat - You can then run it as in the following example and port 8123 became an echo server. twistd -n inetd -f sample-inetd.conf """ optParameters = [[ 'rpc', 'r', '/etc/rpc', 'DEPRECATED. RPC procedure table file' ], ['file', 'f', '/etc/inetd.conf', 'Service configuration file']] optFlags = [['nointernal', 'i', "Don't run internal services"]] compData = usage.Completions( optActions={"file": usage.CompleteFiles('*.conf')})
class Options(usage.Options): """ To use it, create a file named `sample-inetd.conf` with: 8123 stream tcp wait some_user /bin/cat - You can then run it as in the following example and port 8123 became an echo server. twistd -n inetd -f sample-inetd.conf """ optParameters = [ ["rpc", "r", "/etc/rpc", "DEPRECATED. RPC procedure table file"], ["file", "f", "/etc/inetd.conf", "Service configuration file"], ] optFlags = [["nointernal", "i", "Don't run internal services"]] compData = usage.Completions(optActions={"file": usage.CompleteFiles("*.conf")})
class MyOptions(usage.Options): optFlags = [["unsigned", "u"], ['quiet', 'q']] optParameters = [ ["tapfile", "t", "twistd.tap"], ["maintainer", "m", "tap2rpm"], ["protocol", "p", None], ["description", "e", None], ["long_description", "l", "Automatically created by tap2rpm"], ["set-version", "V", "1.0"], ["rpmfile", "r", None], [ "type", "y", "tap", "type of configuration: 'tap', 'xml, " "'source' or 'python'" ], ] compData = usage.Completions( optActions={ "type": usage.CompleteList(["tap", "xml", "source", "python"]), "rpmfile": usage.CompleteFiles("*.rpm") }) def postOptions(self): """ Calculate the default values for certain command-line options. """ # Options whose defaults depend on other parameters. if self['protocol'] is None: base_tapfile = os.path.basename(self['tapfile']) self['protocol'] = os.path.splitext(base_tapfile)[0] if self['description'] is None: self['description'] = "A TCP server for %s" % (self['protocol'], ) if self['rpmfile'] is None: self['rpmfile'] = 'twisted-%s' % (self['protocol'], ) # Values that aren't options, but are calculated from options and are # handy to have around. self['twistd_option'] = type_dict[self['type']] self['release-name'] = '%s-%s' % (self['rpmfile'], self['set-version'])
class Options(usage.Options, app.ReactorSelectionMixin): synopsis = """%s [options] [[file|package|module|TestCase|testmethod]...] """ % (os.path.basename(sys.argv[0]), ) longdesc = ("trial loads and executes a suite of unit tests, obtained " "from modules, packages and files listed on the command line.") optFlags = [ ["help", "h"], [ "rterrors", "e", "realtime errors, print out tracebacks as " "soon as they occur" ], [ "debug", "b", "Run tests in the Python debugger. Will load " "'.pdbrc' from current directory if it exists." ], [ "debug-stacktraces", "B", "Report Deferred creation and " "callback stack traces" ], [ "nopm", None, "don't automatically jump into debugger for " "postmorteming of exceptions" ], ["dry-run", 'n', "do everything but run the tests"], [ "force-gc", None, "Have Trial run gc.collect() before and " "after each test case." ], ["profile", None, "Run tests under the Python profiler"], ["unclean-warnings", None, "Turn dirty reactor errors into warnings"], ["until-failure", "u", "Repeat test until it fails"], ["no-recurse", "N", "Don't recurse into packages"], [ 'help-reporters', None, "Help on available output plugins (reporters)" ] ] optParameters = [ ["logfile", "l", "test.log", "log file name"], [ "random", "z", None, "Run tests in random order using the specified seed" ], [ 'temp-directory', None, '_trial_temp', 'Path to use as working directory for tests.' ], [ 'reporter', None, 'verbose', 'The reporter to use for this test run. See --help-reporters for ' 'more info.' ] ] compData = usage.Completions( optActions={ "tbformat": usage.CompleteList(["plain", "emacs", "cgitb"]), "reporter": _reporterAction, "logfile": usage.CompleteFiles(descr="log file name"), "random": usage.Completer(descr="random seed") }, extraActions=[ usage.CompleteFiles( "*.py", descr="file | module | package | TestCase | testMethod", repeat=True) ], ) fallbackReporter = reporter.TreeReporter extra = None tracer = None def __init__(self): self['tests'] = set() usage.Options.__init__(self) def coverdir(self): """ Return a L{FilePath} representing the directory into which coverage results should be written. """ coverdir = 'coverage' result = FilePath(self['temp-directory']).child(coverdir) print "Setting coverage directory to %s." % (result.path, ) return result def opt_coverage(self): """ Generate coverage information in the I{coverage} file in the directory specified by the I{trial-temp} option. """ import trace self.tracer = trace.Trace(count=1, trace=0) sys.settrace(self.tracer.globaltrace) def opt_testmodule(self, filename): """ Filename to grep for test cases (-*- test-case-name) """ # If the filename passed to this parameter looks like a test module # we just add that to the test suite. # # If not, we inspect it for an Emacs buffer local variable called # 'test-case-name'. If that variable is declared, we try to add its # value to the test suite as a module. # # This parameter allows automated processes (like Buildbot) to pass # a list of files to Trial with the general expectation of "these files, # whatever they are, will get tested" if not os.path.isfile(filename): sys.stderr.write("File %r doesn't exist\n" % (filename, )) return filename = os.path.abspath(filename) if isTestFile(filename): self['tests'].add(filename) else: self['tests'].update(getTestModules(filename)) def opt_spew(self): """ Print an insanely verbose log of everything that happens. Useful when debugging freezes or locks in complex code. """ sys.settrace(spewer) def opt_help_reporters(self): synopsis = ("Trial's output can be customized using plugins called " "Reporters. You can\nselect any of the following " "reporters using --reporter=<foo>\n") print synopsis for p in plugin.getPlugins(itrial.IReporter): print ' ', p.longOpt, '\t', p.description print sys.exit(0) def opt_disablegc(self): """ Disable the garbage collector """ gc.disable() def opt_tbformat(self, opt): """ Specify the format to display tracebacks with. Valid formats are 'plain', 'emacs', and 'cgitb' which uses the nicely verbose stdlib cgitb.text function """ try: self['tbformat'] = TBFORMAT_MAP[opt] except KeyError: raise usage.UsageError( "tbformat must be 'plain', 'emacs', or 'cgitb'.") def opt_extra(self, arg): """ Add an extra argument. (This is a hack necessary for interfacing with emacs's `gud'.) NOTE: This option is deprecated as of Twisted 11.0 """ warnings.warn(deprecate.getDeprecationWarningString( Options.opt_extra, versions.Version('Twisted', 11, 0, 0)), category=DeprecationWarning, stacklevel=2) if self.extra is None: self.extra = [] self.extra.append(arg) opt_x = opt_extra def opt_recursionlimit(self, arg): """ see sys.setrecursionlimit() """ try: sys.setrecursionlimit(int(arg)) except (TypeError, ValueError): raise usage.UsageError( "argument to recursionlimit must be an integer") def opt_random(self, option): try: self['random'] = long(option) except ValueError: raise usage.UsageError( "Argument to --random must be a positive integer") else: if self['random'] < 0: raise usage.UsageError( "Argument to --random must be a positive integer") elif self['random'] == 0: self['random'] = long(time.time() * 100) def opt_without_module(self, option): """ Fake the lack of the specified modules, separated with commas. """ for module in option.split(","): if module in sys.modules: warnings.warn("Module '%s' already imported, " "disabling anyway." % (module, ), category=RuntimeWarning) sys.modules[module] = None def parseArgs(self, *args): self['tests'].update(args) if self.extra is not None: self['tests'].update(self.extra) def _loadReporterByName(self, name): for p in plugin.getPlugins(itrial.IReporter): qual = "%s.%s" % (p.module, p.klass) if p.longOpt == name: return reflect.namedAny(qual) raise usage.UsageError("Only pass names of Reporter plugins to " "--reporter. See --help-reporters for " "more info.") def postOptions(self): # Only load reporters now, as opposed to any earlier, to avoid letting # application-defined plugins muck up reactor selecting by importing # t.i.reactor and causing the default to be installed. self['reporter'] = self._loadReporterByName(self['reporter']) if 'tbformat' not in self: self['tbformat'] = 'default' if self['nopm']: if not self['debug']: raise usage.UsageError("you must specify --debug when using " "--nopm ") failure.DO_POST_MORTEM = False
class Options(usage.Options): """ Define the options accepted by the I{twistd web} plugin. """ synopsis = "[web options]" optParameters = [ [ "port", "p", None, "strports description of the port to " "start the server on." ], [ "logfile", "l", None, "Path to web CLF (Combined Log Format) log file." ], ["https", None, None, "Port to listen on for Secure HTTP."], [ "certificate", "c", "server.pem", "SSL certificate to use for HTTPS. " ], ["privkey", "k", "server.pem", "SSL certificate to use for HTTPS."], ] optFlags = [ [ "personal", "", "Instead of generating a webserver, generate a " "ResourcePublisher which listens on the port given by " "--port, or ~/%s " % (distrib.UserDirectory.userSocketName, ) + "if --port is not specified." ], [ "notracebacks", "n", "Do not display tracebacks in broken web pages. " + "Displaying tracebacks to users may be security risk!" ], ] compData = usage.Completions( optActions={ "logfile": usage.CompleteFiles("*.log"), "certificate": usage.CompleteFiles("*.pem"), "privkey": usage.CompleteFiles("*.pem") }) longdesc = """\ This starts a webserver. If you specify no arguments, it will be a demo webserver that has the Test class from twisted.web.demo in it.""" def __init__(self): usage.Options.__init__(self) self['indexes'] = [] self['root'] = None def opt_index(self, indexName): """ Add the name of a file used to check for directory indexes. [default: index, index.html] """ self['indexes'].append(indexName) opt_i = opt_index def opt_user(self): """ Makes a server with ~/public_html and ~/.twistd-web-pb support for users. """ self['root'] = distrib.UserDirectory() opt_u = opt_user def opt_path(self, path): """ <path> is either a specific file or a directory to be set as the root of the web server. Use this if you have a directory full of HTML, cgi, php3, epy, or rpy files or any other files that you want to be served up raw. """ def php3(*args, **kwargs): # Help avoid actually importing twisted.web.twcgi.PHP3Script until # it is really needed. This avoids getting a deprecation warning if # you're not using deprecated functionality. from twisted.web.twcgi import PHP3Script return PHP3Script(*args, **kwargs) def php(*args, **kwargs): # Help avoid actually importing twisted.web.twcgi.PHPScript until it # is really needed. This avoids getting a deprecation warning if # you're not using deprecated functionality. from twisted.web.twcgi import PHPScript return PHPScript(*args, **kwargs) self['root'] = static.File(os.path.abspath(path)) self['root'].processors = { '.cgi': twcgi.CGIScript, '.php3': php3, '.php': php, '.epy': script.PythonScript, '.rpy': script.ResourceScript, } def opt_processor(self, proc): """ `ext=class' where `class' is added as a Processor for files ending with `ext'. """ if not isinstance(self['root'], static.File): raise usage.UsageError( "You can only use --processor after --path.") ext, klass = proc.split('=', 1) self['root'].processors[ext] = reflect.namedClass(klass) def opt_class(self, className): """ Create a Resource subclass with a zero-argument constructor. """ classObj = reflect.namedClass(className) self['root'] = classObj() def opt_resource_script(self, name): """ An .rpy file to be used as the root resource of the webserver. """ self['root'] = script.ResourceScriptWrapper(name) def opt_wsgi(self, name): """ The FQPN of a WSGI application object to serve as the root resource of the webserver. """ pool = threadpool.ThreadPool() reactor.callWhenRunning(pool.start) reactor.addSystemEventTrigger('after', 'shutdown', pool.stop) try: application = reflect.namedAny(name) except (AttributeError, ValueError): raise usage.UsageError("No such WSGI application: %r" % (name, )) self['root'] = wsgi.WSGIResource(reactor, pool, application) def opt_mime_type(self, defaultType): """ Specify the default mime-type for static files. """ if not isinstance(self['root'], static.File): raise usage.UsageError( "You can only use --mime_type after --path.") self['root'].defaultType = defaultType opt_m = opt_mime_type def opt_allow_ignore_ext(self): """ Specify whether or not a request for 'foo' should return 'foo.ext' """ if not isinstance(self['root'], static.File): raise usage.UsageError("You can only use --allow_ignore_ext " "after --path.") self['root'].ignoreExt('*') def opt_ignore_ext(self, ext): """ Specify an extension to ignore. These will be processed in order. """ if not isinstance(self['root'], static.File): raise usage.UsageError("You can only use --ignore_ext " "after --path.") self['root'].ignoreExt(ext) def postOptions(self): """ Set up conditional defaults and check for dependencies. If SSL is not available but an HTTPS server was configured, raise a L{UsageError} indicating that this is not possible. If no server port was supplied, select a default appropriate for the other options supplied. """ if self['https']: try: from twisted.internet.ssl import DefaultOpenSSLContextFactory except ImportError: raise usage.UsageError("SSL support not installed") if self['port'] is None: if self['personal']: path = os.path.expanduser( os.path.join('~', distrib.UserDirectory.userSocketName)) self['port'] = 'unix:' + path else: self['port'] = 'tcp:8080'
class Options(usage.Options): """ Define the options accepted by the I{twistd web} plugin. """ synopsis = "[web options]" optParameters = [ [ "logfile", "l", None, "Path to web CLF (Combined Log Format) log file." ], [ "certificate", "c", "server.pem", "(DEPRECATED: use --listen) " "SSL certificate to use for HTTPS. ", ], [ "privkey", "k", "server.pem", "(DEPRECATED: use --listen) " "SSL certificate to use for HTTPS.", ], ] optFlags = [ [ "notracebacks", "n", ("(DEPRECATED: Tracebacks are disabled by default. " "See --enable-tracebacks to turn them on."), ], [ "display-tracebacks", "", ("Show uncaught exceptions during rendering tracebacks to " "the client. WARNING: This may be a security risk and " "expose private data!"), ], ] optFlags.append([ "personal", "", "Instead of generating a webserver, generate a " "ResourcePublisher which listens on the port given by " "--listen, or ~/%s " % (distrib.UserDirectory.userSocketName, ) + "if --listen is not specified.", ]) compData = usage.Completions( optActions={ "logfile": usage.CompleteFiles("*.log"), "certificate": usage.CompleteFiles("*.pem"), "privkey": usage.CompleteFiles("*.pem"), }) longdesc = """\ This starts a webserver. If you specify no arguments, it will be a demo webserver that has the Test class from twisted.web.demo in it.""" def __init__(self): usage.Options.__init__(self) self["indexes"] = [] self["root"] = None self["extraHeaders"] = [] self["ports"] = [] self["port"] = self["https"] = None def opt_port(self, port): """ (DEPRECATED: use --listen) Strports description of port to start the server on """ msg = deprecate.getDeprecationWarningString( self.opt_port, incremental.Version("Twisted", 18, 4, 0)) warnings.warn(msg, category=DeprecationWarning, stacklevel=2) self["port"] = port opt_p = opt_port def opt_https(self, port): """ (DEPRECATED: use --listen) Port to listen on for Secure HTTP. """ msg = deprecate.getDeprecationWarningString( self.opt_https, incremental.Version("Twisted", 18, 4, 0)) warnings.warn(msg, category=DeprecationWarning, stacklevel=2) self["https"] = port def opt_listen(self, port): """ Add an strports description of port to start the server on. [default: tcp:8080] """ self["ports"].append(port) def opt_index(self, indexName): """ Add the name of a file used to check for directory indexes. [default: index, index.html] """ self["indexes"].append(indexName) opt_i = opt_index def opt_user(self): """ Makes a server with ~/public_html and ~/.twistd-web-pb support for users. """ self["root"] = distrib.UserDirectory() opt_u = opt_user def opt_path(self, path): """ <path> is either a specific file or a directory to be set as the root of the web server. Use this if you have a directory full of HTML, cgi, epy, or rpy files or any other files that you want to be served up raw. """ self["root"] = static.File(os.path.abspath(path)) self["root"].processors = { ".epy": script.PythonScript, ".rpy": script.ResourceScript, } self["root"].processors[".cgi"] = twcgi.CGIScript def opt_processor(self, proc): """ `ext=class' where `class' is added as a Processor for files ending with `ext'. """ if not isinstance(self["root"], static.File): raise usage.UsageError( "You can only use --processor after --path.") ext, klass = proc.split("=", 1) self["root"].processors[ext] = reflect.namedClass(klass) def opt_class(self, className): """ Create a Resource subclass with a zero-argument constructor. """ classObj = reflect.namedClass(className) self["root"] = classObj() def opt_resource_script(self, name): """ An .rpy file to be used as the root resource of the webserver. """ self["root"] = script.ResourceScriptWrapper(name) def opt_wsgi(self, name): """ The FQPN of a WSGI application object to serve as the root resource of the webserver. """ try: application = reflect.namedAny(name) except (AttributeError, ValueError): raise usage.UsageError(f"No such WSGI application: {name!r}") pool = threadpool.ThreadPool() reactor.callWhenRunning(pool.start) reactor.addSystemEventTrigger("after", "shutdown", pool.stop) self["root"] = wsgi.WSGIResource(reactor, pool, application) def opt_mime_type(self, defaultType): """ Specify the default mime-type for static files. """ if not isinstance(self["root"], static.File): raise usage.UsageError( "You can only use --mime_type after --path.") self["root"].defaultType = defaultType opt_m = opt_mime_type def opt_allow_ignore_ext(self): """ Specify whether or not a request for 'foo' should return 'foo.ext' """ if not isinstance(self["root"], static.File): raise usage.UsageError("You can only use --allow_ignore_ext " "after --path.") self["root"].ignoreExt("*") def opt_ignore_ext(self, ext): """ Specify an extension to ignore. These will be processed in order. """ if not isinstance(self["root"], static.File): raise usage.UsageError("You can only use --ignore_ext " "after --path.") self["root"].ignoreExt(ext) def opt_add_header(self, header): """ Specify an additional header to be included in all responses. Specified as "HeaderName: HeaderValue". """ name, value = header.split(":", 1) self["extraHeaders"].append((name.strip(), value.strip())) def postOptions(self): """ Set up conditional defaults and check for dependencies. If SSL is not available but an HTTPS server was configured, raise a L{UsageError} indicating that this is not possible. If no server port was supplied, select a default appropriate for the other options supplied. """ if self["port"] is not None: self["ports"].append(self["port"]) if self["https"] is not None: try: reflect.namedModule("OpenSSL.SSL") except ImportError: raise usage.UsageError("SSL support not installed") sslStrport = "ssl:port={}:privateKey={}:certKey={}".format( self["https"], self["privkey"], self["certificate"], ) self["ports"].append(sslStrport) if len(self["ports"]) == 0: if self["personal"]: path = os.path.expanduser( os.path.join("~", distrib.UserDirectory.userSocketName)) self["ports"].append("unix:" + path) else: self["ports"].append("tcp:8080")
class Options(usage.Options, strcred.AuthOptionMixin): synopsis = "[options]" optParameters = [ [ "pop3s", "S", 0, "Port to start the POP3-over-SSL server on (0 to disable). " "DEPRECATED: use " "'--pop3 ssl:port:privateKey=pkey.pem:certKey=cert.pem'" ], [ "certificate", "c", None, "Certificate file to use for SSL connections. " "DEPRECATED: use " "'--pop3 ssl:port:privateKey=pkey.pem:certKey=cert.pem'" ], [ "relay", "R", None, "Relay messages according to their envelope 'To', using " "the given path as a queue directory." ], [ "hostname", "H", None, "The hostname by which to identify this server." ], ] optFlags = [ ["esmtp", "E", "Use RFC 1425/1869 SMTP extensions"], [ "disable-anonymous", None, "Disallow non-authenticated SMTP connections" ], ["no-pop3", None, "Disable the default POP3 server."], ["no-smtp", None, "Disable the default SMTP server."], ] _protoDefaults = { "pop3": 8110, "smtp": 8025, } compData = usage.Completions( optActions={ "hostname": usage.CompleteHostnames(), "certificate": usage.CompleteFiles("*.pem") }) longdesc = "This creates a mail.tap file that can be used by twistd." def __init__(self): usage.Options.__init__(self) self.service = mail.MailService() self.last_domain = None for service in self._protoDefaults: self[service] = [] def addEndpoint(self, service, description, certificate=None): """ Given a 'service' (pop3 or smtp), add an endpoint. """ self[service].append(_toEndpoint(description, certificate=certificate)) def opt_pop3(self, description): """ Add a pop3 port listener on the specified endpoint. You can listen on multiple ports by specifying multiple --pop3 options. For backwards compatibility, a bare TCP port number can be specified, but this is deprecated. [SSL Example: ssl:8995:privateKey=mycert.pem] [default: tcp:8110] """ self.addEndpoint('pop3', description) opt_p = opt_pop3 def opt_smtp(self, description): """ Add an smtp port listener on the specified endpoint. You can listen on multiple ports by specifying multiple --smtp options For backwards compatibility, a bare TCP port number can be specified, but this is deprecated. [SSL Example: ssl:8465:privateKey=mycert.pem] [default: tcp:8025] """ self.addEndpoint('smtp', description) opt_s = opt_smtp def opt_passwordfile(self, filename): """ Specify a file containing username:password login info for authenticated ESMTP connections. (DEPRECATED; see --help-auth instead) """ ch = checkers.OnDiskUsernamePasswordDatabase(filename) self.service.smtpPortal.registerChecker(ch) msg = deprecate.getDeprecationWarningString( self.opt_passwordfile, versions.Version('twisted.mail', 11, 0, 0)) warnings.warn(msg, category=DeprecationWarning, stacklevel=2) opt_P = opt_passwordfile def opt_default(self): """Make the most recently specified domain the default domain.""" if self.last_domain: self.service.addDomain('', self.last_domain) else: raise usage.UsageError( "Specify a domain before specifying using --default") opt_D = opt_default def opt_maildirdbmdomain(self, domain): """generate an SMTP/POP3 virtual domain which saves to \"path\" """ try: name, path = domain.split('=') except ValueError: raise usage.UsageError( "Argument to --maildirdbmdomain must be of the form 'name=path'" ) self.last_domain = maildir.MaildirDirdbmDomain(self.service, os.path.abspath(path)) self.service.addDomain(name, self.last_domain) opt_d = opt_maildirdbmdomain def opt_user(self, user_pass): """add a user/password to the last specified domains """ try: user, password = user_pass.split('=', 1) except ValueError: raise usage.UsageError( "Argument to --user must be of the form 'user=password'") if self.last_domain: self.last_domain.addUser(user, password) else: raise usage.UsageError("Specify a domain before specifying users") opt_u = opt_user def opt_bounce_to_postmaster(self): """undelivered mails are sent to the postmaster """ self.last_domain.postmaster = 1 opt_b = opt_bounce_to_postmaster def opt_aliases(self, filename): """Specify an aliases(5) file to use for this domain""" if self.last_domain is not None: if mail.IAliasableDomain.providedBy(self.last_domain): aliases = alias.loadAliasFile(self.service.domains, filename) self.last_domain.setAliasGroup(aliases) self.service.monitor.monitorFile( filename, AliasUpdater(self.service.domains, self.last_domain)) else: raise usage.UsageError("%s does not support alias files" % (self.last_domain.__class__.__name__, )) else: raise usage.UsageError( "Specify a domain before specifying aliases") opt_A = opt_aliases def _getEndpoints(self, reactor, service): """ Return a list of endpoints for the specified service, constructing defaults if necessary. @param reactor: If any endpoints are created, this is the reactor with which they are created. @param service: A key into self indicating the type of service to retrieve endpoints for. This is either C{"pop3"} or C{"smtp"}. @return: A C{list} of C{IServerStreamEndpoint} providers corresponding to the command line parameters that were specified for C{service}. If none were and the protocol was not explicitly disabled with a I{--no-*} option, a default endpoint for the service is created using C{self._protoDefaults}. """ if service == 'pop3' and self['pop3s'] and len(self[service]) == 1: # The single endpoint here is the POP3S service we added in # postOptions. Include the default endpoint alongside it. return self[service] + [ endpoints.TCP4ServerEndpoint(reactor, self._protoDefaults[service]) ] elif self[service]: # For any non-POP3S case, if there are any services set up, just # return those. return self[service] elif self['no-' + service]: # If there are no services, but the service was explicitly disabled, # return nothing. return [] else: # Otherwise, return the old default service. return [ endpoints.TCP4ServerEndpoint(reactor, self._protoDefaults[service]) ] def postOptions(self): from twisted.internet import reactor if self['pop3s']: if not self['certificate']: raise usage.UsageError("Cannot specify --pop3s without " "--certificate") elif not os.path.exists(self['certificate']): raise usage.UsageError("Certificate file %r does not exist." % self['certificate']) else: self.addEndpoint('pop3', self['pop3s'], certificate=self['certificate']) if self['esmtp'] and self['hostname'] is None: raise usage.UsageError("--esmtp requires --hostname") # If the --auth option was passed, this will be present -- otherwise, # it won't be, which is also a perfectly valid state. if 'credCheckers' in self: for ch in self['credCheckers']: self.service.smtpPortal.registerChecker(ch) if not self['disable-anonymous']: self.service.smtpPortal.registerChecker( checkers.AllowAnonymousAccess()) anything = False for service in self._protoDefaults: self[service] = self._getEndpoints(reactor, service) if self[service]: anything = True if not anything: raise usage.UsageError("You cannot disable all protocols")
class Options(usage.Options, strcred.AuthOptionMixin): """ An options list parser for twistd mail. @type synopsis: L{bytes} @ivar synopsis: A description of options for use in the usage message. @type optParameters: L{list} of L{list} of (0) L{bytes}, (1) L{bytes}, (2) L{object}, (3) L{bytes}, (4) L{None} or callable which takes L{bytes} and returns L{object} @ivar optParameters: Information about supported parameters. See L{Options <twisted.python.usage.Options>} for details. @type optFlags: L{list} of L{list} of (0) L{bytes}, (1) L{bytes} or L{None}, (2) L{bytes} @ivar optFlags: Information about supported flags. See L{Options <twisted.python.usage.Options>} for details. @type _protoDefaults: L{dict} mapping L{bytes} to L{int} @ivar _protoDefaults: A mapping of default service to port. @type compData: L{Completions <usage.Completions>} @ivar compData: Metadata for the shell tab completion system. @type longdesc: L{bytes} @ivar longdesc: A long description of the plugin for use in the usage message. @type service: L{MailService} @ivar service: The email service. @type last_domain: L{IDomain} provider or L{None} @ivar last_domain: The most recently specified domain. """ synopsis = "[options]" optParameters = [ [ "pop3s", "S", 0, "Port to start the POP3-over-SSL server on (0 to disable). " "DEPRECATED: use " "'--pop3 ssl:port:privateKey=pkey.pem:certKey=cert.pem'" ], [ "certificate", "c", None, "Certificate file to use for SSL connections. " "DEPRECATED: use " "'--pop3 ssl:port:privateKey=pkey.pem:certKey=cert.pem'" ], [ "relay", "R", None, "Relay messages according to their envelope 'To', using " "the given path as a queue directory." ], [ "hostname", "H", None, "The hostname by which to identify this server." ], ] optFlags = [ ["esmtp", "E", "Use RFC 1425/1869 SMTP extensions"], [ "disable-anonymous", None, "Disallow non-authenticated SMTP connections" ], ["no-pop3", None, "Disable the default POP3 server."], ["no-smtp", None, "Disable the default SMTP server."], ] _protoDefaults = { "pop3": 8110, "smtp": 8025, } compData = usage.Completions( optActions={ "hostname": usage.CompleteHostnames(), "certificate": usage.CompleteFiles("*.pem") }) longdesc = """ An SMTP / POP3 email server plugin for twistd. Examples: 1. SMTP and POP server twistd mail --maildirdbmdomain=example.com=/tmp/example.com --user=joe=password Starts an SMTP server that only accepts emails to [email protected] and saves them to /tmp/example.com. Also starts a POP mail server which will allow a client to log in using username: [email protected] and password: password and collect any email that has been saved in /tmp/example.com. 2. SMTP relay twistd mail --relay=/tmp/mail_queue Starts an SMTP server that accepts emails to any email address and relays them to an appropriate remote SMTP server. Queued emails will be temporarily stored in /tmp/mail_queue. """ def __init__(self): """ Parse options and create a mail service. """ usage.Options.__init__(self) self.service = mail.MailService() self.last_domain = None for service in self._protoDefaults: self[service] = [] def addEndpoint(self, service, description, certificate=None): """ Add an endpoint to a service. @type service: L{bytes} @param service: A service, either C{b'smtp'} or C{b'pop3'}. @type description: L{bytes} @param description: An endpoint description string or a TCP port number. @type certificate: L{bytes} or L{None} @param certificate: The name of a file containing an SSL certificate. """ self[service].append(_toEndpoint(description, certificate=certificate)) def opt_pop3(self, description): """ Add a POP3 port listener on the specified endpoint. You can listen on multiple ports by specifying multiple --pop3 options. For backwards compatibility, a bare TCP port number can be specified, but this is deprecated. [SSL Example: ssl:8995:privateKey=mycert.pem] [default: tcp:8110] """ self.addEndpoint('pop3', description) opt_p = opt_pop3 def opt_smtp(self, description): """ Add an SMTP port listener on the specified endpoint. You can listen on multiple ports by specifying multiple --smtp options. For backwards compatibility, a bare TCP port number can be specified, but this is deprecated. [SSL Example: ssl:8465:privateKey=mycert.pem] [default: tcp:8025] """ self.addEndpoint('smtp', description) opt_s = opt_smtp def opt_default(self): """ Make the most recently specified domain the default domain. """ if self.last_domain: self.service.addDomain('', self.last_domain) else: raise usage.UsageError( "Specify a domain before specifying using --default") opt_D = opt_default def opt_maildirdbmdomain(self, domain): """ Generate an SMTP/POP3 virtual domain. This option requires an argument of the form 'NAME=PATH' where NAME is the DNS domain name for which email will be accepted and where PATH is a the filesystem path to a Maildir folder. [Example: 'example.com=/tmp/example.com'] """ try: name, path = domain.split('=') except ValueError: raise usage.UsageError( "Argument to --maildirdbmdomain must be of the form 'name=path'" ) self.last_domain = maildir.MaildirDirdbmDomain(self.service, os.path.abspath(path)) self.service.addDomain(name, self.last_domain) opt_d = opt_maildirdbmdomain def opt_user(self, user_pass): """ Add a user and password to the last specified domain. """ try: user, password = user_pass.split('=', 1) except ValueError: raise usage.UsageError( "Argument to --user must be of the form 'user=password'") if self.last_domain: self.last_domain.addUser(user, password) else: raise usage.UsageError("Specify a domain before specifying users") opt_u = opt_user def opt_bounce_to_postmaster(self): """ Send undeliverable messages to the postmaster. """ self.last_domain.postmaster = 1 opt_b = opt_bounce_to_postmaster def opt_aliases(self, filename): """ Specify an aliases(5) file to use for the last specified domain. """ if self.last_domain is not None: if mail.IAliasableDomain.providedBy(self.last_domain): aliases = alias.loadAliasFile(self.service.domains, filename) self.last_domain.setAliasGroup(aliases) self.service.monitor.monitorFile( filename, AliasUpdater(self.service.domains, self.last_domain)) else: raise usage.UsageError("%s does not support alias files" % (self.last_domain.__class__.__name__, )) else: raise usage.UsageError( "Specify a domain before specifying aliases") opt_A = opt_aliases def _getEndpoints(self, reactor, service): """ Return a list of endpoints for the specified service, constructing defaults if necessary. If no endpoints were configured for the service and the protocol was not explicitly disabled with a I{--no-*} option, a default endpoint for the service is created. @type reactor: L{IReactorTCP <twisted.internet.interfaces.IReactorTCP>} provider @param reactor: If any endpoints are created, the reactor with which they are created. @type service: L{bytes} @param service: The type of service for which to retrieve endpoints, either C{b'pop3'} or C{b'smtp'}. @rtype: L{list} of L{IStreamServerEndpoint <twisted.internet.interfaces.IStreamServerEndpoint>} provider @return: The endpoints for the specified service as configured by the command line parameters. """ if service == 'pop3' and self['pop3s'] and len(self[service]) == 1: # The single endpoint here is the POP3S service we added in # postOptions. Include the default endpoint alongside it. return self[service] + [ endpoints.TCP4ServerEndpoint(reactor, self._protoDefaults[service]) ] elif self[service]: # For any non-POP3S case, if there are any services set up, just # return those. return self[service] elif self['no-' + service]: # If there are no services, but the service was explicitly disabled, # return nothing. return [] else: # Otherwise, return the old default service. return [ endpoints.TCP4ServerEndpoint(reactor, self._protoDefaults[service]) ] def postOptions(self): """ Check the validity of the specified set of options and configure authentication. @raise UsageError: When the set of options is invalid. """ from twisted.internet import reactor if self['pop3s']: if not self['certificate']: raise usage.UsageError("Cannot specify --pop3s without " "--certificate") elif not os.path.exists(self['certificate']): raise usage.UsageError("Certificate file %r does not exist." % self['certificate']) else: self.addEndpoint('pop3', self['pop3s'], certificate=self['certificate']) if self['esmtp'] and self['hostname'] is None: raise usage.UsageError("--esmtp requires --hostname") # If the --auth option was passed, this will be present -- otherwise, # it won't be, which is also a perfectly valid state. if 'credCheckers' in self: for ch in self['credCheckers']: self.service.smtpPortal.registerChecker(ch) if not self['disable-anonymous']: self.service.smtpPortal.registerChecker( checkers.AllowAnonymousAccess()) anything = False for service in self._protoDefaults: self[service] = self._getEndpoints(reactor, service) if self[service]: anything = True if not anything: raise usage.UsageError("You cannot disable all protocols")
class Options(usage.Options): synopsis = """%s [options] [path to test].py """ % (os.path.basename(sys.argv[0]), ) longdesc = ("ooniprobe loads and executes a suite or a set of suites of" " network tests. These are loaded from modules, packages and" " files listed on the command line") optFlags = [["help", "h"], ["resume", "r"], ["no-collector", "n"], ["no-geoip", "g"], ["list", "s"], ["printdeck", "p"], ["verbose", "v"]] optParameters = [ ["reportfile", "o", None, "report file name"], [ "testdeck", "i", None, "Specify as input a test deck: a yaml file containing the tests to run and their arguments" ], [ "collector", "c", None, "Address of the collector of test results. This option should not be used, but you should always use a bouncer." ], [ "bouncer", "b", 'httpo://nkvphnp3p6agi5qq.onion', "Address of the bouncer for test helpers. default: httpo://nkvphnp3p6agi5qq.onion" ], ["logfile", "l", None, "log file name"], ["pcapfile", "O", None, "pcap file name"], [ "configfile", "f", None, "Specify a path to the ooniprobe configuration file" ], [ "datadir", "d", None, "Specify a path to the ooniprobe data directory" ], [ "annotations", "a", None, "Annotate the report with a key:value[, key:value] format." ] ] compData = usage.Completions(extraActions=[ usage.CompleteFiles( "*.py", descr="file | module | package | TestCase | testMethod", repeat=True) ], ) tracer = None def __init__(self): self['test'] = None usage.Options.__init__(self) def opt_spew(self): """ Print an insanely verbose log of everything that happens. Useful when debugging freezes or locks in complex code. """ sys.settrace(spewer) def opt_version(self): """ Display the ooniprobe version and exit. """ print "ooniprobe version:", __version__ sys.exit(0) def parseArgs(self, *args): if self['testdeck'] or self['list']: return try: self['test_file'] = args[0] self['subargs'] = args[1:] except: raise usage.UsageError("No test filename specified!")
class Options(usage.Options): synopsis = """%s [options] [path to test].py """ % (os.path.basename(sys.argv[0]), ) longdesc = ("ooniprobe loads and executes a suite or a set of suites of" " network tests. These are loaded from modules, packages and" " files listed on the command line.") optFlags = [["help", "h"], ["no-collector", "n", "Disable writing to collector"], ["no-yamloo", "N", "Disable writing to YAML file"], ["no-geoip", "g", "Disable geoip lookup on start"], [ "list", "s", "List the currently installed ooniprobe " "nettests" ], [ "printdeck", "p", "Print the equivalent deck for the " "provided command" ], ["verbose", "v", "Show more verbose information"]] optParameters = [ ["reportfile", "o", None, "Specify the report file name to write to."], [ "testdeck", "i", None, "Specify as input a test deck: a yaml file " "containing the tests to run and their " "arguments." ], [ "collector", "c", None, "Specify the address of the collector for " "test results. In most cases a user will " "prefer to specify a bouncer over this." ], [ "bouncer", "b", None, "Specify the bouncer used to " "obtain the address of the " "collector and test helpers." ], ["logfile", "l", None, "Write to this logs to this filename."], [ "pcapfile", "O", None, "Write a PCAP of the ooniprobe session to " "this filename." ], [ "configfile", "f", None, "Specify a path to the ooniprobe " "configuration file." ], [ "datadir", "d", None, "Specify a path to the ooniprobe data " "directory." ], [ "annotations", "a", None, "Annotate the report with a key:value[, " "key:value] format." ], [ "preferred-backend", "P", None, "Set the preferred backend to use " "when submitting results and/or " "communicating with test helpers. " "Can be either onion, " "https or cloudfront" ], [ "queue", "Q", None, "AMQP Queue URL amqp://user:pass@host:port/vhost/queue" ] ] compData = usage.Completions(extraActions=[ usage.CompleteFiles( "*.py", descr="file | module | package | TestCase | testMethod", repeat=True) ], ) tracer = None def __init__(self): usage.Options.__init__(self) def getUsage(self, width=None): return super(Options, self).getUsage(width) + """ To get started you may want to run: $ oonideckgen This will tell you how to run ooniprobe :) """ def opt_spew(self): """ Print an insanely verbose log of everything that happens. Useful when debugging freezes or locks in complex code. """ from twisted.python.util import spewer sys.settrace(spewer) def opt_version(self): """ Display the ooniprobe version and exit. """ print "ooniprobe version:", __version__ sys.exit(0) def parseArgs(self, *args): if self['testdeck'] or self['list']: return try: self['test_file'] = args[0] self['subargs'] = args[1:] except: raise usage.UsageError("No test filename specified!")
class ServerOptions(usage.Options, ReactorSelectionMixin): longdesc = ("twistd reads a twisted.application.service.Application out " "of a file and runs it.") optFlags = [[ 'savestats', None, "save the Stats object rather than the text output of " "the profiler." ], ['no_save', 'o', "do not save state on shutdown"], ['encrypted', 'e', "The specified tap/aos file is encrypted."]] optParameters = [ ['logfile', 'l', None, "log to a specified file, - for stdout"], [ 'logger', None, None, "A fully-qualified name to a log observer factory to use " "for the initial log observer. Takes precedence over " "--logfile and --syslog (when available)." ], [ 'profile', 'p', None, "Run in profile mode, dumping results to specified file" ], [ 'profiler', None, "hotshot", "Name of the profiler to use (%s)." % ", ".join(AppProfiler.profilers) ], ['file', 'f', 'twistd.tap', "read the given .tap file"], [ 'python', 'y', None, "read an application from within a Python file " "(implies -o)" ], [ 'source', 's', None, "Read an application from a .tas file (AOT format)." ], ['rundir', 'd', '.', 'Change to a supplied directory before running'] ] compData = usage.Completions(mutuallyExclusive=[("file", "python", "source")], optActions={ "file": usage.CompleteFiles("*.tap"), "python": usage.CompleteFiles("*.(tac|py)"), "source": usage.CompleteFiles("*.tas"), "rundir": usage.CompleteDirs() }) _getPlugins = staticmethod(plugin.getPlugins) def __init__(self, *a, **kw): self['debug'] = False usage.Options.__init__(self, *a, **kw) def opt_debug(self): """ Run the application in the Python Debugger (implies nodaemon), sending SIGUSR2 will drop into debugger """ defer.setDebugging(True) failure.startDebugMode() self['debug'] = True opt_b = opt_debug def opt_spew(self): """ Print an insanely verbose log of everything that happens. Useful when debugging freezes or locks in complex code.""" sys.settrace(util.spewer) try: import threading except ImportError: return threading.settrace(util.spewer) def parseOptions(self, options=None): if options is None: options = sys.argv[1:] or ["--help"] usage.Options.parseOptions(self, options) def postOptions(self): if self.subCommand or self['python']: self['no_save'] = True if self['logger'] is not None: try: self['logger'] = namedAny(self['logger']) except Exception as e: raise usage.UsageError( "Logger '%s' could not be imported: %s" % (self['logger'], e)) def subCommands(self): plugins = self._getPlugins(service.IServiceMaker) self.loadedPlugins = {} for plug in sorted(plugins, key=attrgetter('tapname')): self.loadedPlugins[plug.tapname] = plug yield ( plug.tapname, None, # Avoid resolving the options attribute right away, in case # it's a property with a non-trivial getter (eg, one which # imports modules). lambda plug=plug: plug.options(), plug.description) subCommands = property(subCommands)
class _BasicOptions(object): """ Basic options shared between trial and its local workers. """ synopsis = """%s [options] [[file|package|module|TestCase|testmethod]...] """ % (os.path.basename(sys.argv[0]), ) longdesc = ("trial loads and executes a suite of unit tests, obtained " "from modules, packages and files listed on the command line.") optFlags = [ ["help", "h"], ["no-recurse", "N", "Don't recurse into packages"], ['help-orders', None, "Help on available test running orders"], [ 'help-reporters', None, "Help on available output plugins (reporters)" ], [ "rterrors", "e", "realtime errors, print out tracebacks as " "soon as they occur" ], ["unclean-warnings", None, "Turn dirty reactor errors into warnings"], [ "force-gc", None, "Have Trial run gc.collect() before and " "after each test case." ], [ "exitfirst", "x", "Exit after the first non-successful result (cannot be " "specified along with --jobs)." ], ] optParameters = [ [ "order", "o", None, "Specify what order to run test cases and methods. " "See --help-orders for more info.", _checkKnownRunOrder ], [ "random", "z", None, "Run tests in random order using the specified seed" ], [ 'temp-directory', None, '_trial_temp', 'Path to use as working directory for tests.' ], [ 'reporter', None, 'verbose', 'The reporter to use for this test run. See --help-reporters for ' 'more info.' ] ] compData = usage.Completions( optActions={ "order": usage.CompleteList(_runOrders), "reporter": _reporterAction, "logfile": usage.CompleteFiles(descr="log file name"), "random": usage.Completer(descr="random seed") }, extraActions=[ usage.CompleteFiles( "*.py", descr="file | module | package | TestCase | testMethod", repeat=True) ], ) fallbackReporter = reporter.TreeReporter tracer = None def __init__(self): self['tests'] = [] usage.Options.__init__(self) def coverdir(self): """ Return a L{FilePath} representing the directory into which coverage results should be written. """ coverdir = 'coverage' result = FilePath(self['temp-directory']).child(coverdir) print("Setting coverage directory to %s." % (result.path, )) return result # TODO: Some of the opt_* methods on this class have docstrings and some do # not. This is mostly because usage.Options's currently will replace # any intended output in optFlags and optParameters with the # docstring. See #6427. When that is fixed, all methods should be # given docstrings (and it should be verified that those with # docstrings already have content suitable for printing as usage # information). def opt_coverage(self): """ Generate coverage information in the coverage file in the directory specified by the temp-directory option. """ import trace self.tracer = trace.Trace(count=1, trace=0) sys.settrace(self.tracer.globaltrace) self['coverage'] = True def opt_testmodule(self, filename): """ Filename to grep for test cases (-*- test-case-name). """ # If the filename passed to this parameter looks like a test module # we just add that to the test suite. # # If not, we inspect it for an Emacs buffer local variable called # 'test-case-name'. If that variable is declared, we try to add its # value to the test suite as a module. # # This parameter allows automated processes (like Buildbot) to pass # a list of files to Trial with the general expectation of "these files, # whatever they are, will get tested" if not os.path.isfile(filename): sys.stderr.write("File %r doesn't exist\n" % (filename, )) return filename = os.path.abspath(filename) if isTestFile(filename): self['tests'].append(filename) else: self['tests'].extend(getTestModules(filename)) def opt_spew(self): """ Print an insanely verbose log of everything that happens. Useful when debugging freezes or locks in complex code. """ sys.settrace(spewer) def opt_help_orders(self): synopsis = ("Trial can attempt to run test cases and their methods in " "a few different orders. You can select any of the " "following options using --order=<foo>.\n") print(synopsis) for name, (description, _) in sorted(_runOrders.items()): print(' ', name, '\t', description) sys.exit(0) def opt_help_reporters(self): synopsis = ("Trial's output can be customized using plugins called " "Reporters. You can\nselect any of the following " "reporters using --reporter=<foo>\n") print(synopsis) for p in plugin.getPlugins(itrial.IReporter): print(' ', p.longOpt, '\t', p.description) sys.exit(0) def opt_disablegc(self): """ Disable the garbage collector """ self["disablegc"] = True gc.disable() def opt_tbformat(self, opt): """ Specify the format to display tracebacks with. Valid formats are 'plain', 'emacs', and 'cgitb' which uses the nicely verbose stdlib cgitb.text function """ try: self['tbformat'] = TBFORMAT_MAP[opt] except KeyError: raise usage.UsageError( "tbformat must be 'plain', 'emacs', or 'cgitb'.") def opt_recursionlimit(self, arg): """ see sys.setrecursionlimit() """ try: sys.setrecursionlimit(int(arg)) except (TypeError, ValueError): raise usage.UsageError( "argument to recursionlimit must be an integer") else: self["recursionlimit"] = int(arg) def opt_random(self, option): try: self['random'] = long(option) except ValueError: raise usage.UsageError( "Argument to --random must be a positive integer") else: if self['random'] < 0: raise usage.UsageError( "Argument to --random must be a positive integer") elif self['random'] == 0: self['random'] = long(time.time() * 100) def opt_without_module(self, option): """ Fake the lack of the specified modules, separated with commas. """ self["without-module"] = option for module in option.split(","): if module in sys.modules: warnings.warn("Module '%s' already imported, " "disabling anyway." % (module, ), category=RuntimeWarning) sys.modules[module] = None def parseArgs(self, *args): self['tests'].extend(args) def _loadReporterByName(self, name): for p in plugin.getPlugins(itrial.IReporter): qual = "%s.%s" % (p.module, p.klass) if p.longOpt == name: return reflect.namedAny(qual) raise usage.UsageError("Only pass names of Reporter plugins to " "--reporter. See --help-reporters for " "more info.") def postOptions(self): # Only load reporters now, as opposed to any earlier, to avoid letting # application-defined plugins muck up reactor selecting by importing # t.i.reactor and causing the default to be installed. self['reporter'] = self._loadReporterByName(self['reporter']) if 'tbformat' not in self: self['tbformat'] = 'default' if self['order'] is not None and self['random'] is not None: raise usage.UsageError( "You can't specify --random when using --order")
class Options(usage.Options): synopsis = """%s [options] [path to test].py """ % (os.path.basename(sys.argv[0]),) longdesc = ("ooniprobe loads and executes a suite or a set of suites of" " network tests. These are loaded from modules, packages and" " files listed on the command line.") optFlags = [["help", "h"], ["no-collector", "n", "Disable writing to collector"], ["no-njson", "N", "Disable writing to disk"], ["no-geoip", "g", "Don't include geoip related information inside of the report." "Note: Even with this option your IP address can be disclosed in the report."], ["list", "s", "List the currently installed ooniprobe " "nettests"], ["verbose", "v", "Show more verbose information"], ["web-ui", "w", "Start the web UI"], ["initialize", "z", "Initialize ooniprobe to begin running " "it"], ["info", None, "Print system wide info and exit"] ] optParameters = [ ["reportfile", "o", None, "Specify the report file name to write " "to."], ["testdeck", "i", None, "Specify as input a test deck: a yaml file " "containing the tests to run and their " "arguments."], ["collector", "c", None, "Specify the address of the collector for " "test results. In most cases a user will " "prefer to specify a bouncer over this."], ["bouncer", "b", None, "Specify the bouncer used to " "obtain the address of the " "collector and test helpers."], ["logfile", "l", None, "Write to this logs to this filename."], ["pcapfile", "O", None, "Write a PCAP of the ooniprobe session to " "this filename."], ["configfile", "f", None, "Specify a path to the ooniprobe " "configuration file."], ["datadir", "d", None, "Specify a path to the ooniprobe data " "directory."], ["annotations", "a", None, "Annotate the report with a key:value[, " "key:value] format."], ["preferred-backend", "P", None, "Set the preferred backend to use " "when submitting results and/or " "communicating with test helpers. " "Can be either onion, " "https or cloudfront"], ["queue", "Q", None, "AMQP Queue URL " "amqp://*****:*****@host:port/vhost/queue"] ] compData = usage.Completions( extraActions=[usage.CompleteFiles( "*.py", descr="file | module | package | TestCase | testMethod", repeat=True)],) tracer = None def __init__(self): usage.Options.__init__(self) def opt_spew(self): """ Print an insanely verbose log of everything that happens. Useful when debugging freezes or locks in complex code. """ from twisted.python.util import spewer sys.settrace(spewer) def opt_version(self): """ Display the ooniprobe version and exit. """ print "ooniprobe version:", __version__ sys.exit(0) def parseArgs(self, *args): flag_opts = ['testdeck', 'list', 'web-ui', 'info'] if any([self[opt] for opt in flag_opts]): return try: self['test_file'] = args[0] self['subargs'] = args[1:] except: raise usage.UsageError("No test filename specified!")