]> git.ipfire.org Git - people/ms/libloc.git/commitdiff
python: Extend bindings for countries
authorMichael Tremer <michael.tremer@ipfire.org>
Tue, 15 Oct 2019 15:10:26 +0000 (15:10 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Tue, 15 Oct 2019 15:10:26 +0000 (15:10 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
Makefile.am
src/country.c
src/libloc.sym
src/python/country.c [new file with mode: 0644]
src/python/country.h [new file with mode: 0644]
src/python/locationmodule.c
src/python/writer.c

index afc58335988f58f9a17793948e52c254265f03ae..3dca0fee8207b7d006d487259ab4880f6bb08001 100644 (file)
@@ -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 \
index ca16c6db430bc1c43085eb3fd442268432e04ca9..22719c94fa3b10ffcb8b7b6c6b2084699431ad6e 100644 (file)
@@ -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);
 }
 
index 8ed931d60f4bc99ba65308198e9a7831ce649456..7cd7405c273f92ce800da0994d48c8db342b1b3f 100644 (file)
@@ -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 (file)
index 0000000..1247a08
--- /dev/null
@@ -0,0 +1,178 @@
+/*
+       libloc - A library to determine the location of someone on the Internet
+
+       Copyright (C) 2019 IPFire Development Team <info@ipfire.org>
+
+       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 <Python.h>
+
+#include <loc/libloc.h>
+#include <loc/country.h>
+
+#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("<Country %s (%s)>", code, name);
+
+       return PyUnicode_FromFormat("<Country %s>", 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 (file)
index 0000000..3d787d9
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+       libloc - A library to determine the location of someone on the Internet
+
+       Copyright (C) 2019 IPFire Development Team <info@ipfire.org>
+
+       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 <Python.h>
+
+//#include <loc/libloc.h>
+#include <loc/country.h>
+
+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 */
index 90620f7ddc5f05795404bb9acea65c26c67e1db6..3b20d670ee8e98f20ab9887038e06659713040cd 100644 (file)
@@ -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;
index 9e980035f93fdfeeaa9cb77310bc1e31af292f6f..ecb68826a3d0a869d3768ed3e4b7bc4f425cc03b 100644 (file)
@@ -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,