Better messages and return codes in applications

Use stderr and return codes >0 when it makes sense.
Loose return code conventions:
* 1 for generic errors
* 2 for user input errors
* 3 for remote errors (not found, etc.)
* 4 for not implemented
This commit is contained in:
Laurent Bachelier 2011-05-03 01:02:00 +02:00
commit 8075d538f0
18 changed files with 168 additions and 149 deletions

View file

@ -118,7 +118,7 @@ def main():
try: try:
script = imp.load_module("scripts.%s" % fname, f, tmpfile, desc) script = imp.load_module("scripts.%s" % fname, f, tmpfile, desc)
except ImportError, e: except ImportError, e:
print >> sys.stderr, "Unable to load the %s script (%s)" \ print >>sys.stderr, "Unable to load the %s script (%s)" \
% (fname, e) % (fname, e)
else: else:
print "Loaded %s" % fname print "Loaded %s" % fname

View file

@ -146,7 +146,7 @@ class Boobank(ReplApplication):
id, backend_name = self.parse_id(id) id, backend_name = self.parse_id(id)
if not id: if not id:
print >>sys.stderr, 'Error: please give an account ID (hint: use list command)' print >>sys.stderr, 'Error: please give an account ID (hint: use list command)'
return 1 return 2
names = (backend_name,) if backend_name is not None else None names = (backend_name,) if backend_name is not None else None
def do(backend): def do(backend):
@ -204,7 +204,7 @@ class Boobank(ReplApplication):
id_from, backend_name_from = self.parse_id(id_from) id_from, backend_name_from = self.parse_id(id_from)
if not id_to: if not id_to:
print >>sys.stderr, 'Error: listing recipient is not implemented yet' print >>sys.stderr, 'Error: listing recipient is not implemented yet'
return return 4
id_to, backend_name_to = self.parse_id(id_to) id_to, backend_name_to = self.parse_id(id_to)
@ -212,11 +212,11 @@ class Boobank(ReplApplication):
amount = float(amount) amount = float(amount)
except (TypeError,ValueError): except (TypeError,ValueError):
print >>sys.stderr, 'Error: please give a decimal amount to transfer' print >>sys.stderr, 'Error: please give a decimal amount to transfer'
return 1 return 2
if backend_name_from != backend_name_to: if backend_name_from != backend_name_to:
print >>sys.stderr, "Transfer between different backends is not implemented" print >>sys.stderr, "Transfer between different backends is not implemented"
return return 4
else: else:
backend_name = backend_name_from backend_name = backend_name_from

View file

@ -117,7 +117,7 @@ class Event(object):
elif line.startswith('h3=. '): elif line.startswith('h3=. '):
m = re.match('h3=. Event finished. Winner is "(.*)":/users/(\d+)\!', line) m = re.match('h3=. Event finished. Winner is "(.*)":/users/(\d+)\!', line)
if not m: if not m:
print 'Unable to parse h3=: %s' % line print >>sys.stderr, 'Unable to parse h3=: %s' % line
continue continue
self.winner = Member(int(m.group(2)), m.group(1)) self.winner = Member(int(m.group(2)), m.group(1))
elif line.startswith('h2. '): elif line.startswith('h2. '):
@ -125,7 +125,7 @@ class Event(object):
elif line.startswith('h3. '): elif line.startswith('h3. '):
m = re.match('h3. "(.*)":/users/(\d+)', line) m = re.match('h3. "(.*)":/users/(\d+)', line)
if not m: if not m:
print 'Unable to parse user "%s"' % line print >>sys.stderr, 'Unable to parse user "%s"' % line
continue continue
member = Member(int(m.group(2)), m.group(1)) member = Member(int(m.group(2)), m.group(1))
if member.id == self.my_id: if member.id == self.my_id:
@ -164,7 +164,7 @@ class Event(object):
elif line.startswith('[['): elif line.startswith('[['):
m = re.match('\[\[(\w+)\]\]\|\[\[(\w+)\]\]\|(.*)\|', line) m = re.match('\[\[(\w+)\]\]\|\[\[(\w+)\]\]\|(.*)\|', line)
if not m: if not m:
print 'Unable to parse task: "%s"' % line print >>sys.stderr, 'Unable to parse task: "%s"' % line
continue continue
task = Task(m.group(1), m.group(2)) task = Task(m.group(1), m.group(2))
member.tasks.append(task) member.tasks.append(task)
@ -467,7 +467,8 @@ class Boobathon(ReplApplication):
print 'Event is now closed. Winner is %s!' % self.winner.name print 'Event is now closed. Winner is %s!' % self.winner.name
return return
print '"%s" not found' % name print >>sys.stderr, '"%s" not found' % name
return 3
def complete_edit(self, text, line, *ignored): def complete_edit(self, text, line, *ignored):
args = line.split(' ') args = line.split(' ')
@ -481,8 +482,8 @@ class Boobathon(ReplApplication):
Edit information about you or about event. Edit information about you or about event.
""" """
if not line: if not line:
print 'Syntax: edit [event | me]' print >>sys.stderr, 'Syntax: edit [event | me]'
return return 2
self.event.load() self.event.load()
if line == 'event': if line == 'event':
@ -491,12 +492,13 @@ class Boobathon(ReplApplication):
elif line == 'me': elif line == 'me':
mem = self.event.get_me() mem = self.event.get_me()
if not mem: if not mem:
print 'You haven\'t joined the event.' print >>sys.stderr, 'You haven\'t joined the event.'
return return 1
self.edit_member(mem) self.edit_member(mem)
self.save_event('Member edited') self.save_event('Member edited')
else: else:
print 'Unable to edit "%s"' % line print >>sys.stderr, 'Unable to edit "%s"' % line
return 1
def do_info(self, line): def do_info(self, line):
""" """
@ -552,12 +554,12 @@ class Boobathon(ReplApplication):
""" """
self.event.load() self.event.load()
if self.event.backend.browser.get_userid() in self.event.members: if self.event.backend.browser.get_userid() in self.event.members:
print 'You have already joined this event.' print >>sys.stderr, 'You have already joined this event.'
return return 1
if self.event.is_closed(): if self.event.is_closed():
print 'Boobathon is closed.' print >>sys.stderr, "Boobathon is closed."
return return 1
m = Member(self.event.backend.browser.get_userid(), None) m = Member(self.event.backend.browser.get_userid(), None)
self.edit_member(m) self.edit_member(m)
@ -573,17 +575,18 @@ class Boobathon(ReplApplication):
self.event.load() self.event.load()
if self.event.currently_in_event(): if self.event.currently_in_event():
print 'Unable to leave during the event, loser!' print >>sys.stderr, 'Unable to leave during the event, loser!'
return return 1
if self.event.is_closed(): if self.event.is_closed():
print 'Boobathon is closed.' print >>sys.stderr, "Boobathon is closed."
return return 1
try: try:
self.event.members.pop(self.event.backend.browser.get_userid()) self.event.members.pop(self.event.backend.browser.get_userid())
except KeyError: except KeyError:
print 'You have not joined this event.' print >>sys.stderr, "You have not joined this event."
return 1
else: else:
self.save_event('Left the event') self.save_event('Left the event')
@ -596,23 +599,24 @@ class Boobathon(ReplApplication):
self.event.load() self.event.load()
mem = self.event.get_me() mem = self.event.get_me()
if not mem: if not mem:
print 'You have not joined this event.' print >>sys.stderr, "You have not joined this event."
return return 1
if self.event.is_closed(): if self.event.is_closed():
print 'Boobathon is closed.' print >>sys.stderr, "Boobathon is closed."
return return 1
try: try:
task_id = int(line) task_id = int(line)
except ValueError: except ValueError:
print 'The task ID might be a number' print >>sys.stderr, 'The task ID should be a number'
return return 2
try: try:
task = mem.tasks.pop(task_id) task = mem.tasks.pop(task_id)
except IndexError: except IndexError:
print 'Unable to find task #%d' % task_id print >>sys.stderr, 'Unable to find task #%d' % task_id
return 1
else: else:
print 'Removing task #%d (%s,%s).' % (task_id, task.backend, task.capability) print 'Removing task #%d (%s,%s).' % (task_id, task.backend, task.capability)
self.save_event('Remove task') self.save_event('Remove task')
@ -626,25 +630,25 @@ class Boobathon(ReplApplication):
self.event.load() self.event.load()
mem = self.event.get_me() mem = self.event.get_me()
if not mem: if not mem:
print 'You have not joined this event.' print >>sys.stderr, "You have not joined this event."
return return 1
if self.event.is_closed(): if self.event.is_closed():
print 'Boobathon is closed.' print >>sys.stderr, "Boobathon is closed."
return return 1
backend, capability = self.parse_command_args(line, 2, 2) backend, capability = self.parse_command_args(line, 2, 2)
if not backend[0].isupper(): if not backend[0].isupper():
print 'The backend name "%s" needs to start with a capital.' % backend print >>sys.stderr, 'The backend name "%s" needs to start with a capital.' % backend
return return 2
if not capability.startswith('Cap') or not capability[3].isupper(): if not capability.startswith('Cap') or not capability[3].isupper():
print '"%s" is not a right capability name.' % capability print >>sys.stderr, '"%s" is not a proper capability name (must start with Cap).' % capability
return return 2
for task in mem.tasks: for task in mem.tasks:
if (task.backend,task.capability) == (backend,capability): if (task.backend,task.capability) == (backend,capability):
print 'A task already exists for that.' print >>sys.stderr, "A task already exists for that."
return return 1
task = Task(backend, capability) task = Task(backend, capability)
mem.tasks.append(task) mem.tasks.append(task)
@ -660,16 +664,16 @@ class Boobathon(ReplApplication):
self.event.load() self.event.load()
mem = self.event.get_me() mem = self.event.get_me()
if not mem: if not mem:
print 'You have not joined this event.' print >>sys.stderr, "You have not joined this event."
return return 1
if len(mem.tasks) == 0: if len(mem.tasks) == 0:
print "You don't have any task to do." print >>sys.stderr, "You don't have any task to do."
return return 1
if not self.event.currently_in_event(): if not self.event.currently_in_event():
print "You can't start a task, we are not in event." print >>sys.stderr, "You can't start a task, we are not in event."
return return 1
if line.isdigit(): if line.isdigit():
task_id = int(line) task_id = int(line)
@ -687,11 +691,12 @@ class Boobathon(ReplApplication):
if (i == task_id or task_id < 0) and task.status == task.STATUS_NONE: if (i == task_id or task_id < 0) and task.status == task.STATUS_NONE:
break break
else: else:
print 'Task not found.' print >>sys.stderr, 'Task not found.'
return 3
if task.status == task.STATUS_DONE: if task.status == task.STATUS_DONE:
print 'Task is already done.' print >>sys.stderr, 'Task is already done.'
return return 1
task.status = task.STATUS_PROGRESS task.status = task.STATUS_PROGRESS
mem.tasks.remove(task) mem.tasks.remove(task)
@ -707,12 +712,12 @@ class Boobathon(ReplApplication):
self.event.load() self.event.load()
mem = self.event.get_me() mem = self.event.get_me()
if not mem: if not mem:
print 'You have not joined this event.' print >>sys.stderr, "You have not joined this event."
return return 1
if self.event.is_closed(): if self.event.is_closed():
print 'Boobathon is closed.' print >>sys.stderr, "Boobathon is closed."
return return 1
for i, task in enumerate(mem.tasks): for i, task in enumerate(mem.tasks):
if task.status == task.STATUS_PROGRESS: if task.status == task.STATUS_PROGRESS:
@ -724,11 +729,13 @@ class Boobathon(ReplApplication):
self.save_event('Task accomplished') self.save_event('Task accomplished')
else: else:
task.status = task.STATUS_NONE task.status = task.STATUS_NONE
print 'Oops, you are out of event. Canceling the task...' print >>sys.stderr, 'Oops, you are out of event. Canceling the task...'
self.save_event('Cancel task') self.save_event('Cancel task')
return 1
return return
print "There isn't any task in progress." print >>sys.stderr, "There isn't any task in progress."
return 1
def do_cancel(self, line): def do_cancel(self, line):
""" """
@ -739,12 +746,12 @@ class Boobathon(ReplApplication):
self.event.load() self.event.load()
mem = self.event.get_me() mem = self.event.get_me()
if not mem: if not mem:
print 'You have not joined this event.' print >>sys.stderr, "You have not joined this event."
return return 1
if self.event.is_closed(): if self.event.is_closed():
print 'Boobathon is closed.' print >>sys.stderr, "Boobathon is closed."
return return 1
for task in mem.tasks: for task in mem.tasks:
if task.status == task.STATUS_PROGRESS: if task.status == task.STATUS_PROGRESS:
@ -753,7 +760,8 @@ class Boobathon(ReplApplication):
self.save_event('Cancel task') self.save_event('Cancel task')
return return
print "There isn't any task in progress." print >>sys.stderr, "There isn't any task in progress."
return 1
def load_default_backends(self): def load_default_backends(self):
@ -769,7 +777,7 @@ class Boobathon(ReplApplication):
return return
if not self.check_loaded_backends({'url': 'https://symlink.me'}): if not self.check_loaded_backends({'url': 'https://symlink.me'}):
print 'Ok, so leave now, fag.' print "Ok, so leave now, fag."
sys.exit(0) sys.exit(0)
def is_backend_loadable(self, backend): def is_backend_loadable(self, backend):

View file

@ -342,8 +342,8 @@ class Boobmsg(ReplApplication):
Read a message Read a message
""" """
if len(arg) == 0: if len(arg) == 0:
print 'Please give a message ID.' print >>sys.stderr, 'Please give a message ID.'
return return 2
try: try:
message = self.messages[int(arg) - 1] message = self.messages[int(arg) - 1]
@ -355,6 +355,8 @@ class Boobmsg(ReplApplication):
return return
if not self.interactive: if not self.interactive:
print 'Oops, you need to be in interactive mode to read messages' print >>sys.stderr, 'Oops, you need to be in interactive mode to read messages'
return 1
else: else:
print 'Message not found' print >>sys.stderr, 'Message not found'
return 3

View file

@ -102,8 +102,8 @@ class Galleroob(ReplApplication):
gallery = result gallery = result
if not gallery: if not gallery:
print 'Gallery not found: %s' % _id print >>sys.stderr, 'Gallery not found: %s' % _id
return 1 return 3
backend.fillobj(gallery, ('title',)) backend.fillobj(gallery, ('title',))
if dest is None: if dest is None:
@ -127,7 +127,7 @@ class Galleroob(ReplApplication):
if img.data is None: if img.data is None:
backend.fillobj(img, ('url','data')) backend.fillobj(img, ('url','data'))
if img.data is None: if img.data is None:
print "Couldn't get page %d, exiting" % i print >>sys.stderr, "Couldn't get page %d, exiting" % i
break break
ext = search(r"\.([^\.]{1,5})$", img.url) ext = search(r"\.([^\.]{1,5})$", img.url)
@ -156,6 +156,6 @@ class Galleroob(ReplApplication):
gallery = self.get_object(_id, 'get_gallery') gallery = self.get_object(_id, 'get_gallery')
if not gallery: if not gallery:
print >>sys.stderr, 'Gallery not found: %s' % _id print >>sys.stderr, 'Gallery not found: %s' % _id
return return 3
self.format(gallery) self.format(gallery)
self.flush() self.flush()

View file

@ -37,9 +37,7 @@ class Geolooc(ReplApplication):
def main(self, argv): def main(self, argv):
if len(argv) < 2: if len(argv) < 2:
print >>sys.stderr, 'Syntax: %s ipaddr' % argv[0] print >>sys.stderr, 'Syntax: %s ipaddr' % argv[0]
return 1 return 2
for backend, location in self.do('get_location', argv[1]): for backend, location in self.do('get_location', argv[1]):
self.format(location) self.format(location)
return 0

View file

@ -133,7 +133,7 @@ class HaveSex(ReplApplication):
def edit_optims(self, backend_names, optims_names, stop=False): def edit_optims(self, backend_names, optims_names, stop=False):
if optims_names is None: if optims_names is None:
print >>sys.stderr, 'Error: missing parameters.' print >>sys.stderr, 'Error: missing parameters.'
return 1 return 2
for optim_name in optims_names.split(): for optim_name in optims_names.split():
backends_optims = {} backends_optims = {}
@ -165,7 +165,7 @@ class HaveSex(ReplApplication):
def optims(self, function, backend_names, optims, store=True): def optims(self, function, backend_names, optims, store=True):
if optims is None: if optims is None:
print >>sys.stderr, 'Error: missing parameters.' print >>sys.stderr, 'Error: missing parameters.'
return 1 return 2
for optim_name in optims.split(): for optim_name in optims.split():
try: try:
@ -211,8 +211,6 @@ class HaveSex(ReplApplication):
if store: if store:
self.storage.save() self.storage.save()
return 0
def complete_optim(self, text, line, *ignored): def complete_optim(self, text, line, *ignored):
args = line.split(' ') args = line.split(' ')
if len(args) == 2: if len(args) == 2:

View file

@ -53,16 +53,16 @@ class Pastoob(ReplApplication):
print args print args
if not _id: if not _id:
print >>sys.stderr, 'This command takes an argument: %s' % self.get_command_help('get', short=True) print >>sys.stderr, 'This command takes an argument: %s' % self.get_command_help('get', short=True)
return 1 return 2
try: try:
paste = self.get_object(_id, 'get_paste', ['contents']) paste = self.get_object(_id, 'get_paste', ['contents'])
except PasteNotFound: except PasteNotFound:
print >>sys.stderr, 'Paste not found: %s' % _id print >>sys.stderr, 'Paste not found: %s' % _id
return 2 return 3
if not paste: if not paste:
print >>sys.stderr, 'Unable to handle paste: %s' % _id print >>sys.stderr, 'Unable to handle paste: %s' % _id
return 3 return 1
output = codecs.getwriter(sys.stdout.encoding)(sys.stdout) output = codecs.getwriter(sys.stdout.encoding)(sys.stdout)
output.write(paste.contents) output.write(paste.contents)
# add a newline unless we are writing # add a newline unless we are writing

View file

@ -87,13 +87,13 @@ class Radioob(ReplApplication):
Play a radio with a found player. Play a radio with a found player.
""" """
if not _id: if not _id:
print 'This command takes an argument: %s' % self.get_command_help('play', short=True) print >>sys.stderr, 'This command takes an argument: %s' % self.get_command_help('play', short=True)
return return 2
radio = self.get_object(_id, 'get_radio', ['streams']) radio = self.get_object(_id, 'get_radio', ['streams'])
if not radio: if not radio:
print >>sys.stderr, 'Radio not found: ' % _id print >>sys.stderr, 'Radio not found: ' % _id
return return 1
try: try:
player_name = self.config.get('media_player') player_name = self.config.get('media_player')
if not player_name: if not player_name:
@ -115,13 +115,13 @@ class Radioob(ReplApplication):
Get information about a radio. Get information about a radio.
""" """
if not _id: if not _id:
print 'This command takes an argument: %s' % self.get_command_help('info', short=True) print >>sys.stderr, 'This command takes an argument: %s' % self.get_command_help('info', short=True)
return return 2
radio = self.get_object(_id, 'get_radio') radio = self.get_object(_id, 'get_radio')
if not radio: if not radio:
print 'Radio not found:', _id print >>sys.stderr, 'Radio not found:', _id
return return 3
self.format(radio) self.format(radio)
self.flush() self.flush()

View file

@ -93,8 +93,8 @@ class Videoob(ReplApplication):
_id, dest = self.parse_command_args(line, 2, 1) _id, dest = self.parse_command_args(line, 2, 1)
video = self.get_object(_id, 'get_video', ['url']) video = self.get_object(_id, 'get_video', ['url'])
if not video: if not video:
print 'Video not found: %s' % _id print >>sys.stderr, 'Video not found: %s' % _id
return 1 return 3
def check_exec(executable): def check_exec(executable):
with open('/dev/null', 'w') as devnull: with open('/dev/null', 'w') as devnull:
@ -136,13 +136,13 @@ class Videoob(ReplApplication):
Play a video with a found player. Play a video with a found player.
""" """
if not _id: if not _id:
print 'This command takes an argument: %s' % self.get_command_help('play', short=True) print >>sys.stderr, 'This command takes an argument: %s' % self.get_command_help('play', short=True)
return return 2
video = self.get_object(_id, 'get_video', ['url']) video = self.get_object(_id, 'get_video', ['url'])
if not video: if not video:
print 'Video not found: %s' % _id print >>sys.stderr, 'Video not found: %s' % _id
return return 3
try: try:
player_name = self.config.get('media_player') player_name = self.config.get('media_player')
if not player_name: if not player_name:
@ -164,13 +164,13 @@ class Videoob(ReplApplication):
Get information about a video. Get information about a video.
""" """
if not _id: if not _id:
print 'This command takes an argument: %s' % self.get_command_help('info', short=True) print >>sys.stderr, 'This command takes an argument: %s' % self.get_command_help('info', short=True)
return return 2
video = self.get_object(_id, 'get_video') video = self.get_object(_id, 'get_video')
if not video: if not video:
print >>sys.stderr, 'Video not found: %s' % _id print >>sys.stderr, 'Video not found: %s' % _id
return return 3
self.format(video) self.format(video)
self.flush() self.flush()
@ -193,6 +193,7 @@ class Videoob(ReplApplication):
self.nsfw = False self.nsfw = False
else: else:
print 'Invalid argument "%s".' % line print 'Invalid argument "%s".' % line
return 2
else: else:
print "on" if self.nsfw else "off" print "on" if self.nsfw else "off"
@ -206,9 +207,9 @@ class Videoob(ReplApplication):
""" """
if len(self.enabled_backends) == 0: if len(self.enabled_backends) == 0:
if self.interactive: if self.interactive:
print 'No backend loaded. Please use the "backends" command.' print >>sys.stderr, 'No backend loaded. Please use the "backends" command.'
else: else:
print 'No backend loaded.' print >>sys.stderr, 'No backend loaded.'
return 1 return 1
self.set_formatter_header(u'Search pattern: %s' % pattern if pattern else u'Latest videos') self.set_formatter_header(u'Search pattern: %s' % pattern if pattern else u'Latest videos')

View file

@ -54,8 +54,8 @@ class WebContentEdit(ReplApplication):
contents += [content for backend, content in self.do('get_content', _id, backends=backend_names) if content] contents += [content for backend, content in self.do('get_content', _id, backends=backend_names) if content]
if len(contents) == 0: if len(contents) == 0:
print >> sys.stderr, 'No contents found' print >>sys.stderr, 'No contents found'
return 1 return 3
paths = {} paths = {}
for content in contents: for content in contents:
@ -92,8 +92,8 @@ class WebContentEdit(ReplApplication):
contents.remove(content) contents.remove(content)
if len(contents) == 0: if len(contents) == 0:
print 'No changes. Abort.' print >>sys.stderr, 'No changes. Abort.'
return return 1
print 'Contents changed:\n%s' % ('\n'.join(' * %s' % content.id for content in contents)) print 'Contents changed:\n%s' % ('\n'.join(' * %s' % content.id for content in contents))
@ -126,8 +126,8 @@ class WebContentEdit(ReplApplication):
Display log of a page Display log of a page
""" """
if not line: if not line:
print >> sys.stderr, 'Error: please give a page ID' print >>sys.stderr, 'Error: please give a page ID'
return 1 return 2
_id, backend_name = self.parse_id(line) _id, backend_name = self.parse_id(line)
backend_names = (backend_name,) if backend_name is not None else self.enabled_backends backend_names = (backend_name,) if backend_name is not None else self.enabled_backends

View file

@ -52,7 +52,7 @@ class WeboobCfg(ReplApplication):
""" """
if not line: if not line:
print >>sys.stderr, 'You must specify a backend name. Hint: use the "backends" command.' print >>sys.stderr, 'You must specify a backend name. Hint: use the "backends" command.'
return return 2
name, options = self.parse_command_args(line, 2, 1) name, options = self.parse_command_args(line, 2, 1)
if options: if options:
options = options.split(' ') options = options.split(' ')
@ -65,8 +65,8 @@ class WeboobCfg(ReplApplication):
try: try:
key, value = option.split('=', 1) key, value = option.split('=', 1)
except ValueError: except ValueError:
print 'Parameters have to be formatted "key=value"' print >>sys.stderr, 'Parameters have to be formatted "key=value"'
return return 2
params[key] = value params[key] = value
self.add_backend(name, params) self.add_backend(name, params)
@ -133,9 +133,8 @@ class WeboobCfg(ReplApplication):
Remove a configured backend. Remove a configured backend.
""" """
if not self.weboob.backends_config.remove_backend(instance_name): if not self.weboob.backends_config.remove_backend(instance_name):
print 'Backend instance "%s" does not exist' % instance_name print >>sys.stderr, 'Backend instance "%s" does not exist' % instance_name
return 1 return 1
return 0
def do_edit(self, line): def do_edit(self, line):
""" """
@ -175,7 +174,7 @@ class WeboobCfg(ReplApplication):
""" """
if not line: if not line:
print >>sys.stderr, 'You must specify a backend name. Hint: use the "backends" command.' print >>sys.stderr, 'You must specify a backend name. Hint: use the "backends" command.'
return return 2
try: try:
backend = self.weboob.modules_loader.get_or_load_module(line) backend = self.weboob.modules_loader.get_or_load_module(line)
@ -183,7 +182,7 @@ class WeboobCfg(ReplApplication):
backend = None backend = None
if not backend: if not backend:
print 'Backend "%s" does not exist.' % line print >>sys.stderr, 'Backend "%s" does not exist.' % line
return 1 return 1
print '.------------------------------------------------------------------------------.' print '.------------------------------------------------------------------------------.'

View file

@ -42,7 +42,7 @@ class WeboobCli(ReplApplication):
def main(self, argv): def main(self, argv):
if len(argv) < 3: if len(argv) < 3:
print >>sys.stderr, "Syntax: %s capability method [args ..]" % argv[0] print >>sys.stderr, "Syntax: %s capability method [args ..]" % argv[0]
return 1 return 2
cap_s = argv[1] cap_s = argv[1]
cmd = argv[2] cmd = argv[2]

View file

@ -113,6 +113,7 @@ class Weboorrents(ReplApplication):
if not found: if not found:
print >>sys.stderr, 'Torrent "%s" not found' % id print >>sys.stderr, 'Torrent "%s" not found' % id
return 3
else: else:
self.flush() self.flush()
@ -149,6 +150,7 @@ class Weboorrents(ReplApplication):
return return
print >>sys.stderr, 'Torrent "%s" not found' % id print >>sys.stderr, 'Torrent "%s" not found' % id
return 3
def do_search(self, pattern): def do_search(self, pattern):
""" """

View file

@ -304,7 +304,7 @@ class BaseApplication(object):
if self.options.save_responses: if self.options.save_responses:
responses_dirname = tempfile.mkdtemp(prefix='weboob_session_') responses_dirname = tempfile.mkdtemp(prefix='weboob_session_')
print 'Debug data will be saved in this directory: %s' % responses_dirname print >>sys.stderr, 'Debug data will be saved in this directory: %s' % responses_dirname
from weboob.tools.browser import BaseBrowser from weboob.tools.browser import BaseBrowser
BaseBrowser.SAVE_RESPONSES = True BaseBrowser.SAVE_RESPONSES = True
BaseBrowser.responses_dirname = responses_dirname BaseBrowser.responses_dirname = responses_dirname
@ -359,7 +359,7 @@ class BaseApplication(object):
try: try:
app = klass() app = klass()
except BackendsConfig.WrongPermissions, e: except BackendsConfig.WrongPermissions, e:
print e print >>sys.stderr, e
sys.exit(1) sys.exit(1)
try: try:
@ -367,12 +367,12 @@ class BaseApplication(object):
args = app.parse_args(args) args = app.parse_args(args)
sys.exit(app.main(args)) sys.exit(app.main(args))
except KeyboardInterrupt: except KeyboardInterrupt:
print 'Program killed by SIGINT' print >>sys.stderr, 'Program killed by SIGINT'
sys.exit(0) sys.exit(0)
except EOFError: except EOFError:
sys.exit(0) sys.exit(0)
except ConfigError, e: except ConfigError, e:
print 'Configuration error: %s' % e print >>sys.stderr, 'Configuration error: %s' % e
sys.exit(1) sys.exit(1)
except CallErrors, e: except CallErrors, e:
app.bcall_errors_handler(e) app.bcall_errors_handler(e)

View file

@ -126,7 +126,7 @@ class ConsoleApplication(BaseApplication):
if r.isdigit(): if r.isdigit():
i = int(r) - 1 i = int(r) - 1
if i < 0 or i >= len(backends): if i < 0 or i >= len(backends):
print 'Error: %s is not a valid choice' % r print >>sys.stderr, 'Error: %s is not a valid choice' % r
continue continue
name = backends[i] name = backends[i]
try: try:
@ -182,7 +182,7 @@ class ConsoleApplication(BaseApplication):
if response.isdigit(): if response.isdigit():
i = int(response) - 1 i = int(response) - 1
if i < 0 or i >= len(backends): if i < 0 or i >= len(backends):
print 'Error: %s is not a valid choice' % response print >>sys.stderr, 'Error: %s is not a valid choice' % response
continue continue
backend_name = backends[i][0] backend_name = backends[i][0]
else: else:
@ -208,12 +208,12 @@ class ConsoleApplication(BaseApplication):
backend = None backend = None
if not backend: if not backend:
print 'Backend "%s" does not exist.' % name print >>sys.stderr, 'Backend "%s" does not exist.' % name
return None return 1
if not backend.has_caps(ICapAccount) or backend.klass.ACCOUNT_REGISTER_PROPERTIES is None: if not backend.has_caps(ICapAccount) or backend.klass.ACCOUNT_REGISTER_PROPERTIES is None:
print 'You can\'t register a new account with %s' % name print >>sys.stderr, 'You can\'t register a new account with %s' % name
return None return 1
account = Account() account = Account()
account.properties = {} account.properties = {}
@ -274,8 +274,8 @@ class ConsoleApplication(BaseApplication):
items.update(params) items.update(params)
params = items params = items
if not backend: if not backend:
print 'Backend "%s" does not exist. Hint: use the "backends" command.' % name print >>sys.stderr, 'Backend "%s" does not exist. Hint: use the "backends" command.' % name
return None return 1
# ask for params non-specified on command-line arguments # ask for params non-specified on command-line arguments
asked_config = False asked_config = False
@ -296,7 +296,7 @@ class ConsoleApplication(BaseApplication):
print 'Backend "%s" successfully %s.' % (name, 'updated' if edit else 'added') print 'Backend "%s" successfully %s.' % (name, 'updated' if edit else 'added')
return name return name
except BackendAlreadyExists: except BackendAlreadyExists:
print 'Backend "%s" is already configured in file "%s"' % (name, self.weboob.backends_config.confpath) print >>sys.stderr, 'Backend "%s" is already configured in file "%s"' % (name, self.weboob.backends_config.confpath)
while self.ask('Add new instance of "%s" backend?' % name, default=False): while self.ask('Add new instance of "%s" backend?' % name, default=False):
new_name = self.ask('Please give new instance name (could be "%s_1")' % name, regexp=r'^[\w\-_]+$') new_name = self.ask('Please give new instance name (could be "%s_1")' % name, regexp=r'^[\w\-_]+$')
try: try:
@ -304,7 +304,8 @@ class ConsoleApplication(BaseApplication):
print 'Backend "%s" successfully added.' % new_name print 'Backend "%s" successfully added.' % new_name
return new_name return new_name
except BackendAlreadyExists: except BackendAlreadyExists:
print 'Instance "%s" already exists for backend "%s".' % (new_name, name) print >>sys.stderr, 'Instance "%s" already exists for backend "%s".' % (new_name, name)
return 1
def ask(self, question, default=None, masked=False, regexp=None, choices=None): def ask(self, question, default=None, masked=False, regexp=None, choices=None):
""" """
@ -396,7 +397,7 @@ class ConsoleApplication(BaseApplication):
try: try:
v.set_value(line) v.set_value(line)
except ValueError, e: except ValueError, e:
print 'Error: %s' % e print >>sys.stderr, 'Error: %s' % e
else: else:
break break

View file

@ -298,7 +298,8 @@ class ReplApplication(Cmd, ConsoleApplication):
pass pass
def default(self, line): def default(self, line):
print 'Unknown command: "%s"' % line print >>sys.stderr, 'Unknown command: "%s"' % line
return 2
def completenames(self, text, *ignored): def completenames(self, text, *ignored):
return [name for name in Cmd.completenames(self, text, *ignored) if name not in self.hidden_commands] return [name for name in Cmd.completenames(self, text, *ignored) if name not in self.hidden_commands]
@ -440,11 +441,12 @@ class ReplApplication(Cmd, ConsoleApplication):
else: else:
self.stdout.write('%s\n' % command_help) self.stdout.write('%s\n' % command_help)
else: else:
print 'Unknown command: "%s"' % arg print >>sys.stderr, 'Unknown command: "%s"' % arg
else: else:
cmds = self._parser.formatter.format_commands(self._parser.commands) cmds = self._parser.formatter.format_commands(self._parser.commands)
self.stdout.write('%s\n' % cmds) self.stdout.write('%s\n' % cmds)
self.stdout.write('Type "help <command>" for more info about a command.\n') self.stdout.write('Type "help <command>" for more info about a command.\n')
return 2
def complete_backends(self, text, line, begidx, endidx): def complete_backends(self, text, line, begidx, endidx):
choices = [] choices = []
@ -518,7 +520,7 @@ class ReplApplication(Cmd, ConsoleApplication):
if action in ('enable', 'disable', 'only', 'add', 'register', 'edit', 'remove'): if action in ('enable', 'disable', 'only', 'add', 'register', 'edit', 'remove'):
if not given_backend_names: if not given_backend_names:
print >>sys.stderr, 'Please give at least a backend name.' print >>sys.stderr, 'Please give at least a backend name.'
return return 2
given_backends = set(backend for backend in self.weboob.iter_backends() if backend.name in given_backend_names) given_backends = set(backend for backend in self.weboob.iter_backends() if backend.name in given_backend_names)
@ -530,7 +532,7 @@ class ReplApplication(Cmd, ConsoleApplication):
try: try:
self.enabled_backends.remove(backend) self.enabled_backends.remove(backend)
except KeyError: except KeyError:
print '%s is not enabled' % backend.name print >>sys.stderr, '%s is not enabled' % backend.name
elif action == 'only': elif action == 'only':
self.enabled_backends = set() self.enabled_backends = set()
for backend in given_backends: for backend in given_backends:
@ -564,11 +566,11 @@ class ReplApplication(Cmd, ConsoleApplication):
self.weboob.backends_config.remove_backend(backend.name) self.weboob.backends_config.remove_backend(backend.name)
self.unload_backends(backend.name) self.unload_backends(backend.name)
else: else:
print 'Unknown action: "%s"' % action print >>sys.stderr, 'Unknown action: "%s"' % action
return 1 return 1
if len(self.enabled_backends) == 0: if len(self.enabled_backends) == 0:
print 'Warning: no more backends are loaded. %s is probably unusable.' % self.APPNAME.capitalize() print >>sys.stderr, 'Warning: no more backends are loaded. %s is probably unusable.' % self.APPNAME.capitalize()
def complete_logging(self, text, line, begidx, endidx): def complete_logging(self, text, line, begidx, endidx):
levels = ('debug', 'info', 'warning', 'error', 'quiet', 'default') levels = ('debug', 'info', 'warning', 'error', 'quiet', 'default')
@ -611,6 +613,7 @@ class ReplApplication(Cmd, ConsoleApplication):
except KeyError: except KeyError:
print >>sys.stderr, 'Level "%s" does not exist.' % args[0] print >>sys.stderr, 'Level "%s" does not exist.' % args[0]
print >>sys.stderr, 'Availables: %s' % ' '.join(levels.iterkeys()) print >>sys.stderr, 'Availables: %s' % ' '.join(levels.iterkeys())
return 2
else: else:
logging.root.setLevel(level) logging.root.setLevel(level)
for handler in logging.root.handlers: for handler in logging.root.handlers:
@ -634,6 +637,7 @@ class ReplApplication(Cmd, ConsoleApplication):
self.condition = ResultsCondition(line) self.condition = ResultsCondition(line)
except ResultsConditionError, e: except ResultsConditionError, e:
print >>sys.stderr, '%s' % e print >>sys.stderr, '%s' % e
return 2
else: else:
if self.condition is None: if self.condition is None:
print 'No condition is set.' print 'No condition is set.'
@ -658,12 +662,14 @@ class ReplApplication(Cmd, ConsoleApplication):
try: try:
count = int(line) count = int(line)
except ValueError: except ValueError:
print 'Could not interpret "%s" as a number.' % line print >>sys.stderr, 'Could not interpret "%s" as a number.' % line
return 2
else: else:
if count > 0: if count > 0:
self.options.count = count self.options.count = count
else: else:
print 'Number must be at least 1.' print >>sys.stderr, 'Number must be at least 1.'
return 2
else: else:
if self.options.count is None: if self.options.count is None:
print 'Counting disabled.' print 'Counting disabled.'
@ -717,14 +723,16 @@ class ReplApplication(Cmd, ConsoleApplication):
print 'off' if self.options.no_keys else 'on' print 'off' if self.options.no_keys else 'on'
else: else:
if args[2] not in ('on', 'off'): if args[2] not in ('on', 'off'):
print 'Invalid value "%s". Please use "on" or "off" values.' % args[2] print >>sys.stderr, 'Invalid value "%s". Please use "on" or "off" values.' % args[2]
return 2
else: else:
if args[1] == 'header': if args[1] == 'header':
self.options.no_header = True if args[2] == 'off' else False self.options.no_header = True if args[2] == 'off' else False
elif args[1] == 'keys': elif args[1] == 'keys':
self.options.no_keys = True if args[2] == 'off' else False self.options.no_keys = True if args[2] == 'off' else False
else: else:
print 'Don\'t know which option to set. Available options: header, keys.' print >>sys.stderr, 'Don\'t know which option to set. Available options: header, keys.'
return 2
else: else:
if args[0] in self.formatters_loader.get_available_formatters(): if args[0] in self.formatters_loader.get_available_formatters():
if len(args) > 1: if len(args) > 1:
@ -733,8 +741,9 @@ class ReplApplication(Cmd, ConsoleApplication):
self.commands_formatters = {} self.commands_formatters = {}
self.DEFAULT_FORMATTER = self.set_formatter(args[0]) self.DEFAULT_FORMATTER = self.set_formatter(args[0])
else: else:
print 'Formatter "%s" is not available.\n' \ print >>sys.stderr, 'Formatter "%s" is not available.\n' \
'Available formatters: %s.' % (args[0], ', '.join(self.formatters_loader.get_available_formatters())) 'Available formatters: %s.' % (args[0], ', '.join(self.formatters_loader.get_available_formatters()))
return 1
else: else:
print 'Default formatter: %s' % self.DEFAULT_FORMATTER print 'Default formatter: %s' % self.DEFAULT_FORMATTER
for key, klass in self.commands_formatters.iteritems(): for key, klass in self.commands_formatters.iteritems():
@ -779,16 +788,16 @@ class ReplApplication(Cmd, ConsoleApplication):
else: else:
backend_name = line.strip() backend_name = line.strip()
if not backend_name: if not backend_name:
print 'Please specify a backend name.' print >>sys.stderr, 'Please specify a backend name.'
return return 2
backends = set(backend for backend in self.enabled_backends if backend.name == backend_name) backends = set(backend for backend in self.enabled_backends if backend.name == backend_name)
if not backends: if not backends:
print 'No backend found for "%s"' % backend_name print >>sys.stderr, 'No backend found for "%s"' % backend_name
return return 1
backend = backends.pop() backend = backends.pop()
if not hasattr(backend, '_browser'): if not hasattr(backend, '_browser'):
print 'No browser created for backend "%s" yet. Please invoke a command before.' % backend.name print >>sys.stderr, 'No browser created for backend "%s" yet. Please invoke a command before.' % backend.name
return return 1
browser = backend._browser browser = backend._browser
data = browser.parser.tostring(browser.page.document) data = browser.parser.tostring(browser.page.document)
try: try:
@ -866,10 +875,10 @@ class ReplApplication(Cmd, ConsoleApplication):
try: try:
self.formatter = self.formatters_loader.build_formatter(name) self.formatter = self.formatters_loader.build_formatter(name)
except FormatterLoadError, e: except FormatterLoadError, e:
print '%s' % e print >>sys.stderr, '%s' % e
if self.DEFAULT_FORMATTER == name: if self.DEFAULT_FORMATTER == name:
self.DEFAULT_FORMATTER = ReplApplication.DEFAULT_FORMATTER self.DEFAULT_FORMATTER = ReplApplication.DEFAULT_FORMATTER
print 'Falling back to "%s".' % (self.DEFAULT_FORMATTER) print >>sys.stderr, 'Falling back to "%s".' % (self.DEFAULT_FORMATTER)
self.formatter = self.formatters_loader.build_formatter(self.DEFAULT_FORMATTER) self.formatter = self.formatters_loader.build_formatter(self.DEFAULT_FORMATTER)
name = self.DEFAULT_FORMATTER name = self.DEFAULT_FORMATTER
if self.options.no_header: if self.options.no_header:
@ -892,9 +901,9 @@ class ReplApplication(Cmd, ConsoleApplication):
try: try:
self.formatter.format(obj=result, selected_fields=fields) self.formatter.format(obj=result, selected_fields=fields)
except FieldNotFound, e: except FieldNotFound, e:
print e print >>sys.stderr, e
except MandatoryFieldsNotFound, e: except MandatoryFieldsNotFound, e:
print >> sys.stderr, '%s Hint: select missing fields or use another formatter (ex: multiline).' % e print >>sys.stderr, '%s Hint: select missing fields or use another formatter (ex: multiline).' % e
def flush(self): def flush(self):
self.formatter.flush() self.formatter.flush()

View file

@ -24,6 +24,7 @@ from httplib import BadStatusLine
from logging import warning from logging import warning
import mechanize import mechanize
import os import os
import sys
import re import re
import tempfile import tempfile
from threading import RLock from threading import RLock
@ -316,7 +317,7 @@ class BaseBrowser(mechanize.Browser):
""" """
if self.responses_dirname is None: if self.responses_dirname is None:
self.responses_dirname = tempfile.mkdtemp(prefix='weboob_session_') self.responses_dirname = tempfile.mkdtemp(prefix='weboob_session_')
print 'Debug data will be saved in this directory: %s' % self.responses_dirname print >>sys.stderr, 'Debug data will be saved in this directory: %s' % self.responses_dirname
response_filepath = os.path.join(self.responses_dirname, unicode(self.responses_count)) response_filepath = os.path.join(self.responses_dirname, unicode(self.responses_count))
with open(response_filepath, 'w') as f: with open(response_filepath, 'w') as f:
f.write(result.read()) f.write(result.read())
@ -513,7 +514,7 @@ class BaseBrowser(mechanize.Browser):
value = [self.str(is_list.index(args[label]))] value = [self.str(is_list.index(args[label]))]
except ValueError, e: except ValueError, e:
if args[label]: if args[label]:
print '[%s] %s: %s' % (label, args[label], e) print >>sys.stderr, '[%s] %s: %s' % (label, args[label], e)
return return
else: else:
value = [self.str(args[label])] value = [self.str(args[label])]