From 731baff8ab0f6c5ea7fd9cbfc8cb0564bd303dc6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20=27Necoro=27=20Neumann?= Date: Sat, 6 Mar 2010 14:28:25 +0100 Subject: Updated NEWS --- doc/NEWS | 3 +++ 1 file changed, 3 insertions(+) diff --git a/doc/NEWS b/doc/NEWS index a5d3186..a07108d 100644 --- a/doc/NEWS +++ b/doc/NEWS @@ -3,6 +3,9 @@ next: - allow eix as backend DB - use an internal messagequeue module instead of external shm - show the list of world packages +- allow to search descriptions +- add an icon to signal the 'best' version for a package +- added Italian translation (thx to Ponsi) 0.13.1: - fix segfault in GLib -- cgit v1.2.3 From 3cca0806d4929151e33c514bfc52c3dc1dd6a816 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20=27Necoro=27=20Neumann?= Date: Sat, 6 Mar 2010 14:42:46 +0100 Subject: Read translators from file --- TRANSLATORS | 1 + portato/gui/templates/AboutWindow.ui | 7 ------- portato/gui/windows/about.py | 8 ++++++-- setup.py | 1 + 4 files changed, 8 insertions(+), 9 deletions(-) create mode 120000 TRANSLATORS diff --git a/TRANSLATORS b/TRANSLATORS new file mode 120000 index 0000000..d2e7d0b --- /dev/null +++ b/TRANSLATORS @@ -0,0 +1 @@ +doc/TRANSLATORS \ No newline at end of file diff --git a/portato/gui/templates/AboutWindow.ui b/portato/gui/templates/AboutWindow.ui index 5590e2b..a3f81cf 100644 --- a/portato/gui/templates/AboutWindow.ui +++ b/portato/gui/templates/AboutWindow.ui @@ -25,13 +25,6 @@ Thanks goto: - The Porthole team, which often inspired me and gave me hints :) - franzf, who often tested and gave comments - the Sabayon-Distro for making Portato the default Portage-GUI - Catalan - Roger Calvó -German - René 'Necoro' Neumann -Italian - Ponsi -Polish - Tomasz Osiński -Portugese (Brazilian) - Alberto Federman Neto -Spanish - Daniel Halens -Turkish - Gürkan 'seqizz' Gür p4r4d0x (inspired by wolfden) diff --git a/portato/gui/windows/about.py b/portato/gui/windows/about.py index a15fd24..0d2ce1a 100644 --- a/portato/gui/windows/about.py +++ b/portato/gui/windows/about.py @@ -10,12 +10,13 @@ # # Written by René 'Necoro' Neumann -from __future__ import absolute_import +from __future__ import absolute_import, with_statement +import os import gtk from .basic import AbstractDialog -from ...constants import VERSION, REVISION +from ...constants import VERSION, REVISION, DATA_DIR class AboutWindow (AbstractDialog): """A window showing the "about"-informations.""" @@ -27,6 +28,9 @@ class AboutWindow (AbstractDialog): self.window.set_version(VERSION) self.window.set_logo(None) + with open(os.path.join(DATA_DIR, "TRANSLATORS")) as f: + self.window.set_translator_credits("".join(f.readlines())) + if REVISION: gitlabel = self.tree.get_widget("gitLabel") gitlabel.set_label(REVISION) diff --git a/setup.py b/setup.py index 1bcbc44..0acf907 100644 --- a/setup.py +++ b/setup.py @@ -36,6 +36,7 @@ packages = [ data_files = [ (TEMPLATE_DIR, [os.path.join("portato/gui/templates",x) for x in os.listdir("portato/gui/templates") if (x.endswith(".ui") or x.endswith(".menu"))]), (ICON_DIR, ["icons/portato-icon.png", "icons/better-package.svg"]), + (DATA_DIR, ["doc/TRANSLATORS"]), (PLUGIN_DIR, plugin_list("gpytage", "notify", "etc_proposals", "reload_portage", "package_details"))] cmdclass = {'build_manpage': build_manpage} -- cgit v1.2.3 From 42c9e86bd9fe4d48f58e4688c0cdcd8f0066afb1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20=27Necoro=27=20Neumann?= Date: Sun, 7 Mar 2010 00:26:42 +0100 Subject: Fix setup.py --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 0acf907..766b2a2 100644 --- a/setup.py +++ b/setup.py @@ -17,7 +17,7 @@ import sys from distutils.core import setup from distutils.extension import Extension -from portato.constants import VERSION, ICON_DIR, PLUGIN_DIR, TEMPLATE_DIR, APP +from portato.constants import VERSION, ICON_DIR, PLUGIN_DIR, DATA_DIR, TEMPLATE_DIR, APP from build_manpage import build_manpage -- cgit v1.2.3 From c0ef9b8f98eaf9fe46b87759d8083a8bd24620fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20=27Necoro=27=20Neumann?= Date: Sat, 6 Mar 2010 16:26:29 +0100 Subject: Rewrote Session as to use the normal ConfigParser and not our own one (cherry picked from commit 397a31e6deb851de102bca3d7c8d754f40b0656d) --- portato/gui/windows/main.py | 2 +- portato/session.py | 116 +++++++++++++++++++------------------------- 2 files changed, 50 insertions(+), 68 deletions(-) diff --git a/portato/gui/windows/main.py b/portato/gui/windows/main.py index a06756d..bc40a1f 100644 --- a/portato/gui/windows/main.py +++ b/portato/gui/windows/main.py @@ -1070,7 +1070,7 @@ class MainWindow (Window): queue = plugin.get_plugin_queue() if queue: for p in queue.get_plugins(): - self.session.add_handler(([(p.name.replace(" ","_"), "plugins")], load_plugin(p), save_plugin(p))) + self.session.add_handler(([(p.name.replace(" ","_").replace(":","_"), "plugins")], load_plugin(p), save_plugin(p))) # the other things def load_cfg ((name, cat)): diff --git a/portato/session.py b/portato/session.py index 54761a2..be13275 100644 --- a/portato/session.py +++ b/portato/session.py @@ -15,10 +15,12 @@ from __future__ import absolute_import, with_statement import os from UserDict import DictMixin -from .config_parser import ConfigParser, SectionNotFoundException +from ConfigParser import SafeConfigParser, NoSectionError, NoOptionError from .constants import SESSION_DIR from .helper import debug, info +from .odict import OrderedDict +NoSuchThing = (NoSectionError, NoOptionError) sessionlist = [] class Session (object): @@ -44,38 +46,32 @@ class Session (object): @param register: register in the global sessionlist, which is closed at the end """ - self._cfg = None + self._cfg = SafeConfigParser({}, OrderedDict) self._handlers = [] self._name = name if name else "MAIN" + self._file = os.path.join(SESSION_DIR, file) if not (os.path.exists(SESSION_DIR) and os.path.isdir(SESSION_DIR)): os.mkdir(SESSION_DIR) - file = os.path.join(SESSION_DIR, file) oldfiles = [os.path.join(SESSION_DIR, x) for x in oldfiles] - if not os.path.exists(file): + if not os.path.exists(self._file): for o in oldfiles: if os.path.exists(o): debug("Moving old session file '%s' to '%s'." % (o, file)) - os.rename(o,file) + os.rename(o,self._file) break - self._cfg = ConfigParser(file) + self._cfg.read([self._file]) if name: - i = _("Loading '%s' session from %s.") % (name, self._cfg.file) + i = _("Loading '%s' session from %s.") % (name, self._file) else: - i = _("Loading session from %s.") % self._cfg.file + i = _("Loading session from %s.") % self._file info(i) - try: - self._cfg.parse() - except IOError, e: - if e.errno == 2: pass - else: raise - # register if register: sessionlist.append(self) @@ -90,7 +86,8 @@ class Session (object): - a function returning the number of option return values - getting them out of the program """ - options = map(lambda x: (x, self._name) if not hasattr(x, "__iter__") else x, options) + convert = lambda (x,y): (y.upper(), x.lower()) + options = map(lambda x: (self._name, x.lower()) if not hasattr(x, "__iter__") else convert(x), options) self._handlers.append((options, load_fn, save_fn, default)) def load (self, defaults_only = False): @@ -109,7 +106,7 @@ class Session (object): else: try: loaded = [self._cfg.get(*x) for x in options] - except KeyError: # does not exist -> ignore + except NoSuchThing: # does not exist -> ignore debug("No values for %s.", options) ldefault(options, lfn, default) else: @@ -129,87 +126,72 @@ class Session (object): vals = [vals] debug("Saving %s with values %s", options, vals) - for value, (option, section) in zip(vals, options): + for value, (section, option) in zip(vals, options): self.set(option, str(value), section) - self._cfg.write() + with open(self._file, "w") as f: + self._cfg.write(f) @classmethod def close (cls): for s in sessionlist: if s._name != "MAIN": - info(_("Saving '%s' session to %s.") % (s._name, s._cfg.file)) + info(_("Saving '%s' session to %s.") % (s._name, s._file)) else: - info(_("Saving session to %s.") % s._cfg.file) + info(_("Saving session to %s.") % s._file) s.save() - def set (self, key, value, section = ""): - if not section: section = self._name + def set (self, key, value, section = None): + if section is None: section = self._name + section = section.upper() try: - self._cfg.add(key, value, section, with_blankline = False) - except SectionNotFoundException: + self._cfg.set(section, key, value) + except NoSectionError: self._cfg.add_section(section) - self._cfg.add(key, value, section, with_blankline = False) + self._cfg.set(section, key, value) - def get (self, key, section = ""): - if not section: section = self._name + def get (self, key, section = None): + if section is None: section = self._name + section = section.upper() try: - return self._cfg.get(key, section) - except KeyError: + return self._cfg.get(section, key) + except NoSuchThing: return None - def get_boolean (self, key, section = ""): - if not section: section = self._name - - try: - return self._cfg.get_boolean(key, section) - except KeyError: - return None - - def remove (self, key, section = ""): - if not section: section = self._name - + def remove (self, key, section = None): + if section is None: section = self._name section = section.upper() - key = key.lower() - - val = self._cfg._access(key, section) - del self._cfg.cache[val.line] - self._cfg.write() + self._cfg.remove_option(section, key) def remove_section (self, section): section = section.upper() + self._cfg.remove_section(section) - sline = self._cfg.sections[section] - - try: - mline = max(v.line for v in self._cfg.vars[section].itervalues()) - except ValueError: # nothing in the section - mline = sline - - sline = max(sline - 1, 0) # remove blank line too - but only if there is one ;) - - del self._cfg.cache[sline:mline+1] - self._cfg.write() + def rename (self, old, new, section = None): + if section is None: section = self._name + section = section.upper() - def rename (self, old, new, section = ""): - if not section: section = self._name - val = self.get(old, section) - self.remove(old, section) - self._cfg.add(new, val, section, with_blankline = False) + + if val is not None: + self.remove(old, section) + self.set(new, val, section) def rename_section (self, old, new): - old = old.upper() - line = self._cfg.sections[old] - self._cfg.cache[line] = "[%s]\n" % new.upper() - self._cfg.write() + new = new.upper() + + values = self._cfg.items(old) + self.remove_section(old) + for k,v in values: + self.set(k,v,new) def check_version (self, vers): pass # do nothing atm + class SectionDict (DictMixin): """A class, which maps a specific section of a session to a dictionary.""" @@ -231,7 +213,7 @@ class SectionDict (DictMixin): self._session.remove(name, self._section) def keys (self): - return self._session._cfg.vars[self._section].keys() + return self._session._cfg.options(self._section) def __contains__ (self, name): - return self._session.get(name, self._section) is not None + return self._session._cfg.has_option(self._section, name) -- cgit v1.2.3 From c8fab8cd56c88d2322104afc960c836a543cd3d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20=27Necoro=27=20Neumann?= Date: Sun, 14 Mar 2010 20:02:03 +0100 Subject: Send more files for bug mails --- i18n/de.po | 97 +++++++++++++++++---------------- i18n/messages.pot | 84 ++++++++++++++-------------- portato/gui/templates/MailInfoWindow.ui | 38 +++++++++---- portato/gui/windows/mailinfo.py | 93 +++++++++++++++++++++++++------ 4 files changed, 194 insertions(+), 118 deletions(-) diff --git a/i18n/de.po b/i18n/de.po index b7add36..88783a9 100644 --- a/i18n/de.po +++ b/i18n/de.po @@ -2,8 +2,8 @@ msgid "" msgstr "" "Project-Id-Version: Portato\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2010-03-05 21:26+0100\n" -"PO-Revision-Date: 2010-03-05 21:27+0100\n" +"POT-Creation-Date: 2010-03-14 20:01+0100\n" +"PO-Revision-Date: 2010-03-14 20:01+0100\n" "Last-Translator: René 'Necoro' Neumann \n" "Language-Team: \n" "MIME-Version: 1.0\n" @@ -243,7 +243,7 @@ msgstr "Autor:" #: portato/gui/templates/PluginWindow.ui:141 #: portato/gui/windows/pkglist.py:59 -#: portato/gui/windows/main.py:830 +#: portato/gui/windows/main.py:843 #: portato/gui/windows/plugin.py:27 msgid "Enabled" msgstr "Aktiviert" @@ -297,15 +297,11 @@ msgstr "" "Kommentare /\n" "Vorgehensweise um den Bug zu erzeugen?" -#: portato/gui/templates/MailInfoWindow.ui:138 -msgid "Attach _Logfile" -msgstr "Hänge _Logdatei an" +#: portato/gui/templates/MailInfoWindow.ui:160 +msgid "These files will be sent:" +msgstr "Die folgenden Dateien werden geschickt:" -#: portato/gui/templates/MailInfoWindow.ui:142 -msgid "Attaches the logfile to the mail. This log only contains debug information." -msgstr "Hängt die Logdatei an die Mail an. In der Datei sind nur Debug-Informationen enthalten." - -#: portato/gui/templates/MailInfoWindow.ui:206 +#: portato/gui/templates/MailInfoWindow.ui:220 msgid "_Send" msgstr "_Send" @@ -350,7 +346,7 @@ msgid "Homepage:" msgstr "Homepage:" #: portato/gui/templates/MainWindow.ui:462 -#: portato/gui/windows/main.py:831 +#: portato/gui/windows/main.py:844 msgid "Installed" msgstr "Installiert" @@ -406,13 +402,13 @@ msgid "Remove the selected package from the queue" msgstr "Löscht das gewählte Paket aus der Queue" #: portato/gui/templates/MainWindow.ui:782 -#: portato/gui/windows/main.py:611 +#: portato/gui/windows/main.py:620 msgid "Queue" msgstr "Queue" #: portato/gui/templates/MainWindow.ui:806 -#: portato/gui/windows/main.py:1240 -#: portato/gui/windows/main.py:1242 +#: portato/gui/windows/main.py:1253 +#: portato/gui/windows/main.py:1255 msgid "Console" msgstr "Konsole" @@ -509,7 +505,7 @@ msgstr "" "Bitte führe emerge --sync && layman -S aus." #: portato/gui/dialogs.py:123 -#: portato/gui/windows/main.py:1289 +#: portato/gui/windows/main.py:1302 #, python-format msgid "No versions of package '%s' found!" msgstr "Keine Version vom Paket '%s' gefunden!" @@ -592,14 +588,15 @@ msgstr "Pakete mit Updates" msgid "World Packages" msgstr "Pakete in \"World\"" -#: portato/gui/windows/mailinfo.py:83 +#: portato/gui/windows/mailinfo.py:144 #, python-format msgid "An error occurred while sending. I think we were greylisted. The error: %s" msgstr "Während des Sendes trat ein Fehler auf. Wahrscheinlich wurden wir ge-greylistet. Der Fehler: %s" -#: portato/gui/windows/mailinfo.py:84 -msgid "Retrying after waiting 60 seconds." -msgstr "Wiederhole den Versuch nach einer 60s Pause." +#: portato/gui/windows/mailinfo.py:145 +#, python-format +msgid "Retrying after waiting %d seconds." +msgstr "Wiederhole den Versuch nach einer %ds Pause." #: portato/gui/windows/splash.py:35 #, python-format @@ -627,7 +624,7 @@ msgid "Package Set" msgstr "Paket-Set" #: portato/gui/windows/preference.py:259 -#: portato/gui/windows/main.py:833 +#: portato/gui/windows/main.py:846 #: portato/db/database.py:49 #: portato/db/database.py:50 msgid "Description" @@ -655,90 +652,90 @@ msgstr "Paket konnte nicht gefunden werden: %s" msgid "Masked by user" msgstr "Vom Benutzer maskiert" -#: portato/gui/windows/main.py:455 +#: portato/gui/windows/main.py:464 msgid "Loading Config" msgstr "Lade Konfiguration" -#: portato/gui/windows/main.py:467 +#: portato/gui/windows/main.py:476 msgid "Creating Database" msgstr "Erstelle Datenbank" -#: portato/gui/windows/main.py:471 +#: portato/gui/windows/main.py:480 msgid "Loading Plugins" msgstr "Lade Plugins" -#: portato/gui/windows/main.py:479 +#: portato/gui/windows/main.py:488 msgid "Building frontend" msgstr "Erstelle Oberfläche" -#: portato/gui/windows/main.py:545 +#: portato/gui/windows/main.py:554 msgid "Restoring Session" msgstr "Lade Session" -#: portato/gui/windows/main.py:555 +#: portato/gui/windows/main.py:564 msgid "Loading Plugin Widgets" msgstr "Lade GUI-Elemente der Plugins" -#: portato/gui/windows/main.py:558 +#: portato/gui/windows/main.py:567 msgid "Finishing startup" msgstr "Erledige letzte Handgriffe :)" -#: portato/gui/windows/main.py:614 +#: portato/gui/windows/main.py:623 msgid "Options" msgstr "Optionen" -#: portato/gui/windows/main.py:630 +#: portato/gui/windows/main.py:639 msgid "Categories" msgstr "Kategorien" -#: portato/gui/windows/main.py:689 +#: portato/gui/windows/main.py:698 msgid "Packages" msgstr "Pakete" -#: portato/gui/windows/main.py:724 +#: portato/gui/windows/main.py:733 #, python-format msgid "Package '%s/%s' is disabled." msgstr "Paket '%s/%s' wurde deaktiviert." -#: portato/gui/windows/main.py:741 +#: portato/gui/windows/main.py:750 msgid "Versions" msgstr "Versionen" -#: portato/gui/windows/main.py:744 +#: portato/gui/windows/main.py:753 msgid "Slot" msgstr "Slot" -#: portato/gui/windows/main.py:832 +#: portato/gui/windows/main.py:845 msgid "Flag" msgstr "Flag" -#: portato/gui/windows/main.py:856 +#: portato/gui/windows/main.py:869 msgid "This is an expanded use flag and cannot be selected" msgstr "Dies ist ein \"Expanded Use Flag\" und kann daher nicht ausgewählt werden." -#: portato/gui/windows/main.py:914 +#: portato/gui/windows/main.py:927 #, python-format msgid "Translating session from version %d to %d." msgstr "Upgrade Session von Version %d auf Version %d." -#: portato/gui/windows/main.py:917 +#: portato/gui/windows/main.py:930 #, python-format msgid "Cannot translate session from version %d to %d." msgstr "Kann Session nicht von Version %d nach %d upgraden." -#: portato/gui/windows/main.py:1425 +#: portato/gui/windows/main.py:1438 msgid "use flags" msgstr "Use Flags" -#: portato/gui/windows/main.py:1437 +#: portato/gui/windows/main.py:1450 msgid "masking keywords" msgstr "Masking Keywords" -#: portato/gui/windows/main.py:1838 +#: portato/gui/windows/main.py:1851 msgid "The portage tree is not existing." msgstr "Der Portage-Tree existiert nicht." -#: portato/gui/windows/main.py:1842 +#: portato/gui/windows/main.py:1855 msgid "The portage tree seems to be empty." msgstr "Der Portage-Tree scheint leer zu sein." @@ -942,22 +939,22 @@ msgstr "Leere Datenbank..." msgid "Populating database..." msgstr "Fülle Datenbank..." -#: portato/session.py:67 +#: portato/session.py:69 #, python-format msgid "Loading '%s' session from %s." msgstr "Lade '%s'-Session von %s." -#: portato/session.py:69 +#: portato/session.py:71 #, python-format msgid "Loading session from %s." msgstr "Lade Session von %s." -#: portato/session.py:141 +#: portato/session.py:139 #, python-format msgid "Saving '%s' session to %s." msgstr "Schreibe '%s'-Session nach %s." -#: portato/session.py:143 +#: portato/session.py:141 #, python-format msgid "Saving session to %s." msgstr "Schreibe Session nach %s." @@ -1115,6 +1112,14 @@ msgstr "Emerge fehlgeschlagen!" msgid "Error Code: %d" msgstr "Fehler-Code: %d" +#~ msgid "Attach _Logfile" +#~ msgstr "Hänge _Logdatei an" +#~ msgid "" +#~ "Attaches the logfile to the mail. This log only contains debug " +#~ "information." +#~ msgstr "" +#~ "Hängt die Logdatei an die Mail an. In der Datei sind nur Debug-" +#~ "Informationen enthalten." #~ msgid "Plu_gins" #~ msgstr "Plu_gins" #~ msgid "_File" diff --git a/i18n/messages.pot b/i18n/messages.pot index 26f1dd1..555837f 100644 --- a/i18n/messages.pot +++ b/i18n/messages.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2010-03-05 21:26+0100\n" +"POT-Creation-Date: 2010-03-14 20:01+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -239,7 +239,7 @@ msgid "Author:" msgstr "" #: portato/gui/templates/PluginWindow.ui:141 portato/gui/windows/pkglist.py:59 -#: portato/gui/windows/main.py:830 portato/gui/windows/plugin.py:27 +#: portato/gui/windows/main.py:843 portato/gui/windows/plugin.py:27 msgid "Enabled" msgstr "" @@ -284,16 +284,11 @@ msgid "" "what did you do to hit the bug?" msgstr "" -#: portato/gui/templates/MailInfoWindow.ui:138 -msgid "Attach _Logfile" +#: portato/gui/templates/MailInfoWindow.ui:160 +msgid "These files will be sent:" msgstr "" -#: portato/gui/templates/MailInfoWindow.ui:142 -msgid "" -"Attaches the logfile to the mail. This log only contains debug information." -msgstr "" - -#: portato/gui/templates/MailInfoWindow.ui:206 +#: portato/gui/templates/MailInfoWindow.ui:220 msgid "_Send" msgstr "" @@ -337,7 +332,7 @@ msgstr "" msgid "Homepage:" msgstr "" -#: portato/gui/templates/MainWindow.ui:462 portato/gui/windows/main.py:831 +#: portato/gui/templates/MainWindow.ui:462 portato/gui/windows/main.py:844 msgid "Installed" msgstr "" @@ -387,12 +382,12 @@ msgstr "" msgid "Remove the selected package from the queue" msgstr "" -#: portato/gui/templates/MainWindow.ui:782 portato/gui/windows/main.py:611 +#: portato/gui/templates/MainWindow.ui:782 portato/gui/windows/main.py:620 msgid "Queue" msgstr "" -#: portato/gui/templates/MainWindow.ui:806 portato/gui/windows/main.py:1240 -#: portato/gui/windows/main.py:1242 +#: portato/gui/templates/MainWindow.ui:806 portato/gui/windows/main.py:1253 +#: portato/gui/windows/main.py:1255 msgid "Console" msgstr "" @@ -485,7 +480,7 @@ msgid "" "Please run emerge --sync && layman -S." msgstr "" -#: portato/gui/dialogs.py:123 portato/gui/windows/main.py:1289 +#: portato/gui/dialogs.py:123 portato/gui/windows/main.py:1302 #, python-format msgid "No versions of package '%s' found!" msgstr "" @@ -573,14 +568,15 @@ msgstr "" msgid "World Packages" msgstr "" -#: portato/gui/windows/mailinfo.py:83 +#: portato/gui/windows/mailinfo.py:144 #, python-format msgid "" "An error occurred while sending. I think we were greylisted. The error: %s" msgstr "" -#: portato/gui/windows/mailinfo.py:84 -msgid "Retrying after waiting 60 seconds." +#: portato/gui/windows/mailinfo.py:145 +#, python-format +msgid "Retrying after waiting %d seconds." msgstr "" #: portato/gui/windows/splash.py:35 @@ -608,7 +604,7 @@ msgstr "" msgid "Package Set" msgstr "" -#: portato/gui/windows/preference.py:259 portato/gui/windows/main.py:833 +#: portato/gui/windows/preference.py:259 portato/gui/windows/main.py:846 #: portato/db/database.py:49 portato/db/database.py:50 msgid "Description" msgstr "" @@ -634,90 +630,90 @@ msgstr "" msgid "Masked by user" msgstr "" -#: portato/gui/windows/main.py:455 +#: portato/gui/windows/main.py:464 msgid "Loading Config" msgstr "" -#: portato/gui/windows/main.py:467 +#: portato/gui/windows/main.py:476 msgid "Creating Database" msgstr "" -#: portato/gui/windows/main.py:471 +#: portato/gui/windows/main.py:480 msgid "Loading Plugins" msgstr "" -#: portato/gui/windows/main.py:479 +#: portato/gui/windows/main.py:488 msgid "Building frontend" msgstr "" -#: portato/gui/windows/main.py:545 +#: portato/gui/windows/main.py:554 msgid "Restoring Session" msgstr "" -#: portato/gui/windows/main.py:555 +#: portato/gui/windows/main.py:564 msgid "Loading Plugin Widgets" msgstr "" -#: portato/gui/windows/main.py:558 +#: portato/gui/windows/main.py:567 msgid "Finishing startup" msgstr "" -#: portato/gui/windows/main.py:614 +#: portato/gui/windows/main.py:623 msgid "Options" msgstr "" -#: portato/gui/windows/main.py:630 +#: portato/gui/windows/main.py:639 msgid "Categories" msgstr "" -#: portato/gui/windows/main.py:689 +#: portato/gui/windows/main.py:698 msgid "Packages" msgstr "" -#: portato/gui/windows/main.py:724 +#: portato/gui/windows/main.py:733 #, python-format msgid "Package '%s/%s' is disabled." msgstr "" -#: portato/gui/windows/main.py:741 +#: portato/gui/windows/main.py:750 msgid "Versions" msgstr "" -#: portato/gui/windows/main.py:744 +#: portato/gui/windows/main.py:753 msgid "Slot" msgstr "" -#: portato/gui/windows/main.py:832 +#: portato/gui/windows/main.py:845 msgid "Flag" msgstr "" -#: portato/gui/windows/main.py:856 +#: portato/gui/windows/main.py:869 msgid "This is an expanded use flag and cannot be selected" msgstr "" -#: portato/gui/windows/main.py:914 +#: portato/gui/windows/main.py:927 #, python-format msgid "Translating session from version %d to %d." msgstr "" -#: portato/gui/windows/main.py:917 +#: portato/gui/windows/main.py:930 #, python-format msgid "Cannot translate session from version %d to %d." msgstr "" -#: portato/gui/windows/main.py:1425 +#: portato/gui/windows/main.py:1438 msgid "use flags" msgstr "" -#: portato/gui/windows/main.py:1437 +#: portato/gui/windows/main.py:1450 msgid "masking keywords" msgstr "" -#: portato/gui/windows/main.py:1838 +#: portato/gui/windows/main.py:1851 msgid "The portage tree is not existing." msgstr "" -#: portato/gui/windows/main.py:1842 +#: portato/gui/windows/main.py:1855 msgid "The portage tree seems to be empty." msgstr "" @@ -920,22 +916,22 @@ msgstr "" msgid "Populating database..." msgstr "" -#: portato/session.py:67 +#: portato/session.py:69 #, python-format msgid "Loading '%s' session from %s." msgstr "" -#: portato/session.py:69 +#: portato/session.py:71 #, python-format msgid "Loading session from %s." msgstr "" -#: portato/session.py:141 +#: portato/session.py:139 #, python-format msgid "Saving '%s' session to %s." msgstr "" -#: portato/session.py:143 +#: portato/session.py:141 #, python-format msgid "Saving session to %s." msgstr "" diff --git a/portato/gui/templates/MailInfoWindow.ui b/portato/gui/templates/MailInfoWindow.ui index 4551cdb..e3cdd1f 100644 --- a/portato/gui/templates/MailInfoWindow.ui +++ b/portato/gui/templates/MailInfoWindow.ui @@ -134,25 +134,39 @@ what did you do to hit the bug? - - Attach _Logfile + True - True - False - Attaches the logfile to the mail. This log only contains debug information. - True - True - True + 0 + none + + + True + 12 + + + True + True + False + False + False + + + + + + + + True + These files will be sent: + + + 2 4 5 - GTK_FILL - - - 5 diff --git a/portato/gui/windows/mailinfo.py b/portato/gui/windows/mailinfo.py index 0ee232a..6d6e93b 100644 --- a/portato/gui/windows/mailinfo.py +++ b/portato/gui/windows/mailinfo.py @@ -14,15 +14,41 @@ from __future__ import absolute_import, with_statement import smtplib, socket import time +import gtk, pango from email.mime.multipart import MIMEMultipart from email.mime.text import MIMEText +from os.path import basename from .basic import AbstractDialog from ..utils import GtkThread from ..dialogs import mail_failure_dialog from ...helper import debug, info -from ...constants import VERSION +from ...constants import VERSION, CONFIG_LOCATION from ...log import LOGFILE +from ... import session + +class ShowDialog (gtk.Dialog): + + def __init__(self, parent, f): + gtk.Dialog.__init__(self, f, parent, buttons = (gtk.STOCK_CLOSE, gtk.RESPONSE_CLOSE)) + + textview = gtk.TextView() + textview.set_editable(False) + textview.modify_font(pango.FontDescription("Monospace")) + textview.set_size_request(gtk.gdk.screen_width()/2, gtk.gdk.screen_height()/3) + + sw = gtk.ScrolledWindow(); + sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) + sw.add(textview) + + self.vbox.add(sw) + + textbuffer = textview.get_buffer() + + with open(f) as text: + textbuffer.set_text(text.read()) + + self.vbox.show_all() class MailInfoWindow (AbstractDialog): TO = "bugs@portato.necoro.net" @@ -30,10 +56,42 @@ class MailInfoWindow (AbstractDialog): def __init__ (self, parent, tb): AbstractDialog.__init__(self, parent) + + self.files = [LOGFILE, CONFIG_LOCATION] + [s._file for s in session.sessionlist] + self.fileList = self.tree.get_widget("fileList") + self.build_file_list() self.tb = tb self.window.show_all() + def build_file_list(self): + store = gtk.ListStore(bool, str) + + for f in self.files: + store.append((True, f)) + + self.fileList.set_model(store) + cell = gtk.CellRendererText() + tCell = gtk.CellRendererToggle() + tCell.set_property("activatable", True) + tCell.connect("toggled", self.cb_file_toggled) + + self.fileList.append_column(gtk.TreeViewColumn(None, tCell, active = 0)) + self.fileList.append_column(gtk.TreeViewColumn(None, cell, text = 1)) + + def cb_file_toggled(self, cell, path): + store = self.fileList.get_model() + store[path][0] = not store[path][0] + return True + + def cb_file_clicked(self, view, path, *args): + store = view.get_model() + f = store[path][1] + + dialog = ShowDialog(self.window, f) + dialog.run() + dialog.destroy() + def set_data (self): self.message = MIMEMultipart() self.message["Subject"] = "[Bug Report] Bug in Portato %s" % VERSION @@ -63,13 +121,15 @@ class MailInfoWindow (AbstractDialog): txtmsg = MIMEText(text, "plain", "utf-8") self.message.attach(txtmsg) - # log - if self.tree.get_widget("logCheck").get_active(): - with open(LOGFILE, "r") as f: - log = MIMEText(f.read(), "plain", "utf-8") - log.add_header('Content-Disposition', 'attachment', filename='portato.log') + # logs + for (active, f) in self.fileList.get_model(): + if active: + debug("Attaching '%s'", f) + with open(f, "r") as text: + log = MIMEText(text.read(), "plain", "utf-8") + log.add_header('Content-Disposition', 'attachment', filename=basename(f)) - self.message.attach(log) + self.message.attach(log) def send (self): try: @@ -77,21 +137,22 @@ class MailInfoWindow (AbstractDialog): server = smtplib.SMTP("mail.necoro.eu") debug("Sending mail") try: - try: - server.sendmail(self.addr, self.TO, self.message.as_string()) - except smtplib.SMTPRecipientsRefused, e: - info(_("An error occurred while sending. I think we were greylisted. The error: %s") % e) - info(_("Retrying after waiting 60 seconds.")) - time.sleep(60) - server.sendmail(self.addr, self.TO, self.message.as_string()) - debug("Sent") + for i in range(5): # try 5 times at max + try: + server.sendmail(self.addr, self.TO, self.message.as_string()) + except smtplib.SMTPRecipientsRefused, e: + info(_("An error occurred while sending. I think we were greylisted. The error: %s") % e) + info(_("Retrying after waiting %d seconds."), 30) + time.sleep(30) + else: + debug("Sent") + break finally: server.quit() except socket.error, e: mail_failure_dialog("%s (Code: %s)" % (e.args[1], e.args[0])) def cb_cancel_clicked (self, *args): - self.close() return True -- cgit v1.2.3 From d772c8db351d46ed4fc9f55eb978200ebbe98307 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20=27Necoro=27=20Neumann?= Date: Sun, 14 Mar 2010 21:06:19 +0100 Subject: Show a dialog if no email is given --- i18n/de.po | 54 ++++++++++++++++++++++++++--------------- i18n/messages.pot | 51 +++++++++++++++++++++++--------------- portato/gui/dialogs.py | 7 ++++++ portato/gui/windows/basic.py | 3 +++ portato/gui/windows/mailinfo.py | 16 ++++++++---- 5 files changed, 87 insertions(+), 44 deletions(-) diff --git a/i18n/de.po b/i18n/de.po index 88783a9..d60a707 100644 --- a/i18n/de.po +++ b/i18n/de.po @@ -2,8 +2,8 @@ msgid "" msgstr "" "Project-Id-Version: Portato\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2010-03-14 20:01+0100\n" -"PO-Revision-Date: 2010-03-14 20:01+0100\n" +"POT-Creation-Date: 2010-03-14 21:03+0100\n" +"PO-Revision-Date: 2010-03-14 21:04+0100\n" "Last-Translator: René 'Necoro' Neumann \n" "Language-Team: \n" "MIME-Version: 1.0\n" @@ -426,49 +426,63 @@ msgid "The error was: %s" msgstr "Der Fehler war: %s" #: portato/gui/dialogs.py:24 +msgid "No email address given" +msgstr "Keine Email-Adresse gegeben" + +#: portato/gui/dialogs.py:25 +msgid "" +"You haven't specified an email address. Without it, it will not be possible for the developers to contact you for questions and thus it might be harder to fix the bug.\n" +"\n" +"Do you want to proceed nevertheless?" +msgstr "" +"Du hast keine Email-Adresse angegeben. Daher ist es nicht möglich, dass die Entwickler dich kontaktieren können und es kann daher sein, dass der Bug schwerer zu beseitigen ist.\n" +"\n" +"Trotzdem fortfahren?" + +#: portato/gui/dialogs.py:31 msgid "Do you really want to quit?" msgstr "Wirklich beenden?" -#: portato/gui/dialogs.py:25 +#: portato/gui/dialogs.py:32 msgid "There are some packages in the emerge queue and/or an emerge process is running." msgstr "Es sind noch Pakete in der Emerge-Queue und/oder emerge läuft noch." -#: portato/gui/dialogs.py:43 +#: portato/gui/dialogs.py:50 #, python-format msgid "%(blocked)s is blocked by %(blocks)s." msgstr "%(blocks)s blockiert %(blocked)s." -#: portato/gui/dialogs.py:44 +#: portato/gui/dialogs.py:51 msgid "Please unmerge the blocking package." msgstr "Bitte deinstalliere das blockierende Paket." -#: portato/gui/dialogs.py:50 +#: portato/gui/dialogs.py:57 msgid "You are not root." msgstr "Du bist nicht root." -#: portato/gui/dialogs.py:56 +#: portato/gui/dialogs.py:63 #, python-format msgid "%s seems to be masked." msgstr "%s scheint maskiert zu sein." -#: portato/gui/dialogs.py:57 +#: portato/gui/dialogs.py:64 msgid "Do you want to unmask it and its dependencies?" msgstr "Soll das Paket und seine Abhängigkeiten demaskiert werden?" -#: portato/gui/dialogs.py:63 +#: portato/gui/dialogs.py:70 msgid "Package not found!" msgstr "Paket nicht gefunden!" -#: portato/gui/dialogs.py:69 +#: portato/gui/dialogs.py:76 msgid "Do not show this dialog again." msgstr "Diesen Dialog nicht wieder anzeigen." -#: portato/gui/dialogs.py:70 +#: portato/gui/dialogs.py:77 #, python-format msgid "Changed %s" msgstr "%s wurde geändert" -#: portato/gui/dialogs.py:71 +#: portato/gui/dialogs.py:78 msgid "" "Portato will write these changes into the appropriate files.\n" "Please backup them if you think it is necessary." @@ -476,11 +490,11 @@ msgstr "" "Portato wird diese Änderungen speichern.\n" "Bitte sichere die entsprechenden Dateien, wenn du es als notwendig erachtest." -#: portato/gui/dialogs.py:80 +#: portato/gui/dialogs.py:87 msgid "You cannot remove dependencies. :)" msgstr "Du kannst keine Abhängigkeiten löschen ;)." -#: portato/gui/dialogs.py:86 +#: portato/gui/dialogs.py:93 msgid "" "This is the updates queue. You cannot remove single elements.\n" "Do you want to clear the whole queue instead?" @@ -488,15 +502,15 @@ msgstr "" "Das ist die Update-Queue. Aus dieser können keine einzelnen Pakete entfernt werden.\n" "Soll stattdessen die komplette Queue entfernt werden?" -#: portato/gui/dialogs.py:92 +#: portato/gui/dialogs.py:99 msgid "Do you really want to clear the whole queue?" msgstr "Wirklich die gesamte Queue löschen?" -#: portato/gui/dialogs.py:111 +#: portato/gui/dialogs.py:118 msgid "A prerequisite for starting Portato was not matched." msgstr "Eine Vorbedingung um Portato zu starten ist nicht erfüllt." -#: portato/gui/dialogs.py:115 +#: portato/gui/dialogs.py:122 msgid "" "Note: On fresh Sabayon installs or its LiveDVD/-CD, there is no portage tree existing per default.\n" "Please run emerge --sync && layman -S." @@ -504,7 +518,7 @@ msgstr "" "Hinweis: Auf frisch installierten Sabayon-Systemen bzw. der Sabayon LiveDVD/-CD existiert standardmäßig kein Portage-Tree.\n" "Bitte führe emerge --sync && layman -S aus." -#: portato/gui/dialogs.py:123 +#: portato/gui/dialogs.py:130 #: portato/gui/windows/main.py:1302 #, python-format msgid "No versions of package '%s' found!" @@ -588,12 +602,12 @@ msgstr "Pakete mit Updates" msgid "World Packages" msgstr "Pakete in \"World\"" -#: portato/gui/windows/mailinfo.py:144 +#: portato/gui/windows/mailinfo.py:145 #, python-format msgid "An error occurred while sending. I think we were greylisted. The error: %s" msgstr "Während des Sendes trat ein Fehler auf. Wahrscheinlich wurden wir ge-greylistet. Der Fehler: %s" -#: portato/gui/windows/mailinfo.py:145 +#: portato/gui/windows/mailinfo.py:146 #, python-format msgid "Retrying after waiting %d seconds." msgstr "Wiederhole den Versuch nach einer %ds Pause." diff --git a/i18n/messages.pot b/i18n/messages.pot index 555837f..5c007f9 100644 --- a/i18n/messages.pot +++ b/i18n/messages.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2010-03-14 20:01+0100\n" +"POT-Creation-Date: 2010-03-14 21:03+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -405,82 +405,95 @@ msgid "The error was: %s" msgstr "" #: portato/gui/dialogs.py:24 -msgid "Do you really want to quit?" +msgid "No email address given" msgstr "" #: portato/gui/dialogs.py:25 msgid "" +"You haven't specified an email address. Without it, it will not be possible " +"for the developers to contact you for questions and thus it might be harder " +"to fix the bug.\n" +"\n" +"Do you want to proceed nevertheless?" +msgstr "" + +#: portato/gui/dialogs.py:31 +msgid "Do you really want to quit?" +msgstr "" + +#: portato/gui/dialogs.py:32 +msgid "" "There are some packages in the emerge queue and/or an emerge process is " "running." msgstr "" -#: portato/gui/dialogs.py:43 +#: portato/gui/dialogs.py:50 #, python-format msgid "%(blocked)s is blocked by %(blocks)s." msgstr "" -#: portato/gui/dialogs.py:44 +#: portato/gui/dialogs.py:51 msgid "Please unmerge the blocking package." msgstr "" -#: portato/gui/dialogs.py:50 +#: portato/gui/dialogs.py:57 msgid "You are not root." msgstr "" -#: portato/gui/dialogs.py:56 +#: portato/gui/dialogs.py:63 #, python-format msgid "%s seems to be masked." msgstr "" -#: portato/gui/dialogs.py:57 +#: portato/gui/dialogs.py:64 msgid "Do you want to unmask it and its dependencies?" msgstr "" -#: portato/gui/dialogs.py:63 +#: portato/gui/dialogs.py:70 msgid "Package not found!" msgstr "" -#: portato/gui/dialogs.py:69 +#: portato/gui/dialogs.py:76 msgid "Do not show this dialog again." msgstr "" -#: portato/gui/dialogs.py:70 +#: portato/gui/dialogs.py:77 #, python-format msgid "Changed %s" msgstr "" -#: portato/gui/dialogs.py:71 +#: portato/gui/dialogs.py:78 msgid "" "Portato will write these changes into the appropriate files.\n" "Please backup them if you think it is necessary." msgstr "" -#: portato/gui/dialogs.py:80 +#: portato/gui/dialogs.py:87 msgid "You cannot remove dependencies. :)" msgstr "" -#: portato/gui/dialogs.py:86 +#: portato/gui/dialogs.py:93 msgid "" "This is the updates queue. You cannot remove single elements.\n" "Do you want to clear the whole queue instead?" msgstr "" -#: portato/gui/dialogs.py:92 +#: portato/gui/dialogs.py:99 msgid "Do you really want to clear the whole queue?" msgstr "" -#: portato/gui/dialogs.py:111 +#: portato/gui/dialogs.py:118 msgid "A prerequisite for starting Portato was not matched." msgstr "" -#: portato/gui/dialogs.py:115 +#: portato/gui/dialogs.py:122 msgid "" "Note: On fresh Sabayon installs or its LiveDVD/-CD, there is no " "portage tree existing per default.\n" "Please run emerge --sync && layman -S." msgstr "" -#: portato/gui/dialogs.py:123 portato/gui/windows/main.py:1302 +#: portato/gui/dialogs.py:130 portato/gui/windows/main.py:1302 #, python-format msgid "No versions of package '%s' found!" msgstr "" @@ -568,13 +581,13 @@ msgstr "" msgid "World Packages" msgstr "" -#: portato/gui/windows/mailinfo.py:144 +#: portato/gui/windows/mailinfo.py:145 #, python-format msgid "" "An error occurred while sending. I think we were greylisted. The error: %s" msgstr "" -#: portato/gui/windows/mailinfo.py:145 +#: portato/gui/windows/mailinfo.py:146 #, python-format msgid "Retrying after waiting %d seconds." msgstr "" diff --git a/portato/gui/dialogs.py b/portato/gui/dialogs.py index 6044a5b..7ad5c7f 100644 --- a/portato/gui/dialogs.py +++ b/portato/gui/dialogs.py @@ -20,6 +20,13 @@ def mail_failure_dialog(e): dialog.destroy() return ret +def no_email_dialog(p): + dialog = gtk.MessageDialog(p, gtk.DIALOG_MODAL, gtk.MESSAGE_INFO, gtk.BUTTONS_OK_CANCEL, _("No email address given")) + dialog.format_secondary_text(_("You haven't specified an email address. Without it, it will not be possible for the developers to contact you for questions and thus it might be harder to fix the bug.\n\nDo you want to proceed nevertheless?")) + ret = dialog.run() + dialog.destroy() + return ret + def queue_not_empty_dialog(): dialog = gtk.MessageDialog(None, gtk.DIALOG_MODAL, gtk.MESSAGE_QUESTION, gtk.BUTTONS_NONE, _("Do you really want to quit?")) dialog.format_secondary_text(_("There are some packages in the emerge queue and/or an emerge process is running.")) diff --git a/portato/gui/windows/basic.py b/portato/gui/windows/basic.py index 92c35f4..01d31e5 100644 --- a/portato/gui/windows/basic.py +++ b/portato/gui/windows/basic.py @@ -151,6 +151,9 @@ class AbstractDialog (Window): self.window.set_transient_for(parent) self.parent = parent + # type hint + self.window.set_type_hint(gtk.gdk.WINDOW_TYPE_HINT_DIALOG) + # catch the ESC-key self.window.connect("key-press-event", self.cb_key_pressed) diff --git a/portato/gui/windows/mailinfo.py b/portato/gui/windows/mailinfo.py index 6d6e93b..c5002e7 100644 --- a/portato/gui/windows/mailinfo.py +++ b/portato/gui/windows/mailinfo.py @@ -21,7 +21,7 @@ from os.path import basename from .basic import AbstractDialog from ..utils import GtkThread -from ..dialogs import mail_failure_dialog +from ..dialogs import mail_failure_dialog, no_email_dialog from ...helper import debug, info from ...constants import VERSION, CONFIG_LOCATION from ...log import LOGFILE @@ -61,6 +61,7 @@ class MailInfoWindow (AbstractDialog): self.fileList = self.tree.get_widget("fileList") self.build_file_list() + self.mailEntry = self.tree.get_widget("mailEntry") self.tb = tb self.window.show_all() @@ -99,7 +100,7 @@ class MailInfoWindow (AbstractDialog): # TO and FROM name = self.tree.get_widget("nameEntry").get_text() - self.addr = self.tree.get_widget("mailEntry").get_text() + self.addr = self.mailEntry.get_text() if not self.addr: self.addr = self.TO @@ -157,7 +158,12 @@ class MailInfoWindow (AbstractDialog): return True def cb_send_clicked (self, *args): - self.set_data() - GtkThread(target = self.send, name = "Mail Send Thread").start() - self.close() + if self.mailEntry.get_text() or no_email_dialog(self.window) == gtk.RESPONSE_OK: + self.set_data() + GtkThread(target = self.send, name = "Mail Send Thread").start() + self.close() + else: + self.window.present() + self.mailEntry.grab_focus() + return True -- cgit v1.2.3 From dde6c85455fdcfd933c18c65a2c038c14093f525 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20=27Necoro=27=20Neumann?= Date: Sun, 14 Mar 2010 21:21:21 +0100 Subject: Better debug messages when updating database formats --- portato/db/sql.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/portato/db/sql.py b/portato/db/sql.py index a9c27ab..ea4ce91 100644 --- a/portato/db/sql.py +++ b/portato/db/sql.py @@ -47,6 +47,7 @@ class SQLDatabase (Database): updateFormat = False if "format" not in session or session["format"] != self.FORMAT: + debug("Need to update database format from '%s' to '%s'", session["format"], self.FORMAT) session["format"] = self.FORMAT updateFormat = True @@ -61,6 +62,7 @@ class SQLDatabase (Database): pkg_conn = sql.connect(pkgdb) pkg_conn.row_factory = sql.Row if pkgdb_existed and updateFormat: + debug("Dropping old table") pkg_conn.execute("DROP TABLE packages") pkg_conn.execute(""" -- cgit v1.2.3 From 0ed08eba908d3b0ca8fcc282c387c03f95250147 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20=27Necoro=27=20Neumann?= Date: Tue, 16 Mar 2010 02:55:26 +0100 Subject: Rewrote the database initialization to be a class instead of a function --- portato/db/__init__.py | 94 +++++++++++++++++++-------------------- portato/db/database.py | 2 + portato/db/exceptions.py | 24 ++++++++++ portato/db/sql.py | 2 +- portato/gui/exception_handling.py | 4 +- 5 files changed, 76 insertions(+), 50 deletions(-) create mode 100644 portato/db/exceptions.py diff --git a/portato/db/__init__.py b/portato/db/__init__.py index 21f72ce..850a84e 100644 --- a/portato/db/__init__.py +++ b/portato/db/__init__.py @@ -12,66 +12,66 @@ from __future__ import absolute_import +from . import database as db +from .exceptions import UnknownDatabaseTypeError, DatabaseInstantiationError from ..session import Session, SectionDict from ..helper import debug, warning, error -class UnknownDatabaseTypeError (Exception): - pass - -_SESSION = None -_TYPE = None -_DEFAULT = "dict" -_DATABASE = None - types = { "sql": (_("SQLite"), _("Uses an SQLite-database to store package information.\nMay take longer to generate at the first time, but has advantages if portato is re-started with an unchanged portage tree. Additionally it allows to use fast SQL expressions for fetching the data.")), "dict": (_("Hashmap"), _("Uses an in-memory hashmap to store package information.\nHas been used since at least version 0.3.3, but all information has to be regenerated on each startup.")), "eixsql" : (_("eix + SQLite"), _("Similar to SQLite, but now uses the eix database to get the package information.\nThis should be much faster on startup, but requires that your eix database is always up-to-date.\nAdditionally, this is the only database allowing searching in descriptions.")) } -def Database(type = None): - global _SESSION, _TYPE, _DATABASE +class Database(db.Database): + DEFAULT = "dict" - if type is None: - if _DATABASE is None: - warning("No database type specified! Falling back to default.") - return Database(_DEFAULT) - else: - return _DATABASE + def __new__ (cls, type = None): + if not '_the_instance' in cls.__dict__: + dbcls = cls._generate(type) + cls._the_instance = dbcls(cls._get_session()) + elif type is not None: + raise DatabaseInstantiationError("Database instantiation called with 'type' argument multiple times.") + return cls._the_instance - if _SESSION is None: - _SESSION = Session("db.cfg", name = "DB") - _SESSION.load() + @classmethod + def _generate(cls, type): - _TYPE = type + if type is None: + warning("No database type specified! Falling back to default.") + type = cls.DEFAULT + + cls.DB_TYPE = type - if type == "sql": - debug("Using SQLDatabase") - try: - from .sql import SQLDatabase - except ImportError: - warning(_("Cannot load %s."), "SQLDatabase") - _DATABASE = Database("dict") - else: - _DATABASE = SQLDatabase(SectionDict(_SESSION, type)) + if type == "sql": + debug("Using SQLDatabase") + try: + from .sql import SQLDatabase + except ImportError: + warning(_("Cannot load %s."), "SQLDatabase") + return cls._generate("dict") + else: + return SQLDatabase - elif type == "dict": - debug("Using HashDatabase") - from .hash import HashDatabase - _DATABASE = HashDatabase(SectionDict(_SESSION, type)) - - elif type == "eixsql": - debug("Using EixSQLDatabase") - try: - from .eix_sql import EixSQLDatabase - except ImportError: - warning(_("Cannot load %s."), "EixSQLDatabase.") - _DATABASE = Database("sql") - else: - _DATABASE = EixSQLDatabase(SectionDict(_SESSION, type)) + elif type == "dict": + debug("Using HashDatabase") + from .hash import HashDatabase + return HashDatabase + + elif type == "eixsql": + debug("Using EixSQLDatabase") + try: + from .eix_sql import EixSQLDatabase + except ImportError: + warning(_("Cannot load %s."), "EixSQLDatabase.") + return cls._generate("sql") + else: + return EixSQLDatabase - else: - error(_("Unknown database type: %s"), type) - raise UnknownDatabaseTypeError, type + else: + error(_("Unknown database type: %s"), type) + raise UnknownDatabaseTypeError, type - return _DATABASE + @classmethod + def _get_session(cls): + return SectionDict(Session("db.cfg", name = "DB"), cls.DB_TYPE) diff --git a/portato/db/database.py b/portato/db/database.py index 6e92d79..c679d06 100644 --- a/portato/db/database.py +++ b/portato/db/database.py @@ -16,6 +16,8 @@ from threading import RLock from functools import wraps from ..helper import warning +from .exceptions import UnsupportedSearchTypeError + class UnsupportedSearchTypeError(Exception): pass diff --git a/portato/db/exceptions.py b/portato/db/exceptions.py new file mode 100644 index 0000000..8a6e424 --- /dev/null +++ b/portato/db/exceptions.py @@ -0,0 +1,24 @@ +# -*- coding: utf-8 -*- +# +# File: portato/db/exceptions.py +# This file is part of the Portato-Project, a graphical portage-frontend. +# +# Copyright (C) 2006-2010 René 'Necoro' Neumann +# This is free software. You may redistribute copies of it under the terms of +# the GNU General Public License version 2. +# There is NO WARRANTY, to the extent permitted by law. +# +# Written by René 'Necoro' Neumann + +class DatabaseError (Exception): + pass + +class UnknownDatabaseTypeError (DatabaseError): + pass + +class DatabaseInstantiationError (DatabaseError): + pass + +class UnsupportedSearchTypeError(DatabaseError): + pass + diff --git a/portato/db/sql.py b/portato/db/sql.py index ea4ce91..f5dc257 100644 --- a/portato/db/sql.py +++ b/portato/db/sql.py @@ -120,7 +120,7 @@ class SQLDatabase (Database): os.remove(dbpath) db_existed = False - self.session["pickle"] = True # no need for a certain value + self.session["pickle"] = "1" # no need for a certain value if db_existed: debug("portdirs.db already existant") diff --git a/portato/gui/exception_handling.py b/portato/gui/exception_handling.py index dbafa7e..d9b133c 100644 --- a/portato/gui/exception_handling.py +++ b/portato/gui/exception_handling.py @@ -99,7 +99,7 @@ def convert (version): def get_version_infos(): from ..constants import VERSION, REVISION from ..backend import system - from ..db import _TYPE as db_type + from ..db import Database if REVISION: VERSION = "%s (git: %s)" % (VERSION, REVISION) @@ -109,7 +109,7 @@ def get_version_infos(): "System: %s" % " ".join(get_runsystem()), "Python version: %s" % sys.version, "Used backend: %s" % system.get_version(), - "Used database type: %s" % db_type, + "Used database type: %s" % Database.DB_TYPE, "pygtk: %s (using GTK+: %s)" % (convert(gtk.pygtk_version), convert(gtk.gtk_version)), "pygobject: %s (using GLib: %s)" % (convert(gobject.pygobject_version), convert(gobject.glib_version)))) -- cgit v1.2.3 From 5a52259b1404727718f57d44b266820542b9f1e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20=27Necoro=27=20Neumann?= Date: Fri, 26 Mar 2010 22:37:12 +0100 Subject: Fixed mailinfo window --- i18n/de.po | 4 +-- portato/gui/windows/mailinfo.py | 58 +++++++++++++++++++++++++++-------------- 2 files changed, 40 insertions(+), 22 deletions(-) diff --git a/i18n/de.po b/i18n/de.po index d60a707..9935870 100644 --- a/i18n/de.po +++ b/i18n/de.po @@ -3,7 +3,7 @@ msgstr "" "Project-Id-Version: Portato\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2010-03-14 21:03+0100\n" -"PO-Revision-Date: 2010-03-14 21:04+0100\n" +"PO-Revision-Date: 2010-03-26 22:31+0100\n" "Last-Translator: René 'Necoro' Neumann \n" "Language-Team: \n" "MIME-Version: 1.0\n" @@ -418,7 +418,7 @@ msgstr "Log" #: portato/gui/dialogs.py:17 msgid "Mail could not be sent" -msgstr "Mail konnte nicht gesendet werden: %s" +msgstr "Mail konnte nicht gesendet werden" #: portato/gui/dialogs.py:18 #, python-format diff --git a/portato/gui/windows/mailinfo.py b/portato/gui/windows/mailinfo.py index c5002e7..4367482 100644 --- a/portato/gui/windows/mailinfo.py +++ b/portato/gui/windows/mailinfo.py @@ -14,19 +14,23 @@ from __future__ import absolute_import, with_statement import smtplib, socket import time -import gtk, pango +import gtk, pango, gobject from email.mime.multipart import MIMEMultipart from email.mime.text import MIMEText from os.path import basename from .basic import AbstractDialog from ..utils import GtkThread -from ..dialogs import mail_failure_dialog, no_email_dialog +from .. import dialogs from ...helper import debug, info from ...constants import VERSION, CONFIG_LOCATION from ...log import LOGFILE from ... import session +def mail_failure_dialog(*a): + dialogs.mail_failure_dialog(*a) + return False + class ShowDialog (gtk.Dialog): def __init__(self, parent, f): @@ -51,7 +55,7 @@ class ShowDialog (gtk.Dialog): self.vbox.show_all() class MailInfoWindow (AbstractDialog): - TO = "bugs@portato.necoro.net" + TO = "bugs@necoro.eu" def __init__ (self, parent, tb): @@ -97,6 +101,7 @@ class MailInfoWindow (AbstractDialog): self.message = MIMEMultipart() self.message["Subject"] = "[Bug Report] Bug in Portato %s" % VERSION self.message["To"] = self.TO + self.message["X-Portato-Version"] = VERSION # TO and FROM name = self.tree.get_widget("nameEntry").get_text() @@ -134,31 +139,44 @@ class MailInfoWindow (AbstractDialog): def send (self): try: - debug("Connecting to server") - server = smtplib.SMTP("mail.necoro.eu") - debug("Sending mail") - try: - for i in range(5): # try 5 times at max - try: - server.sendmail(self.addr, self.TO, self.message.as_string()) - except smtplib.SMTPRecipientsRefused, e: + for i in range(5): # try 5 times at max + if i > 0: + info(_("Retrying after waiting %d seconds."), 300) + time.sleep(300) + try: + debug("Connecting to server") + server = smtplib.SMTP("mail.necoro.eu") + debug("Sending mail") + + if smtplib._have_ssl: server.starttls() + else: debug("TLS not supported in Python. Continuing without it.") + + server.sendmail(self.addr, self.TO, self.message.as_string()) + except smtplib.SMTPRecipientsRefused, e: + if e.recipients[self.TO][0] < 500: info(_("An error occurred while sending. I think we were greylisted. The error: %s") % e) - info(_("Retrying after waiting %d seconds."), 30) - time.sleep(30) - else: - debug("Sent") - break - finally: - server.quit() + else: raise + else: + debug("Sent") + break + finally: + try: + server.quit() + except smtplib.SMTPServerDisconnected: + pass # ignore this except socket.error, e: - mail_failure_dialog("%s (Code: %s)" % (e.args[1], e.args[0])) + gobject.idle_add(mail_failure_dialog, "%s (Code: %s)" % (e.args[1], e.args[0])) + except smtplib.SMTPResponseException, e: + gobject.idle_add(mail_failure_dialog, "%s (Code: %s)" % (e.smtp_error, e.smtp_code)) + except smtplib.SMTPException, e: + gobject.idle_add(mail_failure_dialog, e.args) def cb_cancel_clicked (self, *args): self.close() return True def cb_send_clicked (self, *args): - if self.mailEntry.get_text() or no_email_dialog(self.window) == gtk.RESPONSE_OK: + if self.mailEntry.get_text() or dialogs.no_email_dialog(self.window) == gtk.RESPONSE_OK: self.set_data() GtkThread(target = self.send, name = "Mail Send Thread").start() self.close() -- cgit v1.2.3 From c7b564ac84ad9fb7a72ee0896c2616b0383c68de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20=27Necoro=27=20Neumann?= Date: Thu, 1 Apr 2010 15:00:12 +0200 Subject: Fixed bug from switching to ConfigParser --- portato/gui/windows/main.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/portato/gui/windows/main.py b/portato/gui/windows/main.py index bc40a1f..3baf71c 100644 --- a/portato/gui/windows/main.py +++ b/portato/gui/windows/main.py @@ -1434,8 +1434,8 @@ class MainWindow (Window): """Execute the current queue.""" if len(flags.newUseFlags) > 0: - if not self.session.get_boolean("useflags", "dialogs"): - self.session.set("useflags", dialogs.changed_flags_dialog(_("use flags"))[1], "dialogs") + if not bool(self.session.get("useflags", "dialogs")): + self.session.set("useflags", str(dialogs.changed_flags_dialog(_("use flags"))[1]), "dialogs") try: flags.write_use_flags() except IOError, e: @@ -1446,8 +1446,8 @@ class MainWindow (Window): debug("new masked: %s",flags.new_masked) debug("new unmasked: %s", flags.new_unmasked) debug("new testing: %s", flags.newTesting) - if not self.session.get_boolean("keywords", "dialogs"): - self.session.set("keywords", dialogs.changed_flags_dialog(_("masking keywords"))[1], "dialogs") + if not bool(self.session.get("keywords", "dialogs")): + self.session.set("keywords", str(dialogs.changed_flags_dialog(_("masking keywords"))[1]), "dialogs") try: flags.write_masked() flags.write_testing() -- cgit v1.2.3 From 96cc1e3964d5ab94847a5756f0494f112b3dac15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20=27Necoro=27=20Neumann?= Date: Fri, 9 Apr 2010 23:33:52 +0200 Subject: Readded a Session.get_bool() method --- portato/gui/windows/main.py | 6 +++--- portato/session.py | 12 +++++++++--- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/portato/gui/windows/main.py b/portato/gui/windows/main.py index 3ba