[pygobject] Add Python implementation of GError
- From: Simon Feltman <sfeltman src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [pygobject] Add Python implementation of GError
- Date: Mon, 5 May 2014 06:51:38 +0000 (UTC)
commit 3083daf420ac1900bb20604c22fd61e5187b4ae8
Author: Simon Feltman <sfeltman src gnome org>
Date: Sun May 4 04:13:46 2014 -0700
Add Python implementation of GError
Add internally used gi/_error.py module as a basis for implementing
a unified GError between introspection and static bindings. Patch Python
implementations of GError.matches and GError.new_literal in the GLib
overrides
https://bugzilla.gnome.org/show_bug.cgi?id=712519
Makefile.am | 3 +-
gi/_error.py | 53 ++++++++++++++++++++++++++++++++++++++++++++++++++
gi/_option.py | 3 +-
gi/overrides/GLib.py | 25 ++++++++++++++++++++++-
gi/pygi-error.c | 18 ++++++----------
tests/test_error.py | 37 ++++++++++++++++++++++++++++++++++
6 files changed, 125 insertions(+), 14 deletions(-)
---
diff --git a/Makefile.am b/Makefile.am
index 208ed13..968b6c9 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -65,7 +65,8 @@ nobase_pyexec_PYTHON = \
gi/_constants.py \
gi/_propertyhelper.py \
gi/_signalhelper.py \
- gi/_option.py
+ gi/_option.py \
+ gi/_error.py
# if we build in a separate tree, we need to symlink the *.py files from the
# source tree; Python does not accept the extensions and modules in different
diff --git a/gi/_error.py b/gi/_error.py
new file mode 100644
index 0000000..34a5317
--- /dev/null
+++ b/gi/_error.py
@@ -0,0 +1,53 @@
+# -*- Mode: Python; py-indent-offset: 4 -*-
+# vim: tabstop=4 shiftwidth=4 expandtab
+#
+# Copyright (C) 2014 Simon Feltman <sfeltman gnome org>
+#
+# _error.py: GError Python implementation
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library 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
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+# USA
+
+
+# NOTE: This file should not have any dependencies on introspection libs
+# like gi.repository.GLib because it would cause a circular dependency.
+# Developers wanting to use the GError class in their applications should
+# use gi.repository.GLib.GError
+
+
+class GError(RuntimeError):
+ def __init__(self, message='unknown error', domain='pygi-error', code=0):
+ super(GError, self).__init__(message)
+ self.message = message
+ self.domain = domain
+ self.code = code
+
+ def __str__(self):
+ return "%s: %s (%d)" % (self.domain, self.message, self.code)
+
+ def __repr__(self):
+ return "GLib.GError('%s', '%s', %d)" % (self.message, self.domain, self.code)
+
+ def copy(self):
+ return GError(self.message, self.domain, self.code)
+
+ def matches(self, domain, code):
+ """Placeholder that will be monkey patched in GLib overrides."""
+ raise NotImplementedError
+
+ @staticmethod
+ def new_literal(domain, message, code):
+ """Placeholder that will be monkey patched in GLib overrides."""
+ raise NotImplementedError
diff --git a/gi/_option.py b/gi/_option.py
index 4ffeb1d..2d30abf 100644
--- a/gi/_option.py
+++ b/gi/_option.py
@@ -40,7 +40,8 @@ else:
_basestring = basestring
_bytes = str
-from gi._gi import _glib, GError
+from gi._gi import _glib
+from gi._error import GError
GLib = get_introspection_module('GLib')
OPTION_CONTEXT_ERROR_QUARK = GLib.quark_to_string(GLib.option_error_quark())
diff --git a/gi/overrides/GLib.py b/gi/overrides/GLib.py
index c2462e3..d25d374 100644
--- a/gi/overrides/GLib.py
+++ b/gi/overrides/GLib.py
@@ -39,7 +39,9 @@ __all__.append('option')
# Types and functions still needed from static bindings
-from gi._gi import _glib, GError
+from gi._gi import _glib
+from gi._error import GError
+
OptionContext = _glib.OptionContext
OptionGroup = _glib.OptionGroup
Pid = _glib.Pid
@@ -51,6 +53,27 @@ def threads_init():
'See: https://wiki.gnome.org/PyGObject/Threading',
PyGIDeprecationWarning, stacklevel=2)
+
+def gerror_matches(self, domain, code):
+ # Handle cases where self.domain was set to an integer for compatibility
+ # with the introspected GLib.Error.
+ if isinstance(self.domain, str):
+ self_domain_quark = GLib.quark_from_string(self.domain)
+ else:
+ self_domain_quark = self.domain
+ return (self_domain_quark, self.code) == (domain, code)
+
+
+def gerror_new_literal(domain, message, code):
+ domain_quark = GLib.quark_to_string(domain)
+ return GError(message, domain_quark, code)
+
+
+# Monkey patch methods that rely on GLib introspection to be loaded at runtime.
+GError.matches = gerror_matches
+GError.new_literal = staticmethod(gerror_new_literal)
+
+
__all__ += ['GError', 'OptionContext', 'OptionGroup', 'Pid',
'spawn_async', 'threads_init']
diff --git a/gi/pygi-error.c b/gi/pygi-error.c
index 33275aa..d848a0e 100644
--- a/gi/pygi-error.c
+++ b/gi/pygi-error.c
@@ -314,16 +314,12 @@ pygi_arg_gerror_new_from_info (GITypeInfo *type_info,
void
pygi_error_register_types (PyObject *module)
{
- PyObject *dict;
- dict = PyDict_New();
- /* This is a hack to work around the deprecation warning of
- * BaseException.message in Python 2.6+.
- * GError has also an "message" attribute.
- */
- PyDict_SetItemString(dict, "message", Py_None);
- PyGError = PyErr_NewException("GLib.GError", PyExc_RuntimeError, dict);
- Py_DECREF(dict);
-
- PyModule_AddObject (module, "GError", PyGError);
+ PyObject *error_module = PyImport_ImportModule ("gi._error");
+ if (!error_module) {
+ return;
+ }
+
+ /* Stash a reference to the Python implemented gi._error.GError. */
+ PyGError = PyObject_GetAttrString (error_module, "GError");
}
diff --git a/tests/test_error.py b/tests/test_error.py
index a022fdd..a509b8a 100644
--- a/tests/test_error.py
+++ b/tests/test_error.py
@@ -5,6 +5,7 @@
#
# Copyright (C) 2012 Will Thompson
# Copyright (C) 2013 Martin Pitt
+# Copyright (C) 2014 Simon Feltman <sfeltman gnome org>
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
@@ -28,6 +29,42 @@ from gi.repository import GLib
from gi.repository import GIMarshallingTests
+class TestType(unittest.TestCase):
+ def test_attributes(self):
+ e = GLib.GError('test message', 'mydomain', 42)
+ self.assertEqual(e.message, 'test message')
+ self.assertEqual(e.domain, 'mydomain')
+ self.assertEqual(e.code, 42)
+
+ def test_new_literal(self):
+ mydomain = GLib.quark_from_string('mydomain')
+ e = GLib.GError.new_literal(mydomain, 'test message', 42)
+ self.assertEqual(e.message, 'test message')
+ self.assertEqual(e.domain, 'mydomain')
+ self.assertEqual(e.code, 42)
+
+ def test_matches(self):
+ mydomain = GLib.quark_from_string('mydomain')
+ notmydomain = GLib.quark_from_string('notmydomain')
+ e = GLib.GError('test message', 'mydomain', 42)
+ self.assertTrue(e.matches(mydomain, 42))
+ self.assertFalse(e.matches(notmydomain, 42))
+ self.assertFalse(e.matches(mydomain, 40))
+
+ def test_str(self):
+ e = GLib.GError('test message', 'mydomain', 42)
+ self.assertEqual(str(e),
+ 'mydomain: test message (42)')
+
+ def test_repr(self):
+ e = GLib.GError('test message', 'mydomain', 42)
+ self.assertEqual(repr(e),
+ "GLib.GError('test message', 'mydomain', 42)")
+
+ def test_inheritance(self):
+ self.assertTrue(issubclass(GLib.GError, RuntimeError))
+
+
class TestMarshalling(unittest.TestCase):
def test_array_in_crash(self):
# Previously there was a bug in invoke, in which C arrays were unwrapped
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]