-
Notifications
You must be signed in to change notification settings - Fork 57
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Make C modules Python 3 compatible #76
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -10,7 +10,11 @@ static PyObject *Skip_Filter_PyString = NULL; | |||||
|
||||||
// SanitizedPlaceholder Object | ||||||
typedef struct { | ||||||
#if PY_MAJOR_VERSION >= 3 | ||||||
PyUnicodeObject str; | ||||||
#else | ||||||
PyStringObject str; | ||||||
#endif | ||||||
} SanitizedPlaceholderObject; | ||||||
|
||||||
// Forward declare the type object. | ||||||
|
@@ -22,6 +26,17 @@ static PyTypeObject SanitizedPlaceholderType; | |||||
static PyObject * | ||||||
mark_as_sanitized(PyObject *self, PyObject *value) | ||||||
{ | ||||||
#if PY_MAJOR_VERSION >= 3 | ||||||
// If the value is not unicode, return it immediately. | ||||||
if (!PyUnicode_CheckExact(value)) { | ||||||
Py_INCREF(value); | ||||||
return value; | ||||||
} | ||||||
PyObject *args = Py_BuildValue("(N)", value); | ||||||
PyObject *obj = PyObject_CallObject((PyObject *) &SanitizedPlaceholderType, args); | ||||||
Py_DECREF(args); | ||||||
return obj; | ||||||
#else | ||||||
// If the value is not a string, return it immediately. | ||||||
if (!PyString_CheckExact(value)) { | ||||||
Py_INCREF(value); | ||||||
|
@@ -31,6 +46,9 @@ mark_as_sanitized(PyObject *self, PyObject *value) | |||||
Py_ssize_t size = PyString_GET_SIZE(value); | ||||||
// Allocate space for the SP object. | ||||||
PyObject *obj = PyType_GenericAlloc(&SanitizedPlaceholderType, size); | ||||||
if (obj == NULL) { | ||||||
return NULL; | ||||||
} | ||||||
SanitizedPlaceholderObject *sp_ptr = (SanitizedPlaceholderObject *)obj; | ||||||
// Set the hash and state. | ||||||
sp_ptr->str.ob_shash = ((PyStringObject *)value)->ob_shash; | ||||||
|
@@ -39,6 +57,7 @@ mark_as_sanitized(PyObject *self, PyObject *value) | |||||
// instantiating a new string object. | ||||||
memcpy(sp_ptr->str.ob_sval, PyString_AS_STRING(value), size+1); | ||||||
return obj; | ||||||
#endif | ||||||
} | ||||||
|
||||||
// Python function that checks if skip_filter is present on the function passed | ||||||
|
@@ -71,28 +90,38 @@ runtime_mark_as_sanitized(PyObject *self, PyObject *args) | |||||
static PyObject * | ||||||
sp_concat(PyObject *self, PyObject *other) | ||||||
{ | ||||||
PyObject *tmpself; | ||||||
#if PY_MAJOR_VERSION >= 3 | ||||||
tmpself = PyUnicode_Concat(self, other); | ||||||
#else | ||||||
// PyString_Concat requires an INCREF on self. | ||||||
Py_INCREF(self); | ||||||
PyString_Concat(&self, other); | ||||||
tmpself = self; | ||||||
#endif | ||||||
if (Py_TYPE(other) != &SanitizedPlaceholderType) { | ||||||
return self; | ||||||
return tmpself; | ||||||
} | ||||||
// PyString_Concat copies self turning it back into a string. Calling | ||||||
// mark_as_sanitized turns it back into a SanitizedPlaceholder. | ||||||
return mark_as_sanitized(self, self); | ||||||
return mark_as_sanitized(tmpself, tmpself); | ||||||
} | ||||||
|
||||||
// SanitizedPlaceholder method for mod (%). A SanitizedPlaceholder is returned | ||||||
// when both values are SanitizedPlaceholders. | ||||||
static PyObject * | ||||||
sp_mod(PyObject *self, PyObject *other) | ||||||
{ | ||||||
PyObject * val = PyString_Format(self, other); | ||||||
#if PY_MAJOR_VERSION >= 3 | ||||||
PyObject *val = PyUnicode_Format(self, other); | ||||||
#else | ||||||
PyObject *val = PyString_Format(self, other); | ||||||
#endif | ||||||
if (Py_TYPE(other) != &SanitizedPlaceholderType) { | ||||||
return val; | ||||||
} | ||||||
// If the other value was a SanitizedPlaceholder, we want to turn the string | ||||||
// result from PyString_Format into a SanitizedPlaceholder. This currently | ||||||
// result from Py*_Format into a SanitizedPlaceholder. This currently | ||||||
// copies over the string which is not the most efficient way to do this. | ||||||
return mark_as_sanitized(self, val); | ||||||
} | ||||||
|
@@ -112,14 +141,15 @@ static PyNumberMethods sp_as_number = { | |||||
0, /* nb_add */ | ||||||
0, /* nb_subtract */ | ||||||
0, /* nb_multiply */ | ||||||
#if PY_MAJOR_VERSION < 3 | ||||||
0, /* nb_divide */ | ||||||
#endif | ||||||
sp_mod, /* nb_remainder */ | ||||||
}; | ||||||
|
||||||
// SanitizedPlaceholder Type. | ||||||
static PyTypeObject SanitizedPlaceholderType = { | ||||||
PyObject_HEAD_INIT(NULL) | ||||||
0, /* ob_size */ | ||||||
PyVarObject_HEAD_INIT(NULL,0 ) | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
"baked.SanitizedPlaceholder", /* tp_name */ | ||||||
sizeof(SanitizedPlaceholderObject), /* tp_basicsize */ | ||||||
0, /* tp_itemsize */ | ||||||
|
@@ -139,8 +169,12 @@ static PyTypeObject SanitizedPlaceholderType = { | |||||
0, /* tp_setattro */ | ||||||
0, /* tp_as_buffer */ | ||||||
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | | ||||||
Py_TPFLAGS_CHECKTYPES | | ||||||
Py_TPFLAGS_STRING_SUBCLASS, /* tp_flags */ | ||||||
#if PY_MAJOR_VERSION >= 3 | ||||||
Py_TPFLAGS_UNICODE_SUBCLASS, /* tp_flags */ | ||||||
#else | ||||||
Py_TPFLAGS_CHECKTYPES | | ||||||
Py_TPFLAGS_STRING_SUBCLASS, /* tp_flags */ | ||||||
#endif | ||||||
0, /* tp_doc */ | ||||||
0, /* tp_traverse */ | ||||||
0, /* tp_clear */ | ||||||
|
@@ -151,7 +185,7 @@ static PyTypeObject SanitizedPlaceholderType = { | |||||
0, /* tp_methods */ | ||||||
0, /* tp_members */ | ||||||
0, /* tp_getset */ | ||||||
0, /* tp_base */ | ||||||
&PyUnicode_Type, /* tp_base */ | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Since we're conditionally setting
Suggested change
|
||||||
0, /* tp_dict */ | ||||||
0, /* tp_descr_get */ | ||||||
0, /* tp_descr_set */ | ||||||
|
@@ -169,25 +203,58 @@ static struct PyMethodDef baked_functions[] = { | |||||
{NULL, NULL} | ||||||
}; | ||||||
|
||||||
PyMODINIT_FUNC | ||||||
init_baked(void) | ||||||
#if PY_MAJOR_VERSION >= 3 | ||||||
static struct PyModuleDef moduledef = { | ||||||
PyModuleDef_HEAD_INIT, | ||||||
"_baked", /* m_name */ | ||||||
"Baked Module", /* m_doc */ | ||||||
-1, /* m_size */ | ||||||
baked_functions, /* m_methods */ | ||||||
NULL, /* m_reload */ | ||||||
NULL, /* m_traverse */ | ||||||
NULL, /* m_clear */ | ||||||
NULL, /* m_free */ | ||||||
}; | ||||||
#endif | ||||||
|
||||||
PyObject* moduleinit(void) | ||||||
{ | ||||||
PyObject *m; | ||||||
|
||||||
#if PY_MAJOR_VERSION >= 3 | ||||||
Skip_Filter_PyString = PyUnicode_InternFromString("skip_filter"); | ||||||
// Set the base type and the constructor. | ||||||
SanitizedPlaceholderType.tp_base = &PyUnicode_Type; | ||||||
SanitizedPlaceholderType.tp_init = PyUnicode_Type.tp_init; | ||||||
#else | ||||||
Skip_Filter_PyString = PyString_InternFromString("skip_filter"); | ||||||
|
||||||
// Set the base type and the constructor. | ||||||
SanitizedPlaceholderType.tp_base = &PyString_Type; | ||||||
SanitizedPlaceholderType.tp_init = PyString_Type.tp_init; | ||||||
if (PyType_Ready(&SanitizedPlaceholderType) < 0) | ||||||
return; | ||||||
#endif | ||||||
|
||||||
if (PyType_Ready(&SanitizedPlaceholderType) < 0) { | ||||||
return NULL; | ||||||
} | ||||||
|
||||||
// Add exported functions to the module. | ||||||
#if PY_MAJOR_VERSION >= 3 | ||||||
m = PyModule_Create(&moduledef); | ||||||
#else | ||||||
m = Py_InitModule3("_baked", baked_functions, "Baked Module"); | ||||||
if (m == NULL) | ||||||
return; | ||||||
#endif | ||||||
if (m == NULL) { | ||||||
return NULL; | ||||||
} | ||||||
|
||||||
Py_INCREF(&SanitizedPlaceholderType); | ||||||
PyModule_AddObject(m, "_SanitizedPlaceholder", | ||||||
(PyObject *) &SanitizedPlaceholderType); | ||||||
return m; | ||||||
} | ||||||
|
||||||
#if PY_MAJOR_VERSION < 3 | ||||||
PyMODINIT_FUNC init_baked(void) { (void)moduleinit(); } | ||||||
#else | ||||||
PyMODINIT_FUNC PyInit__baked(void) { return moduleinit(); } | ||||||
#endif |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -72,7 +72,7 @@ udn_resolve_udn(PyObject *self, PyObject *args, PyObject *kargs) | |
return NULL; | ||
} | ||
|
||
if (!(PyUnicode_Check(name) || PyString_Check(name))) { | ||
if (!(PyUnicode_Check(name) || PyBytes_Check(name))) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think you need to either include |
||
PyErr_SetString(PyExc_ValueError, "name must be string"); | ||
return NULL; | ||
} | ||
|
@@ -110,7 +110,7 @@ udn_resolve_from_search_list(PyObject *self, PyObject *args, PyObject *keywds) | |
return NULL; | ||
} | ||
|
||
if (!(PyUnicode_Check(name) || PyString_Check(name))) { | ||
if (!(PyUnicode_Check(name) || PyBytes_Check(name))) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think you need to either include |
||
PyErr_SetString(PyExc_ValueError, "name must be string"); | ||
return NULL; | ||
} | ||
|
@@ -155,15 +155,31 @@ static struct PyMethodDef udn_methods[] = { | |
{NULL, NULL} | ||
}; | ||
|
||
#if PY_MAJOR_VERSION >= 3 | ||
static struct PyModuleDef moduledef = { | ||
PyModuleDef_HEAD_INIT, | ||
"_udn", /* m_name */ | ||
"_udn module", /* m_doc */ | ||
-1, /* m_size */ | ||
udn_methods, /* m_methods */ | ||
NULL, /* m_reload */ | ||
NULL, /* m_traverse */ | ||
NULL, /* m_clear */ | ||
NULL, /* m_free */ | ||
}; | ||
#endif | ||
|
||
/* Initialization function (import-time) */ | ||
|
||
DL_EXPORT(void) | ||
init_udn(void) | ||
static PyObject* moduleinit(void) | ||
{ | ||
PyObject *m, *runtime_module; | ||
|
||
m = Py_InitModule("_udn", udn_methods); | ||
#if PY_MAJOR_VERSION >= 3 | ||
m = PyModule_Create(&moduledef); | ||
#else | ||
m = Py_InitModule3("_udn", udn_methods, "_udn module"); | ||
#endif | ||
|
||
runtime_module = PyImport_ImportModule("spitfire.runtime"); | ||
PlaceholderError = PyObject_GetAttrString( | ||
|
@@ -177,8 +193,15 @@ init_udn(void) | |
|
||
if (PyErr_Occurred()) | ||
Py_FatalError("Can't initialize module _udn"); | ||
return m; | ||
} | ||
|
||
#if PY_MAJOR_VERSION < 3 | ||
PyMODINIT_FUNC init_udn(void) { (void)moduleinit(); } | ||
#else | ||
PyMODINIT_FUNC PyInit__udn(void) { return moduleinit(); } | ||
#endif | ||
|
||
#ifdef __cplusplus | ||
} | ||
#endif |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you add a comment on why you are choosing
N
(and therefore not incrementing the reference count) instead ofO
?