-
Notifications
You must be signed in to change notification settings - Fork 41
Support ipaddress objects in "get" method #48
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
Changes from all commits
7095aeb
76b6122
a70962c
a609d64
332cdd0
6d2cb82
c101148
b190d97
5fbde66
4bd9b2f
83832e1
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 |
|---|---|---|
|
|
@@ -107,9 +107,64 @@ static int Reader_init(PyObject *self, PyObject *args, PyObject *kwds) | |
| static PyObject *Reader_get(PyObject *self, PyObject *args) | ||
| { | ||
| char *ip_address = NULL; | ||
| PyObject *object = NULL; | ||
| #if PY_MAJOR_VERSION >= 3 | ||
| PyObject *bytes = NULL; | ||
| #endif | ||
|
|
||
| Reader_obj *mmdb_obj = (Reader_obj *)self; | ||
| if (!PyArg_ParseTuple(args, "s", &ip_address)) { | ||
|
|
||
| if (PyArg_ParseTuple(args, "s", &ip_address)) { | ||
| // pass | ||
| } else if (PyErr_Clear(), PyArg_ParseTuple(args, "O", &object)) { | ||
| PyObject* module = PyImport_ImportModule("ipaddress"); | ||
| if (module == NULL) { | ||
| return NULL; | ||
| } | ||
|
|
||
| PyObject* module_dict = PyModule_GetDict(module); | ||
| if (module_dict == NULL) { | ||
| return NULL; | ||
| } | ||
|
|
||
| PyObject* ipaddress_IPv4Address = PyDict_GetItemString( | ||
|
Member
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. Shouldn't we be using
Author
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'm calling |
||
| module_dict, "IPv4Address"); | ||
| int is_ipaddress_object = 0; | ||
|
|
||
| if (ipaddress_IPv4Address != NULL) { | ||
| is_ipaddress_object = PyObject_IsInstance(ipaddress_IPv4Address, | ||
| object); | ||
| } | ||
|
|
||
| PyObject* ipaddress_IPv6Address; | ||
| if (!is_ipaddress_object && | ||
| (ipaddress_IPv6Address = PyDict_GetItemString(module_dict, | ||
| "IPv6Address")) != NULL) { | ||
| is_ipaddress_object = PyObject_IsInstance(ipaddress_IPv6Address, | ||
| object); | ||
| } | ||
|
|
||
| PyErr_Clear(); | ||
| PyObject *str; | ||
|
|
||
| if (!is_ipaddress_object) { | ||
| PyErr_SetString(PyExc_TypeError, "IP address must be a string," | ||
| " ipaddress.IPv4Address or ipaddress.IPv6Address object"); | ||
| } else if ((str = PyObject_Str(object)) != NULL) { | ||
|
Member
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. It is a little bit weird that we are doing all of these gymnastics and creating these heavy Python string and byte objects. I wonder if we could just get the packed address. Ideally, we wouldn't even bother converting that back to a *char, but it probably doesn't hurt too much to do that conversion.
Author
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. The only simpler method I could think of would be casting the argument to a
Author
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.
That is exposed: |
||
| #if PY_MAJOR_VERSION >= 3 | ||
| bytes = PyUnicode_AsEncodedString(str, "UTF-8", "strict"); | ||
| ip_address = PyBytes_AS_STRING(bytes); | ||
|
Member
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. If this code is kept, I think you can just decrement the reference count on bytes here and get rid of the ones below. There are also leaks from early returns as it is done now.
Author
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. Does Python guarantee that garbage collection will not immediately take place when the reference counter drops to 0? The reason I'm i'm decrementing the reference count in more than one place is because the |
||
| #else | ||
| ip_address = PyString_AsString(str); | ||
| #endif | ||
| } | ||
|
|
||
| Py_DECREF(module); | ||
| } else { | ||
| return NULL; | ||
| } | ||
|
|
||
| if (ip_address == NULL) { | ||
| return NULL; | ||
| } | ||
|
|
||
|
|
@@ -131,6 +186,10 @@ static PyObject *Reader_get(PyObject *self, PyObject *args) | |
| PyErr_Format(PyExc_ValueError, | ||
| "'%s' does not appear to be an IPv4 or IPv6 address.", | ||
| ip_address); | ||
|
|
||
| #if PY_MAJOR_VERSION >= 3 | ||
| Py_XDECREF(bytes); | ||
| #endif | ||
| return NULL; | ||
| } | ||
|
|
||
|
|
@@ -143,6 +202,9 @@ static PyObject *Reader_get(PyObject *self, PyObject *args) | |
| } | ||
| PyErr_Format(exception, "Error looking up %s. %s", | ||
| ip_address, MMDB_strerror(mmdb_error)); | ||
| #if PY_MAJOR_VERSION >= 3 | ||
| Py_XDECREF(bytes); | ||
| #endif | ||
| return NULL; | ||
| } | ||
|
|
||
|
|
@@ -157,9 +219,16 @@ static PyObject *Reader_get(PyObject *self, PyObject *args) | |
| "Error while looking up data for %s. %s", | ||
| ip_address, MMDB_strerror(status)); | ||
| MMDB_free_entry_data_list(entry_data_list); | ||
| #if PY_MAJOR_VERSION >= 3 | ||
| Py_XDECREF(bytes); | ||
| #endif | ||
| return NULL; | ||
| } | ||
|
|
||
| #if PY_MAJOR_VERSION >= 3 | ||
| Py_XDECREF(bytes); | ||
| #endif | ||
|
|
||
| MMDB_entry_data_list_s *original_entry_data_list = entry_data_list; | ||
| PyObject *py_obj = from_entry_data_list(&entry_data_list); | ||
| MMDB_free_entry_data_list(original_entry_data_list); | ||
|
|
||
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.
No need to declare the variables at the top of the function.
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.
Where do you propose I declare it? I don't think I can declare it inside the "if" condition since that will cause "bytes" to be scoped to that block which will mean it can't be used in the code further down.
Uh oh!
There was an error while loading. Please reload this page.
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.
I also can't declare
objectinside the "if" block because I need to useobjectin the condition expression.