From: Michael Tremer Date: Sat, 13 Feb 2021 16:34:31 +0000 (+0000) Subject: python: Add simply Parser module X-Git-Tag: 0.9.28~1285^2~728 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=40f17018b55ab89c77035402fd3b886d78915857;p=pakfire.git python: Add simply Parser module Signed-off-by: Michael Tremer --- diff --git a/Makefile.am b/Makefile.am index e5e6ebea1..0af8ae796 100644 --- a/Makefile.am +++ b/Makefile.am @@ -186,6 +186,8 @@ _pakfire_la_SOURCES = \ src/_pakfire/package.h \ src/_pakfire/pakfire.c \ src/_pakfire/pakfire.h \ + src/_pakfire/parser.c \ + src/_pakfire/parser.h \ src/_pakfire/problem.c \ src/_pakfire/problem.h \ src/_pakfire/relation.c \ @@ -625,6 +627,7 @@ TESTS_ENVIRONMENT = \ dist_check_SCRIPTS = \ tests/python/cgroups.py \ tests/python/execute.py \ + tests/python/parser.py \ tests/python/test.py TESTS = \ diff --git a/src/_pakfire/_pakfiremodule.c b/src/_pakfire/_pakfiremodule.c index 9d2c3b119..7357c52ed 100644 --- a/src/_pakfire/_pakfiremodule.c +++ b/src/_pakfire/_pakfiremodule.c @@ -37,6 +37,7 @@ #include "key.h" #include "package.h" #include "pakfire.h" +#include "parser.h" #include "problem.h" #include "relation.h" #include "repo.h" @@ -187,6 +188,13 @@ PyMODINIT_FUNC PyInit__pakfire(void) { Py_INCREF(&PackageType); PyModule_AddObject(module, "Package", (PyObject *)&PackageType); + // Parser + if (PyType_Ready(&ParserType) < 0) + return NULL; + + Py_INCREF(&ParserType); + PyModule_AddObject(module, "Parser", (PyObject *)&ParserType); + // Problem if (PyType_Ready(&ProblemType) < 0) return NULL; diff --git a/src/_pakfire/parser.c b/src/_pakfire/parser.c new file mode 100644 index 000000000..e022e98c1 --- /dev/null +++ b/src/_pakfire/parser.c @@ -0,0 +1,152 @@ +/*############################################################################# +# # +# Pakfire - The IPFire package management system # +# Copyright (C) 2021 Pakfire development team # +# # +# 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 3 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, see . # +# # +#############################################################################*/ + +#include + +#include + +#include "pakfire.h" +#include "parser.h" + +static ParserObject* Parser_new_core(PyTypeObject* type, PakfireParser parser) { + ParserObject* self = (ParserObject *)type->tp_alloc(type, 0); + if (self) { + self->parser = parser; + } + + return self; +} + +PyObject* new_parser(PakfireParser parser) { + ParserObject* p = Parser_new_core(&ParserType, parser); + + return (PyObject*)p; +} + +static PyObject* Parser_new(PyTypeObject* type, PyObject* args, PyObject* kwds) { + ParserObject* self = Parser_new_core(type, NULL); + + return (PyObject *)self; +} + +static void Parser_dealloc(ParserObject* self) { + pakfire_parser_unref(self->parser); + + Py_TYPE(self)->tp_free((PyObject *)self); +} + +static int Parser_init(ParserObject* self, PyObject* args, PyObject* kwds) { + PakfireObject* pakfire = NULL; + const char* namespace = NULL; + + if (!PyArg_ParseTuple(args, "O!|z", &PakfireType, &pakfire, &namespace)) + return -1; + + // Allocate a new parser + self->parser = pakfire_parser_create(pakfire->pakfire, NULL, namespace); + if (!self->parser) { + // What went wrong here? + return -1; + } + + return 0; +} + +static PyObject* Parser_repr(ParserObject* self) { + const char* namespace = pakfire_parser_get_namespace(self->parser); + + return PyUnicode_FromFormat("<_pakfire.Parser %s>", namespace); +} + +static PyObject* Parser_str(ParserObject* self) { + char* s = pakfire_parser_dump(self->parser); + if (!s) { + PyErr_SetFromErrno(PyExc_OSError); + return NULL; + } + + PyObject* ret = PyUnicode_FromString(s); + free(s); + + return ret; +} + +static PyObject* Parser_parse(ParserObject* self, PyObject* args) { + const char* data = NULL; + + if (!PyArg_ParseTuple(args, "s", &data)) + return NULL; + + int r = pakfire_parser_parse(self->parser, data, strlen(data)); + if (r) { + PyErr_SetFromErrno(PyExc_OSError); + return NULL; + } + + Py_RETURN_NONE; +} + +static PyObject* Parser_get(ParserObject* self, PyObject* args) { + const char* key = NULL; + + if (!PyArg_ParseTuple(args, "s", &key)) + return NULL; + + char* value = pakfire_parser_get(self->parser, key); + if (!value) { + PyErr_SetFromErrno(PyExc_OSError); + return NULL; + } + + PyObject* ret = PyUnicode_FromString(value); + free(value); + + return ret; +} + +static struct PyMethodDef Parser_methods[] = { + { + "parse", + (PyCFunction)Parser_parse, + METH_VARARGS, + NULL, + }, + { + "get", + (PyCFunction)Parser_get, + METH_VARARGS, + NULL, + }, + { NULL }, +}; + +PyTypeObject ParserType = { + PyVarObject_HEAD_INIT(NULL, 0) + tp_name: "_pakfire.Parser", + tp_basicsize: sizeof(ParserObject), + tp_flags: Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, + tp_new: Parser_new, + tp_dealloc: (destructor)Parser_dealloc, + tp_init: (initproc)Parser_init, + tp_doc: "Parser Object", + tp_methods: Parser_methods, + tp_repr: (reprfunc)Parser_repr, + tp_str: (reprfunc)Parser_str, +}; diff --git a/src/_pakfire/parser.h b/src/_pakfire/parser.h new file mode 100644 index 000000000..3636d12fd --- /dev/null +++ b/src/_pakfire/parser.h @@ -0,0 +1,37 @@ +/*############################################################################# +# # +# Pakfire - The IPFire package management system # +# Copyright (C) 2021 Pakfire development team # +# # +# 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 3 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, see . # +# # +#############################################################################*/ + +#ifndef PYTHON_PAKFIRE_PARSER_H +#define PYTHON_PAKFIRE_PARSER_H + +#include + +#include + +typedef struct { + PyObject_HEAD + PakfireParser parser; +} ParserObject; + +extern PyTypeObject ParserType; + +PyObject* new_parser(PakfireParser parser); + +#endif /* PYTHON_PAKFIRE_PARSER_H */ diff --git a/src/libpakfire/include/pakfire/parser.h b/src/libpakfire/include/pakfire/parser.h index ab0c1f68d..98e4ba81c 100644 --- a/src/libpakfire/include/pakfire/parser.h +++ b/src/libpakfire/include/pakfire/parser.h @@ -44,8 +44,11 @@ char* pakfire_parser_get(PakfireParser parser, const char* name); PakfireParser pakfire_parser_merge(PakfireParser parser1, PakfireParser parser2); int pakfire_parser_read(PakfireParser parser, FILE* f); +int pakfire_parser_parse(PakfireParser parser, const char* data, size_t size); char* pakfire_parser_dump(PakfireParser parser); +const char* pakfire_parser_get_namespace(PakfireParser parser); + #ifdef PAKFIRE_PRIVATE Pakfire pakfire_parser_get_pakfire(PakfireParser parser); diff --git a/src/libpakfire/libpakfire.sym b/src/libpakfire/libpakfire.sym index e69f8861c..695e25931 100644 --- a/src/libpakfire/libpakfire.sym +++ b/src/libpakfire/libpakfire.sym @@ -252,9 +252,10 @@ global: pakfire_parser_dump; pakfire_parser_expand; pakfire_parser_get; + pakfire_parser_get_namespace; pakfire_parser_get_parent; pakfire_parser_merge; - pakfire_parser_parse_data; + pakfire_parser_parse; pakfire_parser_read; pakfire_parser_ref; pakfire_parser_set; diff --git a/src/libpakfire/parser.c b/src/libpakfire/parser.c index 4d9eecffd..06a78e49e 100644 --- a/src/libpakfire/parser.c +++ b/src/libpakfire/parser.c @@ -462,6 +462,10 @@ PAKFIRE_EXPORT int pakfire_parser_read(PakfireParser parser, FILE* f) { return r; } +PAKFIRE_EXPORT int pakfire_parser_parse(PakfireParser parser, const char* data, size_t size) { + return pakfire_parser_parse_data(parser, data, size); +} + PAKFIRE_EXPORT char* pakfire_parser_dump(PakfireParser parser) { char* s = NULL; @@ -478,3 +482,7 @@ PAKFIRE_EXPORT char* pakfire_parser_dump(PakfireParser parser) { return s; } + +PAKFIRE_EXPORT const char* pakfire_parser_get_namespace(PakfireParser parser) { + return parser->namespace; +} diff --git a/tests/python/parser.py b/tests/python/parser.py new file mode 100755 index 000000000..51d42d5fc --- /dev/null +++ b/tests/python/parser.py @@ -0,0 +1,44 @@ +#!/usr/bin/python3 + +import pakfire +import unittest + +from pakfire._pakfire import Parser + +class Test(unittest.TestCase): + """ + This tests the parser command + """ + def setUp(self): + self.pakfire = pakfire.Pakfire("/") + + def test_simple_parse(self): + p = Parser(self.pakfire) + + # Parse something simple + p.parse(""" + a = 1 + b = 2 + """) + + # Read back a + a = p.get("a") + self.assertEqual(a, "1") + + # Read back b + b = p.get("b") + self.assertEqual(b, "2") + + def test_dump(self): + p = Parser(self.pakfire) + + # Parse something simple + p.parse(""" + a = 1 + b = 2 + """) + + dump = "%s" % p + +if __name__ == "__main__": + unittest.main()