def __init__(self, cli, name, min_args=None, max_args=None, usage=None): self.cli = cli self.name = name self.min_args = min_args self.max_args = max_args if usage is None: usage = """ Usage: %%prog [main_options] %s For help on [main_options] run %%prog with no args. Executes the %s command.""".strip() % (name, name) self.option_parser = OptionParser( usage=usage, io_manager=self.cli.context.io_manager, error_prefix=name + ' command: ')
def __init__(self, commands=None): #: The overall CLIContext containing attributes generated by the #: initial main_options parsing. #: #: The available attributes are: #: #: ============== ==================================================== #: cdn True if the CDN URL should be used instead of the #: default Storage URL. #: client_manager The :py:class:`swiftly.client.manager.ClientManager` #: to use for obtaining clients. #: concurrency Number of concurrent actions to allow. #: io_manager The :py:class:`swiftly.cli.iomanager.IOManager` to #: use for input and output. #: eventlet True if Eventlet is in use. #: original_args The original args used by the CLI. #: original_begin The original time.time() when the CLI was called. #: verbose Function to call when you want to (optionally) emit #: verbose output. ``verbose(msg, *args)`` where the #: output will be constructed with ``msg % args``. #: verbosity Level of verbosity. Just None or 1 right now. #: ============== ==================================================== self.context = CLIContext() self.context.verbose = None self.context.io_manager = IOManager() #: A dictionary of the available commands and their CLICommand #: instances. self.commands = {} if commands is None: commands = COMMANDS for command in commands: mod, cls = command.rsplit('.', 1) cls = getattr(__import__(mod, fromlist=[cls]), cls) inst = cls(self) self.commands[inst.name] = inst #: The main :py:class:`OptionParser`. self.option_parser = OptionParser(version=VERSION, usage=""" Usage: %prog [options] <command> [command_options] [args] With all these main Swiftly options, you can also specify them in a configuration file or in an environment variable. The configuration file option name is the long name of the command line option with any dashes replaced with underscores, for example: --auth-url becomes auth_url The environment variable name is the long name of the command line option in uppercase prefixed with SWIFTLY_, for example: --auth-url becomes SWIFTLY_AUTH_URL Command line options override environment variables which override configuration file variables. """.strip(), io_manager=self.context.io_manager) self.option_parser.add_option('-h', dest='help', action='store_true', help='Shows this help text.') self.option_parser.add_option( '--conf', dest='conf', metavar='PATH', help='Path to the configuration file to use. Default: ' '~/.swiftly.conf') self.option_parser.add_option( '-A', '--auth-url', dest='auth_url', metavar='URL', help='URL to auth system, example: ' 'https://identity.api.rackspacecloud.com/v2.0') self.option_parser.add_option( '-U', '--auth-user', dest='auth_user', metavar='USER', help='User name for auth system, example: test:tester') self.option_parser.add_option( '-K', '--auth-key', dest='auth_key', metavar='KEY', help='Key for auth system, example: testing') self.option_parser.add_option( '-T', '--auth-tenant', dest='auth_tenant', metavar='TENANT', help='Tenant name for auth system, example: test If not ' 'specified and needed, the auth user will be used.') self.option_parser.add_option( '--auth-methods', dest='auth_methods', metavar='name[,name[...]]', help='Auth methods to use with the auth system, example: ' 'auth2key,auth2password,auth2password_force_tenant,auth1 The ' 'best order will try to be determined for you; but if you ' 'notice it keeps making useless auth attempts and that ' 'drives you crazy, you can override that here. All the ' 'available auth methods are listed in the example.') self.option_parser.add_option( '--region', dest='region', metavar='VALUE', help='Region to use, if supported by auth, example: DFW Default: ' 'default region specified by the auth response.') self.option_parser.add_option( '-D', '--direct', dest='direct', metavar='PATH', help='Uses direct connect method to access Swift. Requires access ' 'to rings and backend servers. The PATH is the account ' 'path, example: /v1/AUTH_test') self.option_parser.add_option( '-L', '--local', dest='local', metavar='PATH', help='Uses the local file system method to access a fake Swift. ' 'The PATH is the path on the local file system where the ' 'fake Swift stores its data.') self.option_parser.add_option('-P', '--proxy', dest='proxy', metavar='URL', help='Uses the given HTTP proxy URL.') self.option_parser.add_option( '-B', '--bypass-url', dest='bypass_url', metavar='URL', help='Override Swift endpoint URL provided during authentication.') self.option_parser.add_option( '-S', '--snet', dest='snet', action='store_true', help='Prepends the storage URL host name with "snet-". Mostly ' 'only useful with Rackspace Cloud Files and Rackspace ' 'ServiceNet.') self.option_parser.add_option( '--no-snet', dest='no_snet', action='store_true', help='Disables the above snet value if it had been set true in ' 'the environment or configuration file.') self.option_parser.add_option( '-R', '--retries', dest='retries', metavar='INTEGER', help='Indicates how many times to retry the request on a server ' 'error. Default: 4') self.option_parser.add_option( '-C', '--cache-auth', dest='cache_auth', action='store_true', help='If set true, the storage URL and auth token are cached in ' 'your OS temporary directory as <user>.swiftly for reuse. If ' 'there are already cached values, they are used without ' 'authenticating first.') self.option_parser.add_option( '--no-cache-auth', dest='no_cache_auth', action='store_true', help='Disables the above cache-auth value if it had been set ' 'true in the environment or configuration file.') self.option_parser.add_option( '--cdn', dest='cdn', action='store_true', help='Directs requests to the CDN management interface.') self.option_parser.add_option( '--no-cdn', dest='no_cdn', action='store_true', help='Disables the above cdn value if it had been set true in the ' 'environment or configuration file.') self.option_parser.add_option( '--concurrency', dest='concurrency', metavar='INTEGER', help='Sets the the number of actions that can be done ' 'simultaneously when possible (currently requires using ' 'Eventlet too). Default: 1 Note that some nested actions may ' 'amplify the number of concurrent actions. For instance, a ' 'put of an entire directory will use up to this number of ' 'concurrent actions. A put of a segmented object will use up ' 'to this number of concurrent actions. But, if a directory ' 'structure put is uploading segmented objects, this nesting ' 'could cause up to INTEGER * INTEGER concurrent actions.') self.option_parser.add_option( '--eventlet', dest='eventlet', action='store_true', help='Enables Eventlet, if installed. This is disabled by default ' 'if Eventlet is not installed or is less than version 0.11.0 ' '(because older Swiftly+Eventlet tends to use excessive CPU.') self.option_parser.add_option( '--no-eventlet', dest='no_eventlet', action='store_true', help='Disables Eventlet, even if installed and version 0.11.0 or ' 'greater.') self.option_parser.add_option( '-v', '--verbose', dest='verbose', action='store_true', help='Causes output to standard error indicating actions being ' 'taken. These output lines will be prefixed with VERBOSE and ' 'will also include the number of seconds elapsed since ' 'the command started.') self.option_parser.add_option( '--no-verbose', dest='no_verbose', action='store_true', help='Disables the above verbose value if it had been set true in ' 'the environment or configuration file.') self.option_parser.add_option( '-O', '--direct-object-ring', dest='direct_object_ring', metavar='PATH', help='The current object ring of the cluster being pinged. This ' 'will enable direct client to use this ring for all the ' 'queries. Use of this also requires the main Swift code ' 'is installed and importable.') self.option_parser.add_option( '-k', '--insecure', dest='insecure', action='store_true', help='Allows "insecure" SSL connections for python >= 2.7.9') self.option_parser.raw_epilog = 'Commands:\n' for name in sorted(self.commands): command = self.commands[name] lines = command.option_parser.get_usage().split('\n') main_line = ' ' + lines[0].split(']', 1)[1].strip() for x in moves.range(4): lines.pop(0) for x, line in enumerate(lines): if not line: lines = lines[:x] break if len(main_line) < 24: initial_indent = main_line + ' ' * (24 - len(main_line)) else: self.option_parser.raw_epilog += main_line + '\n' initial_indent = ' ' * 24 self.option_parser.raw_epilog += textwrap.fill( ' '.join(lines), width=79, initial_indent=initial_indent, subsequent_indent=' ' * 24) + '\n'