[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[gpsd-dev] [PATCH 01/12] Fixes Python C extensions for Python 3 compatib
From: |
Fred Wright |
Subject: |
[gpsd-dev] [PATCH 01/12] Fixes Python C extensions for Python 3 compatibility. |
Date: |
Fri, 8 Apr 2016 10:07:42 -0700 |
These are necessary, but not sufficient, changes to make the C
extensions work "polyglot". These are believed to be complete as far
as the C code is concerned, and don't break Python 2 compatibility.
This puts all the stuff that needs to differ between Python 2 and
Python 3 into conditionally-defined macros in a new header file
python_compatibility.h. The definitions assume Python 2.6 or later.
In addition to the things requiring conditionals, the Lexer object was
using the deprecated tp_getattr entry, with a function based on
Py_FindMethod, which is gone in Python 3. However, the newer
tp_getattro entry can be pointed directly to PyObject_GenericGetAttr,
which works in Python 2 and 3.
Packet data returned by the Lexer is now 'bytes' in Python 3, which is
appropriate given that it may contain binary data. However, it means
that packet data can't be passed directly to anything expecting a
'str'. In Python 2, the data is just a 'str' as usual.
TESTED:
Ran "scons build-all check" and xgps (using Python 2.7). Also ran the
daemon and maidenhead-locator tests with Python 2.6.
---
gpsclient.c | 13 +++++++++----
gpspacket.c | 31 +++++++++++++------------------
python_compatibility.h | 44 ++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 66 insertions(+), 22 deletions(-)
create mode 100644 python_compatibility.h
diff --git a/gpsclient.c b/gpsclient.c
index 276900e..7b04ddc 100644
--- a/gpsclient.c
+++ b/gpsclient.c
@@ -10,6 +10,7 @@
#include "gps.h"
#include "gpsdclient.h"
#include "compiler.h" /* for UNUSED */
+#include "python_compatibility.h"
/*
* Client utility functions
@@ -83,13 +84,16 @@ PyDoc_STRVAR(module_doc,
/* banishes a pointless compiler warning */
extern PyMODINIT_FUNC initclienthelpers(void);
-PyMODINIT_FUNC
// cppcheck-suppress unusedFunction
-initclienthelpers(void)
+GPSD_PY_MODULE_INIT(clienthelpers)
{
PyObject *m;
- m = Py_InitModule3("gps.clienthelpers", gpsclient_methods, module_doc);
+ /* Create the module and add the functions */
+ GPSD_PY_MODULE_DEF(m, "clienthelpers", module_doc, gpsclient_methods)
+
+ if (m == NULL)
+ return GPSD_PY_MODULE_ERROR_VAL;
PyModule_AddIntConstant(m, "deg_dd", deg_dd);
PyModule_AddIntConstant(m, "deg_ddmm", deg_ddmm);
@@ -99,5 +103,6 @@ initclienthelpers(void)
PyModule_AddIntConstant(m, "imperial", imperial);
PyModule_AddIntConstant(m, "nautical", nautical);
PyModule_AddIntConstant(m, "metric", metric);
-}
+ return GPSD_PY_MODULE_SUCCESS_VAL(m);
+}
diff --git a/gpspacket.c b/gpspacket.c
index 06a41d3..0c9ade2 100644
--- a/gpspacket.c
+++ b/gpspacket.c
@@ -9,6 +9,7 @@
#include <stdio.h>
#include "gpsd.h"
+#include "python_compatibility.h"
static PyObject *ErrorObject = NULL;
@@ -94,7 +95,7 @@ Lexer_get(LexerObject *self, PyObject *args)
if (PyErr_Occurred())
return NULL;
- return Py_BuildValue("(i, i, s#, i)",
+ return Py_BuildValue("(i, i, " GPSD_PY_BYTE_FORMAT ", i)",
len,
self->lexer.type,
self->lexer.outbuffer,
@@ -125,12 +126,6 @@ static PyMethodDef Lexer_methods[] = {
{NULL, NULL} /* sentinel */
};
-static PyObject *
-Lexer_getattr(LexerObject *self, char *name)
-{
- return Py_FindMethod(Lexer_methods, (PyObject *)self, name);
-}
-
PyDoc_STRVAR(Lexer__doc__,
"GPS packet lexer object\n\
\n\
@@ -139,15 +134,14 @@ Fetch a single packet from file descriptor");
static PyTypeObject Lexer_Type = {
/* The ob_type field must be initialized in the module init function
* to be portable to Windows without using C++. */
- PyObject_HEAD_INIT(NULL)
- 0, /*ob_size*/
+ PyVarObject_HEAD_INIT(NULL, 0)
"gps.packet.lexer", /*tp_name*/
sizeof(LexerObject), /*tp_basicsize*/
0, /*tp_itemsize*/
/* methods */
(destructor)Lexer_dealloc, /*tp_dealloc*/
0, /*tp_print*/
- (getattrfunc)Lexer_getattr, /*tp_getattr*/
+ 0, /*tp_getattr*/
0, /*tp_setattr*/
0, /*tp_compare*/
0, /*tp_repr*/
@@ -157,11 +151,11 @@ static PyTypeObject Lexer_Type = {
0, /*tp_hash*/
0, /*tp_call*/
0, /*tp_str*/
- 0, /*tp_getattro*/
+ PyObject_GenericGetAttr, /*tp_getattro*/
0, /*tp_setattro*/
0, /*tp_as_buffer*/
Py_TPFLAGS_DEFAULT, /*tp_flags*/
- Lexer__doc__, /*tp_doc*/
+ Lexer__doc__, /*tp_doc*/
0, /*tp_traverse*/
0, /*tp_clear*/
0, /*tp_richcompare*/
@@ -255,17 +249,16 @@ level of the message and the message itself.\n\
/* banishes a pointless compiler warning */
extern PyMODINIT_FUNC initpacket(void);
-PyMODINIT_FUNC
// cppcheck-suppress unusedFunction
-initpacket(void)
+GPSD_PY_MODULE_INIT(packet)
{
PyObject *m;
- if (PyType_Ready(&Lexer_Type) < 0)
- return;
-
/* Create the module and add the functions */
- m = Py_InitModule3("packet", packet_methods, module_doc);
+ GPSD_PY_MODULE_DEF(m, "packet", module_doc, packet_methods)
+
+ if (m == NULL || PyType_Ready(&Lexer_Type) < 0)
+ return GPSD_PY_MODULE_ERROR_VAL;
PyModule_AddIntConstant(m, "BAD_PACKET", BAD_PACKET);
PyModule_AddIntConstant(m, "COMMENT_PACKET", COMMENT_PACKET);
@@ -298,4 +291,6 @@ initpacket(void)
PyModule_AddIntConstant(m, "LOG_DATA", LOG_DATA);
PyModule_AddIntConstant(m, "LOG_SPIN", LOG_SPIN);
PyModule_AddIntConstant(m, "LOG_RAW", LOG_RAW);
+
+ return GPSD_PY_MODULE_SUCCESS_VAL(m);
}
diff --git a/python_compatibility.h b/python_compatibility.h
new file mode 100644
index 0000000..635cd06
--- /dev/null
+++ b/python_compatibility.h
@@ -0,0 +1,44 @@
+/*
+ * python_compatibility.h -- macros for Python 2/3 compatibility
+ *
+ * This file is Copyright (c) 2016 by the GPSD project
+ * BSD terms apply: see the file COPYING in the distribution root for details.
+ *
+ * Definitions based on examples in "Supporting Python 3 - The Book Site"
+ * http://python3porting.com/cextensions.html
+ */
+
+#ifndef _PYTHON_COMPATIBILITY_H_
+#define _PYTHON_COMPATIBILITY_H_
+
+#include <Python.h>
+
+#if PY_MAJOR_VERSION >= 3
+
+#define GPSD_PY_MODULE_INIT(name) PyMODINIT_FUNC PyInit_##name(void)
+
+#define GPSD_PY_MODULE_DEF(mod, name, doc, methods) \
+ static struct PyModuleDef moduledef = { \
+ PyModuleDef_HEAD_INIT, name, doc, -1, methods, }; \
+ mod = PyModule_Create(&moduledef);
+
+#define GPSD_PY_MODULE_ERROR_VAL NULL
+#define GPSD_PY_MODULE_SUCCESS_VAL(val) val
+
+#define GPSD_PY_BYTE_FORMAT "y#"
+
+#else /* !Python 3 */
+
+#define GPSD_PY_MODULE_INIT(name) PyMODINIT_FUNC init##name(void)
+
+#define GPSD_PY_MODULE_DEF(mod, name, doc, methods) \
+ mod = Py_InitModule3(name, methods, doc);
+
+#define GPSD_PY_MODULE_ERROR_VAL
+#define GPSD_PY_MODULE_SUCCESS_VAL(val)
+
+#define GPSD_PY_BYTE_FORMAT "s#"
+
+#endif /* !Python 3 */
+
+#endif /* _PYTHON_COMPATIBILITY_H_ */
--
2.8.0
- [gpsd-dev] Python 3 Updates, Fred Wright, 2016/04/08
- [gpsd-dev] [PATCH 01/12] Fixes Python C extensions for Python 3 compatibility.,
Fred Wright <=
- [gpsd-dev] [PATCH 02/12] Fixes fake.py 'packet' import for Python 3., Fred Wright, 2016/04/08
- [gpsd-dev] [PATCH 04/12] Fixes xgps for Python 3., Fred Wright, 2016/04/08
- [gpsd-dev] [PATCH 05/12] Fixes a client.py exception for Python 3., Fred Wright, 2016/04/08
- [gpsd-dev] [PATCH 06/12] Fixes Gtk warnings related to xgps/xgpsspeed error boxes., Fred Wright, 2016/04/08
- [gpsd-dev] [PATCH 07/12] Changes type checks in misc.py:isotime to use isinstance()., Fred Wright, 2016/04/08
- [gpsd-dev] [PATCH 03/12] Forces Python 3 import behavior in all gps/* modules., Fred Wright, 2016/04/08
- [gpsd-dev] [PATCH 09/12] Fixes gpscat and test_maidenhead.py for Python 3., Fred Wright, 2016/04/08
- [gpsd-dev] [PATCH 08/12] Removes unnecessary Unicode literal from xgps., Fred Wright, 2016/04/08
- [gpsd-dev] [PATCH 10/12] Fixes fake.py and gpsfake for Python 3., Fred Wright, 2016/04/08
- [gpsd-dev] [PATCH 12/12] Removes redundant polystr/polybytes defs from client.py., Fred Wright, 2016/04/08