From: Michael Tremer Date: Fri, 15 Jul 2022 14:11:41 +0000 (+0000) Subject: file: Create Python wrapper for file objects X-Git-Tag: 0.9.28~712 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c2c834f4da820e9ad812336893d7edb6563cc7bc;p=pakfire.git file: Create Python wrapper for file objects Signed-off-by: Michael Tremer --- diff --git a/Makefile.am b/Makefile.am index 4025c77e5..d3c33dc80 100644 --- a/Makefile.am +++ b/Makefile.am @@ -146,6 +146,8 @@ _pakfire_la_SOURCES = \ src/_pakfire/archive.c \ src/_pakfire/archive.h \ src/_pakfire/errors.h \ + src/_pakfire/file.c \ + src/_pakfire/file.h \ src/_pakfire/key.c \ src/_pakfire/key.h \ src/_pakfire/package.c \ diff --git a/src/_pakfire/_pakfiremodule.c b/src/_pakfire/_pakfiremodule.c index b58a56307..cdbedc41e 100644 --- a/src/_pakfire/_pakfiremodule.c +++ b/src/_pakfire/_pakfiremodule.c @@ -25,6 +25,7 @@ #include "archive.h" #include "errors.h" +#include "file.h" #include "key.h" #include "package.h" #include "pakfire.h" @@ -98,6 +99,13 @@ PyMODINIT_FUNC PyInit__pakfire(void) { Py_INCREF(&ArchiveType); PyModule_AddObject(module, "Archive", (PyObject *)&ArchiveType); + // File + if (PyType_Ready(&FileType) < 0) + return NULL; + + Py_INCREF(&FileType); + PyModule_AddObject(module, "File", (PyObject *)&FileType); + // Key if (PyType_Ready(&KeyType) < 0) return NULL; diff --git a/src/_pakfire/file.c b/src/_pakfire/file.c new file mode 100644 index 000000000..72d69cd3e --- /dev/null +++ b/src/_pakfire/file.c @@ -0,0 +1,302 @@ +/*############################################################################# +# # +# Pakfire - The IPFire package management system # +# Copyright (C) 2022 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 + +#include "file.h" +#include "pakfire.h" + +PyObject* new_file(struct pakfire_file* file) { + PyTypeObject* type = &FileType; + + FileObject* self = (FileObject *)type->tp_alloc(type, 0); + if (self) { + if (file) + self->file = pakfire_file_ref(file); + else + self->file = NULL; + } + + return (PyObject *)self; +} + +static PyObject* File_new(PyTypeObject* type, PyObject* args, PyObject* kwds) { + return new_file(NULL); +} + +static void File_dealloc(FileObject* self) { + if (self->file) + pakfire_file_unref(self->file); + + Py_TYPE(self)->tp_free((PyObject *)self); +} + +static int File_init(FileObject* self, PyObject* args, PyObject* kwds) { + PakfireObject* pakfire = NULL; + + if (!PyArg_ParseTuple(args, "O!", &PakfireType, &pakfire)) + return -1; + + // Create a new File object + int r = pakfire_file_create(&self->file, pakfire->pakfire); + if (r) + return -1; + + return 0; +} + +static PyObject* File_repr(FileObject* self) { + const char* path = pakfire_file_get_path(self->file); + + return PyUnicode_FromFormat("<_pakfire.Problem %s>", path); +} + +static PyObject* File_get_path(FileObject* self) { + const char* path = pakfire_file_get_path(self->file); + + return PyUnicode_FromString(path); +} + +static int File_set_path(FileObject* self, PyObject* value) { + const char* path = PyUnicode_AsUTF8(value); + if (!path) + return -1; + + pakfire_file_set_path(self->file, path); + return 0; +} + +static PyObject* File_get_size(FileObject* self) { + const size_t size = pakfire_file_get_size(self->file); + + return PyLong_FromSize_t(size); +} + +static int File_set_size(FileObject* self, PyObject* value) { + long size = PyLong_AsLong(value); + if (size < 0) + return -1; + + pakfire_file_set_size(self->file, size); + return 0; +} + +static PyObject* File_get_type(FileObject* self) { + int type = pakfire_file_get_type(self->file); + + return PyLong_FromLong(type); +} + +static PyObject* File_get_user(FileObject* self) { + const char* user = pakfire_file_get_user(self->file); + + return PyUnicode_FromString(user); +} + +static int File_set_user(FileObject* self, PyObject* value) { + const char* user = PyUnicode_AsUTF8(value); + if (!user) + return -1; + + pakfire_file_set_user(self->file, user); + return 0; +} + +static PyObject* File_get_group(FileObject* self) { + const char* group = pakfire_file_get_group(self->file); + + return PyUnicode_FromString(group); +} + +static int File_set_group(FileObject* self, PyObject* value) { + const char* group = PyUnicode_AsUTF8(value); + if (!group) + return -1; + + pakfire_file_set_group(self->file, group); + return 0; +} + +static PyObject* File_get_mode(FileObject* self) { + const mode_t mode = pakfire_file_get_mode(self->file); + + return PyLong_FromLong(mode); +} + +static int File_set_mode(FileObject* self, PyObject* value) { + const mode_t mode = PyLong_AsLong(value); + + pakfire_file_set_mode(self->file, mode); + return 0; +} + +static PyObject* PyDateTime_FromTime_t(const time_t* t) { + struct tm buffer; + + struct tm* tm = gmtime_r(t, &buffer); + if (!tm) + return NULL; + + PyDateTime_IMPORT; + + return PyDateTime_FromDateAndTime( + 1900 + tm->tm_year, + 1 + tm->tm_mon, + tm->tm_mday, + tm->tm_hour, + tm->tm_min, + tm->tm_sec, + 0 + ); +} + +static time_t PyDateTime_AsTime_t(PyObject* value) { + if (!PyDateTime_Check(value)) + return -1; + + PyDateTime_IMPORT; + + // Convert from datetime to struct tm + struct tm tm = { + .tm_year = PyDateTime_GET_YEAR(value) - 1900, + .tm_mon = PyDateTime_GET_MONTH(value) - 1, + .tm_mday = PyDateTime_GET_DAY(value), + .tm_hour = PyDateTime_DATE_GET_HOUR(value), + .tm_min = PyDateTime_DATE_GET_MINUTE(value), + .tm_sec = PyDateTime_DATE_GET_SECOND(value), + .tm_isdst = 0, + }; + + // Convert into time_t + const time_t t = mktime(&tm); + if (t < 0) { + PyErr_SetFromErrno(PyExc_OSError); + return -1; + } + + return t; +} + +static PyObject* File_get_ctime(FileObject* self) { + const time_t t = pakfire_file_get_ctime(self->file); + + return PyDateTime_FromTime_t(&t); +} + +static int File_set_ctime(FileObject* self, PyObject* value) { + const time_t t = PyDateTime_AsTime_t(value); + if (t < 0) + return -1; + + pakfire_file_set_ctime(self->file, t); + return 0; +} + +static PyObject* File_get_mtime(FileObject* self) { + const time_t t = pakfire_file_get_mtime(self->file); + + return PyDateTime_FromTime_t(&t); +} + +static int File_set_mtime(FileObject* self, PyObject* value) { + const time_t t = PyDateTime_AsTime_t(value); + if (t < 0) + return -1; + + pakfire_file_set_mtime(self->file, t); + return 0; +} + +static struct PyGetSetDef File_getsetters[] = { + { + "ctime", + (getter)File_get_ctime, + (setter)File_set_ctime, + NULL, + NULL, + }, + { + "group", + (getter)File_get_group, + (setter)File_set_group, + NULL, + NULL, + }, + { + "mode", + (getter)File_get_mode, + (setter)File_set_mode, + NULL, + NULL, + }, + { + "mtime", + (getter)File_get_mtime, + (setter)File_set_mtime, + NULL, + NULL, + }, + { + "path", + (getter)File_get_path, + (setter)File_set_path, + NULL, + NULL, + }, + { + "size", + (getter)File_get_size, + (setter)File_set_size, + NULL, + NULL, + }, + { + "type", + (getter)File_get_type, + NULL, + NULL, + NULL, + }, + { + "user", + (getter)File_get_user, + (setter)File_set_user, + NULL, + NULL, + }, + { NULL }, +}; + +PyTypeObject FileType = { + PyVarObject_HEAD_INIT(NULL, 0) + tp_name: "_pakfire.File", + tp_basicsize: sizeof(FileObject), + tp_flags: Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, + tp_new: File_new, + tp_dealloc: (destructor)File_dealloc, + tp_init: (initproc)File_init, + tp_doc: "File object", + tp_getset: File_getsetters, + tp_repr: (reprfunc)File_repr, + tp_str: (reprfunc)File_get_path, +}; diff --git a/src/_pakfire/file.h b/src/_pakfire/file.h new file mode 100644 index 000000000..3ce22aeb2 --- /dev/null +++ b/src/_pakfire/file.h @@ -0,0 +1,37 @@ +/*############################################################################# +# # +# Pakfire - The IPFire package management system # +# Copyright (C) 2022 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_FILE_H +#define PYTHON_PAKFIRE_FILE_H + +#include + +#include + +typedef struct { + PyObject_HEAD + struct pakfire_file* file; +} FileObject; + +extern PyTypeObject FileType; + +PyObject* new_file(struct pakfire_file* file); + +#endif /* PYTHON_PAKFIRE_FILE_H */