From: Michael Tremer Date: Tue, 15 Oct 2019 15:10:26 +0000 (+0000) Subject: python: Extend bindings for countries X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=af208e26c6952036955e8e10e08fa3108a9dde2d;p=people%2Fsennis%2Flibloc.git python: Extend bindings for countries Signed-off-by: Michael Tremer --- diff --git a/Makefile.am b/Makefile.am index afc5833..3dca0fe 100644 --- a/Makefile.am +++ b/Makefile.am @@ -120,6 +120,8 @@ src_python_location_la_SOURCES = \ src/python/locationmodule.h \ src/python/as.c \ src/python/as.h \ + src/python/country.c \ + src/python/country.h \ src/python/database.c \ src/python/database.h \ src/python/network.c \ diff --git a/src/country.c b/src/country.c index ca16c6d..22719c9 100644 --- a/src/country.c +++ b/src/country.c @@ -113,7 +113,7 @@ LOC_EXPORT int loc_country_set_name(struct loc_country* country, const char* nam return 0; } -int loc_country_cmp(struct loc_country* country1, struct loc_country* country2) { +LOC_EXPORT int loc_country_cmp(struct loc_country* country1, struct loc_country* country2) { return strcmp(country1->code, country2->code); } diff --git a/src/libloc.sym b/src/libloc.sym index 8ed931d..7cd7405 100644 --- a/src/libloc.sym +++ b/src/libloc.sym @@ -37,6 +37,7 @@ global: loc_as_unref; # Country + loc_country_cmp; loc_country_get_code; loc_country_get_continent_code; loc_country_get_name; diff --git a/src/python/country.c b/src/python/country.c new file mode 100644 index 0000000..1247a08 --- /dev/null +++ b/src/python/country.c @@ -0,0 +1,178 @@ +/* + libloc - A library to determine the location of someone on the Internet + + Copyright (C) 2019 IPFire Development Team + + 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. +*/ + +#include + +#include +#include + +#include "locationmodule.h" +#include "country.h" + +PyObject* new_country(PyTypeObject* type, struct loc_country* country) { + CountryObject* self = (CountryObject*)type->tp_alloc(type, 0); + if (self) { + self->country = loc_country_ref(country); + } + + return (PyObject*)self; +} + +static PyObject* Country_new(PyTypeObject* type, PyObject* args, PyObject* kwds) { + CountryObject* self = (CountryObject*)type->tp_alloc(type, 0); + + return (PyObject*)self; +} + +static void Country_dealloc(CountryObject* self) { + if (self->country) + loc_country_unref(self->country); + + Py_TYPE(self)->tp_free((PyObject* )self); +} + +static int Country_init(CountryObject* self, PyObject* args, PyObject* kwargs) { + const char* country_code = NULL; + + if (!PyArg_ParseTuple(args, "s", &country_code)) + return -1; + + // Create the country object + int r = loc_country_new(loc_ctx, &self->country, country_code); + if (r) + return -1; + + return 0; +} + +static PyObject* Country_repr(CountryObject* self) { + const char* code = loc_country_get_code(self->country); + const char* name = loc_country_get_name(self->country); + + if (name) + return PyUnicode_FromFormat("", code, name); + + return PyUnicode_FromFormat("", code); +} + +static PyObject* Country_get_code(CountryObject* self) { + const char* code = loc_country_get_code(self->country); + + return PyUnicode_FromString(code); +} + +static PyObject* Country_str(CountryObject* self) { + return Country_get_code(self); +} + +static PyObject* Country_get_name(CountryObject* self) { + const char* name = loc_country_get_name(self->country); + + return PyUnicode_FromString(name); +} + +static int Country_set_name(CountryObject* self, PyObject* value) { + const char* name = PyUnicode_AsUTF8(value); + + int r = loc_country_set_name(self->country, name); + if (r) { + PyErr_Format(PyExc_ValueError, "Could not set name: %s", name); + return r; + } + + return 0; +} + +static PyObject* Country_get_continent_code(CountryObject* self) { + const char* code = loc_country_get_continent_code(self->country); + + return PyUnicode_FromString(code); +} + +static int Country_set_continent_code(CountryObject* self, PyObject* value) { + const char* code = PyUnicode_AsUTF8(value); + + int r = loc_country_set_continent_code(self->country, code); + if (r) { + PyErr_Format(PyExc_ValueError, "Could not set continent code: %s", code); + return r; + } + + return 0; +} + +static PyObject* Country_richcompare(CountryObject* self, CountryObject* other, int op) { + int r = loc_country_cmp(self->country, other->country); + + switch (op) { + case Py_EQ: + if (r == 0) + Py_RETURN_TRUE; + + Py_RETURN_FALSE; + + case Py_LT: + if (r < 0) + Py_RETURN_TRUE; + + Py_RETURN_FALSE; + + default: + break; + } + + Py_RETURN_NOTIMPLEMENTED; +} + +static struct PyGetSetDef Country_getsetters[] = { + { + "code", + (getter)Country_get_code, + NULL, + NULL, + NULL, + }, + { + "name", + (getter)Country_get_name, + (setter)Country_set_name, + NULL, + NULL, + }, + { + "continent_code", + (getter)Country_get_continent_code, + (setter)Country_set_continent_code, + NULL, + NULL, + }, + { NULL }, +}; + +PyTypeObject CountryType = { + PyVarObject_HEAD_INIT(NULL, 0) + .tp_name = "location.Country", + .tp_basicsize = sizeof(CountryObject), + .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, + .tp_new = Country_new, + .tp_dealloc = (destructor)Country_dealloc, + .tp_init = (initproc)Country_init, + .tp_doc = "Country object", + .tp_getset = Country_getsetters, + .tp_repr = (reprfunc)Country_repr, + .tp_str = (reprfunc)Country_str, + .tp_richcompare = (richcmpfunc)Country_richcompare, +}; diff --git a/src/python/country.h b/src/python/country.h new file mode 100644 index 0000000..3d787d9 --- /dev/null +++ b/src/python/country.h @@ -0,0 +1,34 @@ +/* + libloc - A library to determine the location of someone on the Internet + + Copyright (C) 2019 IPFire Development Team + + 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. +*/ + +#ifndef PYTHON_LOCATION_COUNTRY_H +#define PYTHON_LOCATION_COUNTRY_H + +#include + +//#include +#include + +typedef struct { + PyObject_HEAD + struct loc_country* country; +} CountryObject; + +extern PyTypeObject CountryType; + +PyObject* new_country(PyTypeObject* type, struct loc_country* country); + +#endif /* PYTHON_LOCATION_COUNTRY_H */ diff --git a/src/python/locationmodule.c b/src/python/locationmodule.c index 90620f7..3b20d67 100644 --- a/src/python/locationmodule.c +++ b/src/python/locationmodule.c @@ -19,6 +19,7 @@ #include "locationmodule.h" #include "as.h" +#include "country.h" #include "database.h" #include "network.h" #include "writer.h" @@ -81,6 +82,13 @@ PyMODINIT_FUNC PyInit_location(void) { Py_INCREF(&ASType); PyModule_AddObject(m, "AS", (PyObject *)&ASType); + // Country + if (PyType_Ready(&CountryType) < 0) + return NULL; + + Py_INCREF(&CountryType); + PyModule_AddObject(m, "Country", (PyObject *)&CountryType); + // Database if (PyType_Ready(&DatabaseType) < 0) return NULL; diff --git a/src/python/writer.c b/src/python/writer.c index 9e98003..ecb6882 100644 --- a/src/python/writer.c +++ b/src/python/writer.c @@ -21,6 +21,7 @@ #include "locationmodule.h" #include "as.h" +#include "country.h" #include "network.h" #include "writer.h" @@ -118,6 +119,32 @@ static PyObject* Writer_add_as(WriterObject* self, PyObject* args) { return obj; } +static PyObject* Writer_add_country(WriterObject* self, PyObject* args) { + struct loc_country* country; + const char* country_code; + + if (!PyArg_ParseTuple(args, "s", &country_code)) + return NULL; + + // Create country object + int r = loc_writer_add_country(self->writer, &country, country_code); + if (r) { + switch (r) { + case -EINVAL: + PyErr_SetString(PyExc_ValueError, "Invalid network"); + break; + + default: + return NULL; + } + } + + PyObject* obj = new_country(&CountryType, country); + loc_country_unref(country); + + return obj; +} + static PyObject* Writer_add_network(WriterObject* self, PyObject* args) { struct loc_network* network; const char* string = NULL; @@ -178,6 +205,12 @@ static struct PyMethodDef Writer_methods[] = { METH_VARARGS, NULL, }, + { + "add_country", + (PyCFunction)Writer_add_country, + METH_VARARGS, + NULL, + }, { "add_network", (PyCFunction)Writer_add_network,