diff --git a/scripts/parceloob b/scripts/parceloob new file mode 100755 index 0000000000000000000000000000000000000000..7393fd826b200485d1de233236056903ef5c77ee --- /dev/null +++ b/scripts/parceloob @@ -0,0 +1,27 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# vim: ft=python et softtabstop=4 cinoptions=4 shiftwidth=4 ts=4 ai + +# Copyright(C) 2013 Romain Bignon +# +# This file is part of weboob. +# +# weboob is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# weboob is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with weboob. If not, see . + + +from weboob.applications.parceloob import Parceloob + + +if __name__ == '__main__': + Parceloob.run() diff --git a/weboob/applications/parceloob/__init__.py b/weboob/applications/parceloob/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..bb9ef6cadeb730e1fa8fea315d4ec5864f13a321 --- /dev/null +++ b/weboob/applications/parceloob/__init__.py @@ -0,0 +1,23 @@ +# -*- coding: utf-8 -*- + +# Copyright(C) 2013 Romain Bignon +# +# This file is part of weboob. +# +# weboob is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# weboob is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with weboob. If not, see . + + +from .parceloob import Parceloob + +__all__ = ['Parceloob'] diff --git a/weboob/applications/parceloob/parceloob.py b/weboob/applications/parceloob/parceloob.py new file mode 100644 index 0000000000000000000000000000000000000000..d2679473470d2817c16a1b44881a534e74fffbe8 --- /dev/null +++ b/weboob/applications/parceloob/parceloob.py @@ -0,0 +1,159 @@ +# -*- coding: utf-8 -*- + +# Copyright(C) 2013 Romain Bignon +# +# This file is part of weboob. +# +# weboob is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# weboob is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with weboob. If not, see . + + +import sys + +from weboob.capabilities.base import empty +from weboob.capabilities.parcel import ICapParcel, Parcel +from weboob.tools.application.repl import ReplApplication +from weboob.tools.application.formatters.iformatter import IFormatter + + +__all__ = ['Parceloob'] + + +STATUS = {Parcel.STATUS_PLANNED: ('PLANNED', 'red'), + Parcel.STATUS_IN_TRANSIT: ('IN TRANSIT', 'yellow'), + Parcel.STATUS_ARRIVED: ('ARRIVED', 'green'), + Parcel.STATUS_UNKNOWN: ('', 'white'), + } + +class HistoryFormatter(IFormatter): + MANDATORY_FIELDS = () + + def format_obj(self, obj, alias): + if isinstance(obj, Parcel): + result = u'Parcel %s (%s)\n' % (self.colored(obj.id, 'red', 'bold'), + self.colored(obj.backend, 'blue', 'bold')) + result += u'%sArrival:%s %s\n' % (self.BOLD, self.NC, obj.arrival) + status, status_color = STATUS[obj.status] + result += u'%sStatus:%s %s\n' % (self.BOLD, self.NC, self.colored(status, status_color)) + result += u'%sInfo:%s %s\n\n' % (self.BOLD, self.NC, obj.info) + result += u' Date Location Activity \n' + result += u'---------------------+-----------------+---------------------------------------------------\n' + return result + + return ' %s %s %s' % (self.colored('%-19s' % obj.date, 'blue'), + self.colored('%-17s' % obj.location, 'magenta'), + self.colored(obj.activity, 'yellow')) + +class StatusFormatter(IFormatter): + MANDATORY_FIELDS = ('id',) + + def format_obj(self, obj, alias): + if alias is not None: + id = '%s (%s)' % (self.colored('%3s' % ('#' + alias), 'red', 'bold'), + self.colored(obj.backend, 'blue', 'bold')) + clean = '#%s (%s)' % (alias, obj.backend) + if len(clean) < 15: + id += (' ' * (15 - len(clean))) + else: + id = self.colored('%30s' % obj.fullid, 'red', 'bold') + + status, status_color = STATUS[obj.status] + arrival = obj.arrival.strftime('%Y-%m-%d') if not empty(obj.arrival) else '' + result = u'%s %s %s %s %s' % (id, self.colored(u'—', 'cyan'), + self.colored('%-10s' % status, status_color), + self.colored('%-10s' % arrival, 'blue'), + self.colored('%-20s' % obj.info, 'yellow')) + + return result + + +class Parceloob(ReplApplication): + APPNAME = 'parceloob' + VERSION = '0.g' + COPYRIGHT = 'Copyright(C) 2013 Romain Bignon' + CAPS = ICapParcel + DESCRIPTION = "Console application to track your parcels." + SHORT_DESCRIPTION = "manage your parcels" + EXTRA_FORMATTERS = {'status': StatusFormatter, + 'history': HistoryFormatter, + } + DEFAULT_FORMATTER = 'table' + COMMANDS_FORMATTERS = {'status': 'status', + 'info': 'history', + } + STORAGE = {'tracking': []} + + def do_track(self, line): + """ + track ID + + Track a parcel. + """ + parcel = self.get_object(line, 'get_parcel_tracking') + if not parcel: + print >>sys.stderr, 'Error: the parcel "%s" is not found' % line + return 2 + + parcels = set(self.storage.get('tracking', default=[])) + parcels.add(parcel.fullid) + self.storage.set('tracking', list(parcels)) + self.storage.save() + + print 'Parcel "%s" has been tracked.' % parcel.fullid + + def do_untrack(self, line): + """ + untrack ID + + Stop tracking a parcel. + """ + parcel = self.get_object(line, 'get_parcel_tracking') + if not parcel: + print >>sys.stderr, 'Error: the parcel "%s" is not found' % line + return 2 + + parcels = set(self.storage.get('tracking', default=[])) + try: + parcels.remove(parcel.fullid) + except KeyError: + print >>sys.stderr, "Error: parcel \"%s\" wasn't tracked" % parcel.fullid + return 2 + + self.storage.set('tracking', list(parcels)) + self.storage.save() + + print "Parcel \"%s\" isn't tracked anymore." % parcel.fullid + + def do_status(self, line): + """ + status + + Display status for all of the tracked parcels. + """ + self.start_format() + for id in self.storage.get('tracking', default=[]): + p = self.get_object(id, 'get_parcel_tracking') + if p is None: + continue + self.cached_format(p) + + def do_info(self, id): + parcel = self.get_object(id, 'get_parcel_tracking', []) + if not parcel: + print >>sys.stderr, 'Error: parcel not found' + return 2 + + self.start_format() + self.format(parcel) + for event in parcel.history: + self.format(event)