CLI: simplify argument-passing, use options= for everthing, including stdout

This commit is contained in:
Brian Warner 2008-08-01 11:46:24 -07:00
parent 6d3ec390b0
commit f181a0458a
12 changed files with 140 additions and 122 deletions

View File

@ -204,131 +204,78 @@ subCommands = [
["repl", None, ReplOptions, "Open a python interpreter"], ["repl", None, ReplOptions, "Open a python interpreter"],
] ]
def mkdir(config, stdout, stderr): def mkdir(options):
from allmydata.scripts import tahoe_mkdir from allmydata.scripts import tahoe_mkdir
rc = tahoe_mkdir.mkdir(config['node-url'], rc = tahoe_mkdir.mkdir(options)
config.aliases,
config.where,
stdout, stderr)
return rc return rc
def add_alias(config, stdout, stderr): def add_alias(options):
from allmydata.scripts import tahoe_add_alias from allmydata.scripts import tahoe_add_alias
rc = tahoe_add_alias.add_alias(config['node-directory'], rc = tahoe_add_alias.add_alias(options)
config.alias,
config.cap,
stdout, stderr)
return rc return rc
def list_aliases(config, stdout, stderr): def list_aliases(options):
from allmydata.scripts import tahoe_add_alias from allmydata.scripts import tahoe_add_alias
rc = tahoe_add_alias.list_aliases(config['node-directory'], rc = tahoe_add_alias.list_aliases(options)
stdout, stderr)
return rc return rc
def list(config, stdout, stderr): def list(options):
from allmydata.scripts import tahoe_ls from allmydata.scripts import tahoe_ls
rc = tahoe_ls.list(config['node-url'], rc = tahoe_ls.list(options)
config.aliases,
config.where,
config,
stdout, stderr)
return rc return rc
def get(config, stdout, stderr): def get(options):
from allmydata.scripts import tahoe_get from allmydata.scripts import tahoe_get
rc = tahoe_get.get(config['node-url'], rc = tahoe_get.get(options)
config.aliases,
config.from_file,
config.to_file,
stdout, stderr)
if rc == 0: if rc == 0:
if config.to_file is None: if options.to_file is None:
# be quiet, since the file being written to stdout should be # be quiet, since the file being written to stdout should be
# proof enough that it worked, unless the user is unlucky # proof enough that it worked, unless the user is unlucky
# enough to have picked an empty file # enough to have picked an empty file
pass pass
else: else:
print >>stderr, "%s retrieved and written to %s" % \ print >>options.stderr, "%s retrieved and written to %s" % \
(config.from_file, config.to_file) (options.from_file, options.to_file)
return rc return rc
def put(config, stdout, stderr, stdin=sys.stdin): def put(options):
from allmydata.scripts import tahoe_put from allmydata.scripts import tahoe_put
if config['quiet']: rc = tahoe_put.put(options)
verbosity = 0
else:
verbosity = 2
rc = tahoe_put.put(config['node-url'],
config.aliases,
config.from_file,
config.to_file,
config['mutable'],
verbosity,
stdin, stdout, stderr)
return rc return rc
def cp(config, stdout, stderr): def cp(options):
from allmydata.scripts import tahoe_cp from allmydata.scripts import tahoe_cp
if config['quiet']: rc = tahoe_cp.copy(options)
verbosity = 0
else:
verbosity = 2
rc = tahoe_cp.copy(config['node-url'],
config,
config.aliases,
config.sources,
config.destination,
verbosity,
stdout, stderr)
return rc return rc
def rm(config, stdout, stderr): def rm(options):
from allmydata.scripts import tahoe_rm from allmydata.scripts import tahoe_rm
if config['quiet']: rc = tahoe_rm.rm(options)
verbosity = 0
else:
verbosity = 2
rc = tahoe_rm.rm(config['node-url'],
config.aliases,
config.where,
verbosity,
stdout, stderr)
return rc return rc
def mv(config, stdout, stderr): def mv(options):
from allmydata.scripts import tahoe_mv from allmydata.scripts import tahoe_mv
rc = tahoe_mv.mv(config['node-url'], rc = tahoe_mv.mv(options, mode="move")
config.aliases,
config.from_file,
config.to_file,
stdout, stderr,
mode="move")
return rc return rc
def ln(config, stdout, stderr): def ln(options):
from allmydata.scripts import tahoe_mv from allmydata.scripts import tahoe_mv
rc = tahoe_mv.mv(config['node-url'], rc = tahoe_mv.mv(options, mode="link")
config.aliases,
config.from_file,
config.to_file,
stdout, stderr,
mode="link")
return rc return rc
def webopen(config, stdout, stderr): def webopen(options):
import urllib, webbrowser import urllib, webbrowser
nodeurl = config['node-url'] nodeurl = options['node-url']
if nodeurl[-1] != "/": if nodeurl[-1] != "/":
nodeurl += "/" nodeurl += "/"
root_cap = config.aliases["tahoe"] root_cap = options.aliases["tahoe"]
url = nodeurl + "uri/%s/" % urllib.quote(root_cap) url = nodeurl + "uri/%s/" % urllib.quote(root_cap)
if config['vdrive_pathname']: if options['vdrive_pathname']:
url += urllib.quote(config['vdrive_pathname']) url += urllib.quote(options['vdrive_pathname'])
webbrowser.open(url) webbrowser.open(url)
return 0 return 0
def repl(config, stdout, stderr): def repl(options):
import code import code
return code.interact() return code.interact()

View File

@ -4,6 +4,11 @@ from twisted.python import usage
class BaseOptions: class BaseOptions:
# unit tests can override these to point at StringIO instances
stdin = sys.stdin
stdout = sys.stdout
stderr = sys.stderr
optFlags = [ optFlags = [
["quiet", "q", "Operate silently."], ["quiet", "q", "Operate silently."],
["version", "V", "Display version numbers and exit."], ["version", "V", "Display version numbers and exit."],

View File

@ -23,7 +23,9 @@ class Options(BaseOptions, usage.Options):
if not hasattr(self, 'subOptions'): if not hasattr(self, 'subOptions'):
raise usage.UsageError("must specify a command") raise usage.UsageError("must specify a command")
def runner(argv, run_by_human=True, stdout=sys.stdout, stderr=sys.stderr, def runner(argv,
run_by_human=True,
stdin=sys.stdin, stdout=sys.stdout, stderr=sys.stderr,
install_node_control=True, additional_commands=None): install_node_control=True, additional_commands=None):
config = Options() config = Options()
@ -53,6 +55,10 @@ def runner(argv, run_by_human=True, stdout=sys.stdout, stderr=sys.stderr,
if config['quiet']: if config['quiet']:
stdout = StringIO() stdout = StringIO()
so.stdout = stdout
so.stderr = stderr
so.stdin = stdin
rc = 0 rc = 0
if command in create_node.dispatch: if command in create_node.dispatch:
for basedir in so.basedirs: for basedir in so.basedirs:
@ -63,7 +69,7 @@ def runner(argv, run_by_human=True, stdout=sys.stdout, stderr=sys.stderr,
elif command in debug.dispatch: elif command in debug.dispatch:
rc = debug.dispatch[command](so, stdout, stderr) rc = debug.dispatch[command](so, stdout, stderr)
elif command in cli.dispatch: elif command in cli.dispatch:
rc = cli.dispatch[command](so, stdout, stderr) rc = cli.dispatch[command](so)
elif command in keygen.dispatch: elif command in keygen.dispatch:
rc = keygen.dispatch[command](so, stdout, stderr) rc = keygen.dispatch[command](so, stdout, stderr)
elif command in ac_dispatch: elif command in ac_dispatch:

View File

@ -3,7 +3,12 @@ import os.path
from allmydata import uri from allmydata import uri
from allmydata.scripts.common import get_aliases from allmydata.scripts.common import get_aliases
def add_alias(nodedir, alias, cap, stdout, stderr): def add_alias(options):
nodedir = options['node-directory']
alias = options.alias
cap = options.cap
stdout = options.stdout
stderr = options.stderr
aliasfile = os.path.join(nodedir, "private", "aliases") aliasfile = os.path.join(nodedir, "private", "aliases")
cap = uri.from_string_dirnode(cap).to_string() cap = uri.from_string_dirnode(cap).to_string()
assert ":" not in alias assert ":" not in alias
@ -15,7 +20,10 @@ def add_alias(nodedir, alias, cap, stdout, stderr):
print >>stdout, "Alias '%s' added" % (alias,) print >>stdout, "Alias '%s' added" % (alias,)
return 0 return 0
def list_aliases(nodedir, stdout, stderr): def list_aliases(options):
nodedir = options['node-directory']
stdout = options.stdout
stderr = options.stderr
aliases = get_aliases(nodedir) aliases = get_aliases(nodedir)
alias_names = sorted(aliases.keys()) alias_names = sorted(aliases.keys())
max_width = max([len(name) for name in alias_names] + [0]) max_width = max([len(name) for name in alias_names] + [0])

View File

@ -397,29 +397,31 @@ class TahoeDirectoryTarget:
POST(url, body) POST(url, body)
class Copier: class Copier:
def __init__(self, nodeurl, config, aliases,
verbosity, stdout, stderr, def do_copy(self, options, progressfunc=None):
progressfunc=None): if options['quiet']:
verbosity = 0
else:
verbosity = 2
nodeurl = options['node-url']
if nodeurl[-1] != "/": if nodeurl[-1] != "/":
nodeurl += "/" nodeurl += "/"
self.nodeurl = nodeurl self.nodeurl = nodeurl
self.progressfunc = progressfunc self.progressfunc = progressfunc
self.config = config self.options = options
self.aliases = aliases self.aliases = options.aliases
self.verbosity = verbosity self.verbosity = verbosity
if config["verbose"] and not self.progressfunc: self.stdout = options.stdout
self.stderr = options.stderr
if options["verbose"] and not self.progressfunc:
def progress(message): def progress(message):
print >>stderr, message print >>self.stderr, message
self.progressfunc = progress self.progressfunc = progress
self.stdout = stdout
self.stderr = stderr
self.cache = {} self.cache = {}
source_specs = options.sources
def to_stderr(self, text): destination_spec = options.destination
print >>self.stderr, text recursive = self.options["recursive"]
def do_copy(self, source_specs, destination_spec):
recursive = self.config["recursive"]
target = self.get_target_info(destination_spec) target = self.get_target_info(destination_spec)
@ -470,6 +472,9 @@ class Copier:
self.to_stderr("unknown target") self.to_stderr("unknown target")
return 1 return 1
def to_stderr(self, text):
print >>self.stderr, text
def get_target_info(self, destination_spec): def get_target_info(self, destination_spec):
rootcap, path = get_alias(self.aliases, destination_spec, None) rootcap, path = get_alias(self.aliases, destination_spec, None)
if rootcap == DefaultAliasMarker: if rootcap == DefaultAliasMarker:
@ -705,7 +710,5 @@ class Copier:
return graphs return graphs
def copy(nodeurl, config, aliases, sources, destination, def copy(options):
verbosity, stdout, stderr): return Copier().do_copy(options)
c = Copier(nodeurl, config, aliases, verbosity, stdout, stderr)
return c.do_copy(sources, destination)

View File

@ -3,7 +3,14 @@ import urllib
from allmydata.scripts.common import get_alias, DEFAULT_ALIAS, escape_path from allmydata.scripts.common import get_alias, DEFAULT_ALIAS, escape_path
from allmydata.scripts.common_http import do_http from allmydata.scripts.common_http import do_http
def get(nodeurl, aliases, from_file, to_file, stdout, stderr): def get(options):
nodeurl = options['node-url']
aliases = options.aliases
from_file = options.from_file
to_file = options.to_file
stdout = options.stdout
stderr = options.stderr
if nodeurl[-1] != "/": if nodeurl[-1] != "/":
nodeurl += "/" nodeurl += "/"
rootcap, path = get_alias(aliases, from_file, DEFAULT_ALIAS) rootcap, path = get_alias(aliases, from_file, DEFAULT_ALIAS)

View File

@ -4,7 +4,13 @@ import simplejson
from allmydata.scripts.common import get_alias, DEFAULT_ALIAS, escape_path from allmydata.scripts.common import get_alias, DEFAULT_ALIAS, escape_path
from allmydata.scripts.common_http import do_http from allmydata.scripts.common_http import do_http
def list(nodeurl, aliases, where, config, stdout, stderr): def list(options):
nodeurl = options['node-url']
aliases = options.aliases
where = options.where
stdout = options.stdout
stderr = options.stderr
if not nodeurl.endswith("/"): if not nodeurl.endswith("/"):
nodeurl += "/" nodeurl += "/"
if where.endswith("/"): if where.endswith("/"):
@ -26,7 +32,7 @@ def list(nodeurl, aliases, where, config, stdout, stderr):
resp.read()) resp.read())
data = resp.read() data = resp.read()
if config['json']: if options['json']:
print >>stdout, data print >>stdout, data
return return
@ -90,16 +96,16 @@ def list(nodeurl, aliases, where, config, stdout, stderr):
uri = rw_uri or ro_uri uri = rw_uri or ro_uri
line = [] line = []
if config["long"]: if options["long"]:
line.append(t0+t1+t2+t3) line.append(t0+t1+t2+t3)
line.append(size) line.append(size)
line.append(ctime_s) line.append(ctime_s)
if not config["classify"]: if not options["classify"]:
classify = "" classify = ""
line.append(name + classify) line.append(name + classify)
if config["uri"]: if options["uri"]:
line.append(uri) line.append(uri)
if config["readonly-uri"]: if options["readonly-uri"]:
line.append(ro_uri or "-") line.append(ro_uri or "-")
rows.append(line) rows.append(line)

View File

@ -3,7 +3,12 @@ import urllib
from allmydata.scripts.common_http import do_http, check_http_error from allmydata.scripts.common_http import do_http, check_http_error
from allmydata.scripts.common import get_alias, DEFAULT_ALIAS from allmydata.scripts.common import get_alias, DEFAULT_ALIAS
def mkdir(nodeurl, aliases, where, stdout, stderr): def mkdir(options):
nodeurl = options['node-url']
aliases = options.aliases
where = options.where
stdout = options.stdout
stderr = options.stderr
if not nodeurl.endswith("/"): if not nodeurl.endswith("/"):
nodeurl += "/" nodeurl += "/"
if where: if where:

View File

@ -7,7 +7,14 @@ from allmydata.scripts.common_http import do_http
# this script is used for both 'mv' and 'ln' # this script is used for both 'mv' and 'ln'
def mv(nodeurl, aliases, from_file, to_file, stdout, stderr, mode="move"): def mv(options, mode="move"):
nodeurl = options['node-url']
aliases = options.aliases
from_file = options.from_file
to_file = options.to_file
stdout = options.stdout
stderr = options.stderr
if nodeurl[-1] != "/": if nodeurl[-1] != "/":
nodeurl += "/" nodeurl += "/"
rootcap, path = get_alias(aliases, from_file, DEFAULT_ALIAS) rootcap, path = get_alias(aliases, from_file, DEFAULT_ALIAS)

View File

@ -4,13 +4,25 @@ import urllib
from allmydata.scripts.common_http import do_http from allmydata.scripts.common_http import do_http
from allmydata.scripts.common import get_alias, DEFAULT_ALIAS, escape_path from allmydata.scripts.common import get_alias, DEFAULT_ALIAS, escape_path
def put(nodeurl, aliases, from_file, to_file, mutable, def put(options):
verbosity, stdin, stdout, stderr):
""" """
@param verbosity: 0, 1, or 2, meaning quiet, verbose, or very verbose @param verbosity: 0, 1, or 2, meaning quiet, verbose, or very verbose
@return: a Deferred which eventually fires with the exit code @return: a Deferred which eventually fires with the exit code
""" """
nodeurl = options['node-url']
aliases = options.aliases
from_file = options.from_file
to_file = options.to_file
mutable = options['mutable']
if options['quiet']:
verbosity = 0
else:
verbosity = 2
stdin = options.stdin
stdout = options.stdout
stderr = options.stderr
if nodeurl[-1] != "/": if nodeurl[-1] != "/":
nodeurl += "/" nodeurl += "/"
if to_file: if to_file:

View File

@ -3,12 +3,22 @@ import urllib
from allmydata.scripts.common_http import do_http from allmydata.scripts.common_http import do_http
from allmydata.scripts.common import get_alias, DEFAULT_ALIAS, escape_path from allmydata.scripts.common import get_alias, DEFAULT_ALIAS, escape_path
def rm(nodeurl, aliases, where, verbosity, stdout, stderr): def rm(options):
""" """
@param verbosity: 0, 1, or 2, meaning quiet, verbose, or very verbose @param verbosity: 0, 1, or 2, meaning quiet, verbose, or very verbose
@return: a Deferred which eventually fires with the exit code @return: a Deferred which eventually fires with the exit code
""" """
nodeurl = options['node-url']
aliases = options.aliases
where = options.where
if options['quiet']:
verbosity = 0
else:
verbosity = 2
stdout = options.stdout
stderr = options.stderr
if nodeurl[-1] != "/": if nodeurl[-1] != "/":
nodeurl += "/" nodeurl += "/"
rootcap, path = get_alias(aliases, where, DEFAULT_ALIAS) rootcap, path = get_alias(aliases, where, DEFAULT_ALIAS)

View File

@ -1344,9 +1344,9 @@ class SystemTest(SystemTestMixin, unittest.TestCase):
def _check_ls((out,err), expected_children, unexpected_children=[]): def _check_ls((out,err), expected_children, unexpected_children=[]):
self.failUnlessEqual(err, "") self.failUnlessEqual(err, "")
for s in expected_children: for s in expected_children:
self.failUnless(s in out, s) self.failUnless(s in out, (s,out))
for s in unexpected_children: for s in unexpected_children:
self.failIf(s in out, s) self.failIf(s in out, (s,out))
def _check_ls_root((out,err)): def _check_ls_root((out,err)):
self.failUnless("personal" in out) self.failUnless("personal" in out)
@ -1442,8 +1442,10 @@ class SystemTest(SystemTestMixin, unittest.TestCase):
o.parseOptions(args) o.parseOptions(args)
stdin = StringIO(data) stdin = StringIO(data)
stdout, stderr = StringIO(), StringIO() stdout, stderr = StringIO(), StringIO()
d = threads.deferToThread(cli.put, o, o.stdin = stdin
stdout=stdout, stderr=stderr, stdin=stdin) o.stdout = stdout
o.stderr = stderr
d = threads.deferToThread(cli.put, o)
def _done(res): def _done(res):
return stdout.getvalue(), stderr.getvalue() return stdout.getvalue(), stderr.getvalue()
d.addCallback(_done) d.addCallback(_done)