Skip to content

Commit

Permalink
Starting at porting py2 pygtk to py3 PyGObject
Browse files Browse the repository at this point in the history
Steps here:
- ran remove_utf-8.py (included here) via find for all .py files.
- ran pygi-convert.sh via find also
- ran $ 2to3 -f all . > refact_2to3.txt   (included here) to capture the
diff of the changes to be made.
- ran $ 2to3 -w -f all .   and copied the messages to
refact_2to3_messages.txt (included here)
  • Loading branch information
RoDuth committed Oct 24, 2020
1 parent 5fa8e36 commit ffac89e
Show file tree
Hide file tree
Showing 116 changed files with 20,884 additions and 4,391 deletions.
84 changes: 41 additions & 43 deletions bauble/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
# -*- coding: utf-8 -*-
#
# Copyright (c) 2005,2006,2007,2008,2009 Brett Adams <[email protected]>
# Copyright (c) 2012-2017 Mario Frasca <[email protected]>
# Copyright 2017 Jardín Botánico de Quito
Expand Down Expand Up @@ -82,9 +80,9 @@ def pb_release():
os.pathsep, os.environ['PATH'])


# if not hasattr(gtk.Widget, 'set_tooltip_markup'):
# if not hasattr(Gtk.Widget, 'set_tooltip_markup'):
# msg = _('Ghini requires GTK+ version 2.12 or greater')
# utils.message_dialog(msg, gtk.MESSAGE_ERROR)
# utils.message_dialog(msg, Gtk.MessageType.ERROR)
# sys.exit(1)

# make sure we look in the lib path for modules
Expand Down Expand Up @@ -130,18 +128,18 @@ def quit():
"""
Stop all tasks and quit Ghini.
"""
import gtk
from gi.repository import Gtk
import bauble.utils as utils
try:
import bauble.task as task
except Exception, e:
except Exception as e:
logger.error('bauble.quit(): %s' % utils.utf8(e))
else:
task.kill()
try:
save_state()
gtk.main_quit()
except RuntimeError, e:
Gtk.main_quit()
except RuntimeError as e:
# in case main_quit is called before main, e.g. before
# bauble.main() is called
sys.exit(1)
Expand All @@ -161,14 +159,14 @@ def command_handler(cmd, arg):
:type arg: list
"""
logger.debug('entering ui.command_handler %s %s' % (cmd, arg))
import gtk
from gi.repository import Gtk
import bauble.utils as utils
import bauble.pluginmgr as pluginmgr
global last_handler
handler_cls = None
try:
handler_cls = pluginmgr.commands[cmd]
except KeyError, e:
except KeyError as e:
if cmd is None:
utils.message_dialog(_('No default handler registered'))
else:
Expand All @@ -190,11 +188,11 @@ def command_handler(cmd, arg):
gui.window.add_accel_group(handler_view.accel_group)
try:
last_handler(cmd, arg)
except Exception, e:
except Exception as e:
msg = utils.xml_safe(e)
logger.error('bauble.command_handler(): %s' % msg)
utils.message_details_dialog(
msg, traceback.format_exc(), gtk.MESSAGE_ERROR)
msg, traceback.format_exc(), Gtk.MessageType.ERROR)


conn_default_pref = "conn.default"
Expand All @@ -212,16 +210,16 @@ def main(uri=None):
:type uri: str
"""
# TODO: it would be nice to show a Tk dialog here saying we can't
# import gtk...but then we would have to include all of the Tk libs in
# import Gtk...but then we would have to include all of the Tk libs in
# with the win32 batteries-included installer
try:
import gtk
import gobject
except ImportError, e:
print _('** Error: could not import gtk and/or gobject')
print e
from gi.repository import Gtk
from gi.repository import GObject
except ImportError as e:
print(_('** Error: could not import gtk and/or gobject'))
print(e)
if sys.platform == 'win32':
print _('Please make sure that GTK_ROOT\\bin is in your PATH.')
print(_('Please make sure that GTK_ROOT\\bin is in your PATH.'))
sys.exit(1)

# create the user directory
Expand Down Expand Up @@ -282,30 +280,30 @@ def main(uri=None):
else:
logger.debug('not registering sentry client')

except Exception, e:
except Exception as e:
logger.warning("can't configure sentry client")
logger.debug("%s(%s)" % (type(e).__name__, e))

import gtk.gdk
import pygtk
import Gtk.gdk
import gi
if not paths.main_is_frozen():
pygtk.require("2.0")
gi.require_version("Gtk", "3.0")

display = gtk.gdk.display_get_default()
display = Gdk.Display.get_default()
if display is None:
print _("**Error: Ghini must be run in a windowed environment.")
print(_("**Error: Ghini must be run in a windowed environment."))
sys.exit(1)

import bauble.pluginmgr as pluginmgr
import bauble.utils as utils

# initialize threading
gobject.threads_init()
GObject.threads_init()

try:
import bauble.db as db
except Exception, e:
utils.message_dialog(utils.xml_safe(e), gtk.MESSAGE_ERROR)
except Exception as e:
utils.message_dialog(utils.xml_safe(e), Gtk.MessageType.ERROR)
sys.exit(1)

# declare module level variables
Expand All @@ -330,26 +328,26 @@ def main(uri=None):
break
else:
uri = conn_name = None
except err.VersionError, e:
except err.VersionError as e:
logger.warning("%s(%s)" % (type(e), e))
db.open(uri, False)
break
except (err.EmptyDatabaseError, err.MetaTableError,
err.VersionError, err.TimestampError,
err.RegistryError), e:
err.RegistryError) as e:
logger.info("%s(%s)" % (type(e), e))
open_exc = e
# reopen without verification so that db.Session and
# db.engine, db.metadata will be bound to an engine
db.open(uri, False)
break
except err.DatabaseError, e:
except err.DatabaseError as e:
logger.debug("%s(%s)" % (type(e).__name__, e))
open_exc = e
except Exception, e:
except Exception as e:
msg = _("Could not open connection.\n\n%s") % e
utils.message_details_dialog(msg, traceback.format_exc(),
gtk.MESSAGE_ERROR)
Gtk.MessageType.ERROR)
uri = None
else:
db.open(uri, True, True)
Expand All @@ -371,7 +369,7 @@ def main(uri=None):
gui = ui.GUI()

def _post_loop():
gtk.gdk.threads_enter()
Gdk.threads_enter()
try:
if isinstance(open_exc, err.DatabaseError):
msg = _('Would you like to create a new Ghini database at '
Expand All @@ -388,32 +386,32 @@ def _post_loop():
pluginmgr.init()
# set the default connection
prefs[conn_default_pref] = conn_name
except Exception, e:
except Exception as e:
utils.message_details_dialog(utils.xml_safe(e),
traceback.format_exc(),
gtk.MESSAGE_ERROR)
Gtk.MessageType.ERROR)
logger.error("%s(%s)" % (type(e).__name__, e))
else:
pluginmgr.init()
except Exception, e:
except Exception as e:
logger.warning("%s\n%s(%s)"
% (traceback.format_exc(), type(e).__name__, e))
msg = utils.utf8("%s(%s)" % (type(e).__name__, e))
utils.message_dialog(msg, gtk.MESSAGE_WARNING)
utils.message_dialog(msg, Gtk.MessageType.WARNING)
gui.get_view().update()
gtk.gdk.threads_leave()
Gdk.threads_leave()

gobject.idle_add(_post_loop)
GObject.idle_add(_post_loop)
logger.info('This version installed on: %s; '
'This version installed at: %s; '
'Latest published version: %s; '
'Publication date: %s' %
(bauble.installation_date, __file__, bauble.release_version, bauble.release_date, ))

gui.show()
gtk.threads_enter()
gtk.main()
Gtk.threads_enter()
Gtk.main()
active_view = gui.get_view()
if active_view:
active_view.cancel_threads()
gtk.threads_leave()
Gtk.threads_leave()
4 changes: 1 addition & 3 deletions bauble/assistant.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
# -*- coding: utf-8 -*-
#
# Copyright (c) 2005,2006,2007,2008,2009 Brett Adams <[email protected]>
# Copyright (c) 2012-2015 Mario Frasca <[email protected]>
#
Expand All @@ -20,7 +18,7 @@
#
# assistant.py
#
# Descriptions: use gtk.Assistant to create a new database wizard
# Descriptions: use Gtk.Assistant to create a new database wizard
#
# issue #29: implement the assistant
#
10 changes: 4 additions & 6 deletions bauble/btypes.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
# -*- coding: utf-8 -*-
#
# Copyright (c) 2005,2006,2007,2008,2009 Brett Adams <[email protected]>
# Copyright (c) 2012-2017 Mario Frasca <[email protected]>
#
Expand Down Expand Up @@ -59,12 +57,12 @@ def __init__(self, values, empty_to_none=False, strict=True,
except TypeError:
raise EnumError(_('Enum requires string values (or None)'))
if set(type(x) for x in values if x is not None) - \
set([type(''), type(u'')]) != set():
set([type(''), type('')]) != set():
raise EnumError(_('Enum requires string values (or None)'))
if len(values) != len(set(values)):
raise EnumError(_('Enum requires the values to be different'))
self.translations = dict((v, v) for v in values)
for key, value in translations.iteritems():
for key, value in translations.items():
self.translations[key] = value
if empty_to_none and None not in values:
raise EnumError(_('You have configured empty_to_none=True but '
Expand Down Expand Up @@ -112,7 +110,7 @@ class DateTime(types.TypeDecorator):
_rx_tz = re.compile('[+-]')

def process_bind_param(self, value, dialect):
if not isinstance(value, basestring):
if not isinstance(value, str):
return value
try:
DateTime._dayfirst
Expand Down Expand Up @@ -140,7 +138,7 @@ class Date(types.TypeDecorator):
impl = types.Date

def process_bind_param(self, value, dialect):
if not isinstance(value, basestring):
if not isinstance(value, str):
return value
try:
Date._dayfirst
Expand Down
Loading

3 comments on commit ffac89e

@mfrasca
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hi. any reason to start this port 2→3 from scratch?

@RoDuth
Copy link
Owner Author

@RoDuth RoDuth commented on ffac89e Feb 2, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I spent a fair amount of time looking into Ghini#432 Ghini#403 (the windows installer being the big one) and had no luck with the libchamplain/clutter issue I mentioned. (see: here. Also see: libshumate and issue1 but all that is GTK4 and not much use right now.).

So, with some spare time during a COVID lock down (and perhaps naively), I decided to go back to a version I knew worked and work forward from there. Trying for a more modest python 3 version and checking in mac and windows (including packaging as soon as I thought it practical) as I went. Was mostly a proof of concept. I had read that it wasn't possible (or at least worth while) to package PyGObject for windows, see here, and this would be a deal breaker for me. I had also been unable to get py2exe working in mingw at all but had also seen some pyinstaller commits that seemed to be aimed at mingw pygobject projects etc.. In the end the packaging portion was relatively easy! (see .appveyor.yml, ghini.spec etc.). So concept proved. Where to from here? I'm not really sure to be honest. I haven't looked at this or v3.1 in some time now.

@mfrasca
Copy link

@mfrasca mfrasca commented on ffac89e Feb 2, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you see, the difficulties with making an old Desktop, Gtk2, Glade, Python2, SqlAlchemy program work on modern OS can in my opinion only be solved by dropping all those now outdated choices. you may have seen "ghini reloaded" and the web instances I had started to create, hoping to raise some interest among users.

both ghini-3.1 and ghini-1.0 have serious trouble with threading and concurrency, partially "solved" using the fibra module, which was unpublished until I put it in pip, and which has never been included in Debian. fibra implements a cooperative concurrency model, resembling early Windows 3, something rather insulting to programmers, and not only this century. however, if you look at your logs I'm sure you will see loads of complaints about objects being closed in a thread while they belong to an other. I have not solved this, and I think it's giving more trouble in Python3 that it was doing in Python2.

thus "ghini reloaded".

for which I have no users who showed any commitment.

Please sign in to comment.