Needed for #86.
Signed-off-by: Martin Milata mmilata@redhat.com --- python/Makefile.am | 2 + python/py_module.c | 10 +++ python/py_operating_system.c | 167 +++++++++++++++++++++++++++++++++++++++++++ python/py_operating_system.h | 63 ++++++++++++++++ tests/python/report.py | 23 ++++++ tests/python_bindings.at | 1 + 6 files changed, 266 insertions(+) create mode 100644 python/py_operating_system.c create mode 100644 python/py_operating_system.h create mode 100755 tests/python/report.py
diff --git a/python/Makefile.am b/python/Makefile.am index 95a81c0..fab2c13 100644 --- a/python/Makefile.am +++ b/python/Makefile.am @@ -44,6 +44,8 @@ _satyr_la_SOURCES = \ py_java_stacktrace.c \ py_metrics.h \ py_metrics.c \ + py_operating_system.h \ + py_operating_system.c \ py_common.h \ py_common.c \ py_module.c diff --git a/python/py_module.c b/python/py_module.c index 23c8882..763ffaf 100644 --- a/python/py_module.c +++ b/python/py_module.c @@ -18,6 +18,7 @@ #include "py_core_thread.h" #include "py_core_stacktrace.h" #include "py_metrics.h" +#include "py_operating_system.h"
#include "distance.h" #include "thread.h" @@ -157,6 +158,12 @@ init_satyr() return; }
+ if (PyType_Ready(&sr_py_operating_system_type) < 0) + { + puts("PyType_Ready(&sr_py_operating_system_type) < 0"); + return; + } +
PyObject *module = Py_InitModule("_satyr", module_methods); if (!module) @@ -264,4 +271,7 @@ init_satyr() PyModule_AddObject(module, "CoreStacktrace", (PyObject *)&sr_py_core_stacktrace_type);
+ Py_INCREF(&sr_py_operating_system_type); + PyModule_AddObject(module, "OperatingSystem", + (PyObject *)&sr_py_operating_system_type); } diff --git a/python/py_operating_system.c b/python/py_operating_system.c new file mode 100644 index 0000000..0974d7a --- /dev/null +++ b/python/py_operating_system.c @@ -0,0 +1,167 @@ +/* + py_operating_system.c + + Copyright (C) 2013 Red Hat, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include "py_common.h" +#include "py_operating_system.h" + +#include "operating_system.h" +#include "strbuf.h" + +#define operating_system_doc "satyr.OperatingSystem - describes an operating system\n" \ + "Usage:\n" \ + "satyr.OperatingSystem() - creates an empty operating system object\n" \ + "satyr.OperatingSystem(name, version, arch) - creates an operating system\n" \ + "object with given properties (all arguments are strings or None)" + +/* See python/py_common.h and python/py_gdb_frame.c for generic getters/setters documentation. */ +#define GSOFF_PY_STRUCT sr_py_operating_system +#define GSOFF_PY_MEMBER operating_system +#define GSOFF_C_STRUCT sr_operating_system +GSOFF_START +GSOFF_MEMBER(name), +GSOFF_MEMBER(version), +GSOFF_MEMBER(architecture), +GSOFF_MEMBER(cpe), +GSOFF_MEMBER(uptime) +GSOFF_END + +static PyGetSetDef +operating_system_getset[] = +{ + SR_ATTRIBUTE_STRING(name, "Operating system name (string)" ), + SR_ATTRIBUTE_STRING(version, "Version (string)" ), + SR_ATTRIBUTE_STRING(architecture, "Architecture (string)" ), + SR_ATTRIBUTE_STRING(cpe, "Common platform enumeration identifier (string)" ), + SR_ATTRIBUTE_UINT64(uptime, "Machine uptime (long)" ), + { NULL }, +}; + +PyTypeObject +sr_py_operating_system_type = +{ + PyObject_HEAD_INIT(NULL) + 0, + "satyr.OperatingSystem", /* tp_name */ + sizeof(struct sr_py_operating_system), /* tp_basicsize */ + 0, /* tp_itemsize */ + sr_py_operating_system_free,/* tp_dealloc */ + NULL, /* tp_print */ + NULL, /* tp_getattr */ + NULL, /* tp_setattr */ + NULL, /* tp_compare */ + NULL, /* tp_repr */ + NULL, /* tp_as_number */ + NULL, /* tp_as_sequence */ + NULL, /* tp_as_mapping */ + NULL, /* tp_hash */ + NULL, /* tp_call */ + sr_py_operating_system_str, /* tp_str */ + NULL, /* tp_getattro */ + NULL, /* tp_setattro */ + NULL, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT, /* tp_flags */ + operating_system_doc, /* tp_doc */ + NULL, /* tp_traverse */ + NULL, /* tp_clear */ + NULL, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + NULL, /* tp_iter */ + NULL, /* tp_iternext */ + NULL, /* tp_methods */ + NULL, /* tp_members */ + operating_system_getset, /* tp_getset */ + NULL, /* tp_base */ + NULL, /* tp_dict */ + NULL, /* tp_descr_get */ + NULL, /* tp_descr_set */ + 0, /* tp_dictoffset */ + NULL, /* tp_init */ + NULL, /* tp_alloc */ + sr_py_operating_system_new, /* tp_new */ + NULL, /* tp_free */ + NULL, /* tp_is_gc */ + NULL, /* tp_bases */ + NULL, /* tp_mro */ + NULL, /* tp_cache */ + NULL, /* tp_subclasses */ + NULL, /* tp_weaklist */ +}; + +/* constructor */ +PyObject * +sr_py_operating_system_new(PyTypeObject *object, PyObject *args, PyObject *kwds) +{ + struct sr_py_operating_system *os = + PyObject_New(struct sr_py_operating_system, &sr_py_operating_system_type); + + if (!os) + return PyErr_NoMemory(); + + os->operating_system = sr_operating_system_new(); + + const char *name = NULL, *version = NULL, *arch = NULL; + if (!PyArg_ParseTuple(args, "|sss", &name, &version, &arch)) + return NULL; + + if (name) + os->operating_system->name = sr_strdup(name); + + if (version) + os->operating_system->version = sr_strdup(version); + + if (arch) + os->operating_system->architecture = sr_strdup(arch); + + return (PyObject*)os; +} + +/* destructor */ +void +sr_py_operating_system_free(PyObject *object) +{ + struct sr_py_operating_system *this = (struct sr_py_operating_system *)object; + sr_operating_system_free(this->operating_system); + PyObject_Del(object); +} + +/* str */ +PyObject * +sr_py_operating_system_str(PyObject *object) +{ + struct sr_py_operating_system *this = (struct sr_py_operating_system*)object; + struct sr_strbuf *buf = sr_strbuf_new(); + + sr_strbuf_append_str(buf, + this->operating_system->name ? this->operating_system->name : "(unknown)"); + + if (this->operating_system->version) + sr_strbuf_append_strf(buf, " %s", this->operating_system->version); + + if (this->operating_system->architecture) + sr_strbuf_append_strf(buf, " (%s)", this->operating_system->architecture); + + if (this->operating_system->cpe) + sr_strbuf_append_strf(buf, ", CPE: %s", this->operating_system->cpe); + + char *str = sr_strbuf_free_nobuf(buf); + PyObject *result = Py_BuildValue("s", str); + free(str); + return result; +} diff --git a/python/py_operating_system.h b/python/py_operating_system.h new file mode 100644 index 0000000..bcd8e7f --- /dev/null +++ b/python/py_operating_system.h @@ -0,0 +1,63 @@ +/* + py_operating_system.h + + Copyright (C) 2013 Red Hat, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ +#ifndef SATYR_PY_OPERATING_SYSTEM_H +#define SATYR_PY_OPERATING_SYSTEM_H + +/** + * @file + * @brief Python bindings for operating system. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <Python.h> +#include <structmember.h> + +PyTypeObject sr_py_operating_system_type; + +struct sr_py_operating_system +{ + PyObject_HEAD + struct sr_operating_system *operating_system; +}; + +/** + * Constructor. + */ +PyObject *sr_py_operating_system_new(PyTypeObject *object, + PyObject *args, PyObject *kwds); + +/** + * Destructor. + */ +void sr_py_operating_system_free(PyObject *object); + +/** + * str + */ +PyObject *sr_py_operating_system_str(PyObject *self); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/tests/python/report.py b/tests/python/report.py new file mode 100755 index 0000000..7580fb5 --- /dev/null +++ b/tests/python/report.py @@ -0,0 +1,23 @@ +#!/usr/bin/env python + +import unittest +from test_helpers import * + +class TestOperatingSystem(BindingsTestCase): + def setUp(self): + self.opsys = satyr.OperatingSystem('fedora', '19', 'x86_64') + + def test_str(self): + self.assertEqual(str(self.opsys), 'fedora 19 (x86_64)') + + def test_getset(self): + self.assertGetSetCorrect(self.opsys, 'name', 'fedora', 'debian') + self.assertGetSetCorrect(self.opsys, 'version', '19', 'XP') + self.assertGetSetCorrect(self.opsys, 'architecture', 'x86_64', 's390x') + self.assertGetSetCorrect(self.opsys, 'uptime', 0, 9000) + self.assertGetSetCorrect(self.opsys, 'cpe', None, 'cpe:/o:fedoraproject:fedora:19') + + +if __name__ == '__main__': + unittest.main() + diff --git a/tests/python_bindings.at b/tests/python_bindings.at index a7ab98d..1433864 100644 --- a/tests/python_bindings.at +++ b/tests/python_bindings.at @@ -12,3 +12,4 @@ AT_TEST_PYTHON([python]) AT_TEST_PYTHON([java]) AT_TEST_PYTHON([core]) AT_TEST_PYTHON([metrics]) +AT_TEST_PYTHON([report])