[pygobject] Escape identifiers which are Python keywords
- From: Martin Pitt <martinpitt src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [pygobject] Escape identifiers which are Python keywords
- Date: Mon, 25 Jun 2012 07:45:29 +0000 (UTC)
commit 16280d6985f2cf4db9cf062e857650e620fd9da8
Author: Martin Pitt <martinpitt gnome org>
Date: Mon Jun 25 09:40:38 2012 +0200
Escape identifiers which are Python keywords
Add a trailing underscore to identifiers which are Python keywords.
We use a per-major-version static identifier list derived from keyword.kwlist
instead of calling out to Python's keyword.iskeyword(). This is much faster,
and also allows us to tweak the result. For example, Python 3 dropped "print"
as a keyword, but we still want to escape that to avoid breaking the API
between different Python versions.
Error out when building with a major Python version not covered yet, so that we
do not forget to update the list in the future.
https://bugzilla.gnome.org/show_bug.cgi?id=676746
gi/pygi-info.c | 38 +++++++++++++++++++++++++++++++++++++-
tests/test_gi.py | 17 +++++++++++++++++
2 files changed, 54 insertions(+), 1 deletions(-)
---
diff --git a/gi/pygi-info.c b/gi/pygi-info.c
index d850052..4efb467 100644
--- a/gi/pygi-info.c
+++ b/gi/pygi-info.c
@@ -95,7 +95,43 @@ PYGLIB_DEFINE_TYPE("gi.BaseInfo", PyGIBaseInfo_Type, PyGIBaseInfo);
static PyObject *
_wrap_g_base_info_get_name (PyGIBaseInfo *self)
{
- return PYGLIB_PyUnicode_FromString (g_base_info_get_name (self->info));
+ /* It may be better to use keyword.iskeyword(); keep in sync with
+ * python -c 'import keyword; print(keyword.kwlist)' */
+#if PY_VERSION_HEX < 0x03000000
+ /* Python 2.x */
+ static const gchar* keywords[] = {"and", "as", "assert", "break", "class",
+ "continue", "def", "del", "elif", "else", "except", "exec", "finally",
+ "for", "from", "global", "if", "import", "in", "is", "lambda", "not",
+ "or", "pass", "print", "raise", "return", "try", "while", "with",
+ "yield", NULL};
+#elif PY_VERSION_HEX < 0x04000000
+ /* Python 3.x; note that we explicitly keep "print"; it is not a keyword
+ * any more, but we do not want to break API between Python versions */
+ static const gchar* keywords[] = {"False", "None", "True", "and", "as",
+ "assert", "break", "class", "continue", "def", "del", "elif", "else",
+ "except", "finally", "for", "from", "global", "if", "import", "in",
+ "is", "lambda", "nonlocal", "not", "or", "pass", "raise", "return",
+ "try", "while", "with", "yield",
+ "print", NULL};
+#else
+ #error Need keyword list for this major Python version
+#endif
+
+ const gchar *name, **i;
+
+ name = g_base_info_get_name (self->info);
+
+ /* escape keywords */
+ for (i = keywords; *i != NULL; ++i) {
+ if (strcmp (name, *i) == 0) {
+ gchar *escaped = g_strconcat (name, "_", NULL);
+ PyObject *obj = PYGLIB_PyUnicode_FromString (escaped);
+ g_free (escaped);
+ return obj;
+ }
+ }
+
+ return PYGLIB_PyUnicode_FromString (name);
}
static PyObject *
diff --git a/tests/test_gi.py b/tests/test_gi.py
index 4ebbd68..6aa7445 100644
--- a/tests/test_gi.py
+++ b/tests/test_gi.py
@@ -2212,3 +2212,20 @@ class TestPropertiesObject(unittest.TestCase):
obj = GIMarshallingTests.PropertiesObject(some_boxed_struct=struct1)
self.assertEqual(obj.props.some_boxed_struct.long_, 1)
+
+
+class TestKeywords(unittest.TestCase):
+ def test_method(self):
+ # g_variant_print()
+ v = GLib.Variant('i', 1)
+ self.assertEqual(v.print_(False), '1')
+
+ def test_function(self):
+ # g_thread_yield()
+ self.assertEqual(GLib.Thread.yield_(), None)
+
+ def test_struct_method(self):
+ # g_timer_continue()
+ # we cannot currently instantiate GLib.Timer objects, so just ensure
+ # the method exists
+ self.assertTrue(callable(GLib.Timer.continue_))
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]