diff --git a/SOURCES/0004-Add-new-functions-to-extend-exception-handling.patch b/SOURCES/0004-Add-new-functions-to-extend-exception-handling.patch new file mode 100644 index 0000000..7659516 --- /dev/null +++ b/SOURCES/0004-Add-new-functions-to-extend-exception-handling.patch @@ -0,0 +1,222 @@ +From e701c277cdb07d849a9f7b67aabfc4ff391f8970 Mon Sep 17 00:00:00 2001 +From: Chris Lumens +Date: Tue, 13 Jan 2015 11:13:17 -0500 +Subject: [PATCH 4/7] Add new functions to extend exception handling. + +We've been avoiding this for an awful long time, but there is now a need for +users of pyparted to be able to specify what answers should be given to parted +exceptions that ask a question. Specifically, we need to be able to ask the +user whether to proceed with a disk containing a corrupted GPT disk label or not. + +This adds a function to register a callback that can prompt the user (among other +possible actions) and a function to clear this callback to restore default +behavior. +--- + src/_pedmodule.c | 135 ++++++++++++++++++++++++++++++++++++++++++++++++++----- + 1 file changed, 125 insertions(+), 10 deletions(-) + +diff --git a/src/_pedmodule.c b/src/_pedmodule.c +index a1c8947..7f02193 100644 +--- a/src/_pedmodule.c ++++ b/src/_pedmodule.c +@@ -5,7 +5,7 @@ + * Python module that implements the libparted functionality via Python + * classes and other high level language features. + * +- * Copyright (C) 2007, 2008 Red Hat, Inc. ++ * Copyright (C) 2007-2015 Red Hat, Inc. + * + * This copyrighted material is made available to anyone wishing to use, + * modify, copy, or redistribute it subject to the terms and conditions of +@@ -44,6 +44,8 @@ + char *partedExnMessage = NULL; + unsigned int partedExnRaised = 0; + ++PyObject *exn_handler = NULL; ++ + /* Docs strings are broken out of the module structure here to be at least a + * little bit readable. + */ +@@ -190,6 +192,25 @@ PyDoc_STRVAR(unit_get_by_name_doc, + "Returns a Unit given its textual representation. Returns one of the\n" + "UNIT_* constants."); + ++PyDoc_STRVAR(register_exn_handler_doc, ++"register_exn_handler(function)\n\n" ++"When parted raises an exception, the function registered here will be called\n" ++"to help determine what action to take. This does not bypass the exception\n" ++"handler pyparted uses. Instead, it can be used to pop up a dialog to ask the\n" ++"user which course of action to take, or to provide a different default answer,\n" ++"or other actions.\n\n" ++"The given function must accept as arguments: (1) an integer corresponding to\n" ++"one of the EXCEPTION_TYPE_* constants; (2) an integer corresponding to one of the\n" ++"EXCEPTION_OPT_* constants; and (3) a string that is the problem encountered by\n" ++"parted. This string will already be translated. The given function must return\n" ++"one of the EXCEPTION_RESOLVE_* constants instructing parted how to proceed."); ++ ++PyDoc_STRVAR(clear_exn_handler_doc, ++"clear_exn_handler()\n\n" ++"Clear any previously added exception handling function. This means the\n" ++"default behavior for all parted exceptions will be used, so only safe\n" ++"answers to any questions parted asks will be automatically provided."); ++ + PyDoc_STRVAR(_ped_doc, + "This module implements an interface to libparted.\n\n" + "pyparted provides two API layers: a lower level that exposes the complete\n" +@@ -204,6 +225,25 @@ PyDoc_STRVAR(_ped_doc, + "For complete documentation, refer to the docs strings for each _ped\n" + "method, exception class, and subclass."); + ++PyObject *py_ped_register_exn_handler(PyObject *s, PyObject *args) { ++ PyObject *fn = NULL; ++ ++ if (!PyArg_ParseTuple(args, "O", &fn)) { ++ return NULL; ++ } ++ ++ Py_DECREF(exn_handler); ++ exn_handler = fn; ++ ++ Py_RETURN_TRUE; ++} ++ ++PyObject *py_ped_clear_exn_handler(PyObject *s, PyObject *args) { ++ exn_handler = Py_None; ++ Py_INCREF(exn_handler); ++ Py_RETURN_TRUE; ++} ++ + /* all of the methods for the _ped module */ + static struct PyMethodDef PyPedModuleMethods[] = { + {"libparted_version", (PyCFunction) py_libparted_get_version, METH_VARARGS, +@@ -211,6 +251,11 @@ static struct PyMethodDef PyPedModuleMethods[] = { + {"pyparted_version", (PyCFunction) py_pyparted_version, METH_VARARGS, + pyparted_version_doc}, + ++ {"register_exn_handler", (PyCFunction) py_ped_register_exn_handler, METH_VARARGS, ++ register_exn_handler_doc}, ++ {"clear_exn_handler", (PyCFunction) py_ped_clear_exn_handler, METH_VARARGS, ++ clear_exn_handler_doc}, ++ + /* pyconstraint.c */ + {"constraint_new_from_min_max", (PyCFunction) py_ped_constraint_new_from_min_max, + METH_VARARGS, constraint_new_from_min_max_doc}, +@@ -337,6 +382,10 @@ PyObject *py_pyparted_version(PyObject *s, PyObject *args) { + * main motivation for this function is that methods in our parted module need + * to be able to raise specific, helpful exceptions instead of something + * generic. ++ * ++ * It is also possible for callers to specify a function to help in deciding ++ * what to do with parted exceptions. See the docs for the ++ * py_ped_register_exn_handler function. + */ + static PedExceptionOption partedExnHandler(PedException *e) { + switch (e->type) { +@@ -350,13 +399,29 @@ static PedExceptionOption partedExnHandler(PedException *e) { + + if (partedExnMessage == NULL) + PyErr_NoMemory(); +- +- /* +- * return 'no' for yes/no question exceptions in libparted, +- * prevent any potential disk destruction and pass up an +- * exception to our caller +- */ +- return PED_EXCEPTION_NO; ++ else if (exn_handler && PyCallable_Check(exn_handler)) { ++ PyObject *args, *retval; ++ ++ args = PyTuple_New(3); ++ PyTuple_SetItem(args, 0, PyInt_FromLong(e->type)); ++ PyTuple_SetItem(args, 1, PyInt_FromLong(e->options)); ++ PyTuple_SetItem(args, 2, PyUnicode_FromString(e->message)); ++ ++ retval = PyObject_CallObject(exn_handler, NULL); ++ Py_DECREF(args); ++ if (retval != NULL && (PyLong_AsLong(retval) == PED_EXCEPTION_UNHANDLED || (PyLong_AsLong(retval) & e->options) > 0)) ++ return PyLong_AsLong(retval); ++ else ++ /* Call failed, use the default value. */ ++ return PED_EXCEPTION_NO; ++ } ++ else { ++ /* If no exception handling function was registered to ++ * tell us what to do, return "no" for any yes/no ++ * questions to prevent any potential disk destruction. ++ */ ++ return PED_EXCEPTION_NO; ++ } + } else { + partedExnRaised = 0; + return PED_EXCEPTION_IGNORE; +@@ -372,8 +437,29 @@ static PedExceptionOption partedExnHandler(PedException *e) { + + if (partedExnMessage == NULL) + PyErr_NoMemory(); +- +- return PED_EXCEPTION_CANCEL; ++ else if (exn_handler && PyCallable_Check(exn_handler)) { ++ PyObject *args, *retval; ++ ++ args = PyTuple_New(3); ++ PyTuple_SetItem(args, 0, PyInt_FromLong(e->type)); ++ PyTuple_SetItem(args, 1, PyInt_FromLong(e->options)); ++ PyTuple_SetItem(args, 2, PyUnicode_FromString(e->message)); ++ ++ retval = PyObject_CallObject(exn_handler, NULL); ++ Py_DECREF(args); ++ if (retval != NULL && (PyLong_AsLong(retval) == PED_EXCEPTION_UNHANDLED || (PyLong_AsLong(retval) & e->options) > 0)) ++ return PyLong_AsLong(retval); ++ else ++ /* Call failed, use the default value. */ ++ return PED_EXCEPTION_CANCEL; ++ } ++ else { ++ /* If no exception handling function was registered to tell us ++ * what to do, return "cancel" for any questions to prevent ++ * any potential disk destruction. ++ */ ++ return PED_EXCEPTION_CANCEL; ++ } + + /* Raise exceptions for internal parted bugs immediately. */ + case PED_EXCEPTION_BUG: +@@ -607,6 +693,35 @@ PyMODINIT_FUNC init_ped(void) { + Py_INCREF(UnknownTypeException); + PyModule_AddObject(m, "UnknownTypeException", UnknownTypeException); + ++ /* Exception type constants. */ ++ PyModule_AddIntConstant(m, "EXCEPTION_TYPE_INFORMATION", PED_EXCEPTION_INFORMATION); ++ PyModule_AddIntConstant(m, "EXCEPTION_TYPE_WARNING", PED_EXCEPTION_WARNING); ++ PyModule_AddIntConstant(m, "EXCEPTION_TYPE_ERROR", PED_EXCEPTION_ERROR); ++ PyModule_AddIntConstant(m, "EXCEPTION_TYPE_FATAL", PED_EXCEPTION_FATAL); ++ PyModule_AddIntConstant(m, "EXCEPTION_TYPE_BUG", PED_EXCEPTION_BUG); ++ PyModule_AddIntConstant(m, "EXCEPTION_TYPE_NO_FEATURE", PED_EXCEPTION_NO_FEATURE); ++ ++ /* Exception resolution constants. */ ++ PyModule_AddIntConstant(m, "EXCEPTION_RESOLVE_UNHANDLED", PED_EXCEPTION_UNHANDLED); ++ PyModule_AddIntConstant(m, "EXCEPTION_RESOLVE_FIX", PED_EXCEPTION_FIX); ++ PyModule_AddIntConstant(m, "EXCEPTION_RESOLVE_YES", PED_EXCEPTION_YES); ++ PyModule_AddIntConstant(m, "EXCEPTION_RESOLVE_NO", PED_EXCEPTION_NO); ++ PyModule_AddIntConstant(m, "EXCEPTION_RESOLVE_OK", PED_EXCEPTION_OK); ++ PyModule_AddIntConstant(m, "EXCEPTION_RESOLVE_RETRY", PED_EXCEPTION_RETRY); ++ PyModule_AddIntConstant(m, "EXCEPTION_RESOLVE_IGNORE", PED_EXCEPTION_IGNORE); ++ PyModule_AddIntConstant(m, "EXCEPTION_RESOLVE_CANCEL", PED_EXCEPTION_CANCEL); ++ ++ /* Exception option constants. */ ++ PyModule_AddIntConstant(m, "EXCEPTION_OPT_OK_CANCEL", PED_EXCEPTION_OK_CANCEL); ++ PyModule_AddIntConstant(m, "EXCEPTION_OPT_YES_NO", PED_EXCEPTION_YES_NO); ++ PyModule_AddIntConstant(m, "EXCEPTION_OPT_YES_NO_CANCEL", PED_EXCEPTION_YES_NO_CANCEL); ++ PyModule_AddIntConstant(m, "EXCEPTION_OPT_IGNORE_CANCEL", PED_EXCEPTION_IGNORE_CANCEL); ++ PyModule_AddIntConstant(m, "EXCEPTION_OPT_RETRY_CANCEL", PED_EXCEPTION_RETRY_CANCEL); ++ PyModule_AddIntConstant(m, "EXCEPTION_OPT_RETRY_IGNORE_CANCEL", PED_EXCEPTION_RETRY_IGNORE_CANCEL); ++ ++ exn_handler = Py_None; ++ Py_INCREF(exn_handler); ++ + /* Set up our libparted exception handler. */ + ped_exception_set_handler(partedExnHandler); + } +-- +2.4.0 + diff --git a/SOURCES/0005-PyInt_FromLong-doesn-t-exist-in-python3-so-always-us.patch b/SOURCES/0005-PyInt_FromLong-doesn-t-exist-in-python3-so-always-us.patch new file mode 100644 index 0000000..f282c47 --- /dev/null +++ b/SOURCES/0005-PyInt_FromLong-doesn-t-exist-in-python3-so-always-us.patch @@ -0,0 +1,39 @@ +From 273377f924599a4d7358770664467a22a81249ef Mon Sep 17 00:00:00 2001 +From: Chris Lumens +Date: Wed, 14 Jan 2015 11:40:42 -0500 +Subject: [PATCH 5/7] PyInt_FromLong doesn't exist in python3, so always use + PyLong_FromLong. + +--- + src/_pedmodule.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/src/_pedmodule.c b/src/_pedmodule.c +index 7f02193..a048d91 100644 +--- a/src/_pedmodule.c ++++ b/src/_pedmodule.c +@@ -403,8 +403,8 @@ static PedExceptionOption partedExnHandler(PedException *e) { + PyObject *args, *retval; + + args = PyTuple_New(3); +- PyTuple_SetItem(args, 0, PyInt_FromLong(e->type)); +- PyTuple_SetItem(args, 1, PyInt_FromLong(e->options)); ++ PyTuple_SetItem(args, 0, PyLong_FromLong(e->type)); ++ PyTuple_SetItem(args, 1, PyLong_FromLong(e->options)); + PyTuple_SetItem(args, 2, PyUnicode_FromString(e->message)); + + retval = PyObject_CallObject(exn_handler, NULL); +@@ -441,8 +441,8 @@ static PedExceptionOption partedExnHandler(PedException *e) { + PyObject *args, *retval; + + args = PyTuple_New(3); +- PyTuple_SetItem(args, 0, PyInt_FromLong(e->type)); +- PyTuple_SetItem(args, 1, PyInt_FromLong(e->options)); ++ PyTuple_SetItem(args, 0, PyLong_FromLong(e->type)); ++ PyTuple_SetItem(args, 1, PyLong_FromLong(e->options)); + PyTuple_SetItem(args, 2, PyUnicode_FromString(e->message)); + + retval = PyObject_CallObject(exn_handler, NULL); +-- +2.4.0 + diff --git a/SOURCES/0006-Remember-to-pass-the-arguments-to-the-exception-hand.patch b/SOURCES/0006-Remember-to-pass-the-arguments-to-the-exception-hand.patch new file mode 100644 index 0000000..f2242e1 --- /dev/null +++ b/SOURCES/0006-Remember-to-pass-the-arguments-to-the-exception-hand.patch @@ -0,0 +1,34 @@ +From 603534d12ed52405e9f464f9608fea725583a51e Mon Sep 17 00:00:00 2001 +From: Chris Lumens +Date: Wed, 14 Jan 2015 14:56:34 -0500 +Subject: [PATCH 6/7] Remember to pass the arguments to the exception handler. + +--- + src/_pedmodule.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/_pedmodule.c b/src/_pedmodule.c +index a048d91..cfe2dd8 100644 +--- a/src/_pedmodule.c ++++ b/src/_pedmodule.c +@@ -407,7 +407,7 @@ static PedExceptionOption partedExnHandler(PedException *e) { + PyTuple_SetItem(args, 1, PyLong_FromLong(e->options)); + PyTuple_SetItem(args, 2, PyUnicode_FromString(e->message)); + +- retval = PyObject_CallObject(exn_handler, NULL); ++ retval = PyObject_CallObject(exn_handler, args); + Py_DECREF(args); + if (retval != NULL && (PyLong_AsLong(retval) == PED_EXCEPTION_UNHANDLED || (PyLong_AsLong(retval) & e->options) > 0)) + return PyLong_AsLong(retval); +@@ -445,7 +445,7 @@ static PedExceptionOption partedExnHandler(PedException *e) { + PyTuple_SetItem(args, 1, PyLong_FromLong(e->options)); + PyTuple_SetItem(args, 2, PyUnicode_FromString(e->message)); + +- retval = PyObject_CallObject(exn_handler, NULL); ++ retval = PyObject_CallObject(exn_handler, args); + Py_DECREF(args); + if (retval != NULL && (PyLong_AsLong(retval) == PED_EXCEPTION_UNHANDLED || (PyLong_AsLong(retval) & e->options) > 0)) + return PyLong_AsLong(retval); +-- +2.4.0 + diff --git a/SOURCES/0007-Put-new-_ped-constants-and-functions-into-the-parted.patch b/SOURCES/0007-Put-new-_ped-constants-and-functions-into-the-parted.patch new file mode 100644 index 0000000..aa0b6a5 --- /dev/null +++ b/SOURCES/0007-Put-new-_ped-constants-and-functions-into-the-parted.patch @@ -0,0 +1,68 @@ +From 13bad0da9efbd38ca288e7f28f9512649473f6ce Mon Sep 17 00:00:00 2001 +From: Chris Lumens +Date: Wed, 14 Jan 2015 11:55:45 -0500 +Subject: [PATCH 7/7] Put new _ped constants and functions into the parted + module. + +We don't want to require users of pyparted to have to dig down into the +lower level bindings to get at these things. +--- + src/parted/__init__.py | 28 +++++++++++++++++++++++++++- + 1 file changed, 27 insertions(+), 1 deletion(-) + +diff --git a/src/parted/__init__.py b/src/parted/__init__.py +index c8f6830..2d9ea32 100644 +--- a/src/parted/__init__.py ++++ b/src/parted/__init__.py +@@ -2,7 +2,7 @@ + # __init__.py + # Python bindings for libparted (built on top of the _ped Python module). + # +-# Copyright (C) 2007, 2008, 2009 Red Hat, Inc. ++# Copyright (C) 2007-2015 Red Hat, Inc. + # + # This copyrighted material is made available to anyone wishing to use, + # modify, copy, or redistribute it subject to the terms and conditions of +@@ -48,6 +48,9 @@ from _ped import TimerException + from _ped import UnknownDeviceException + from _ped import UnknownTypeException + ++from _ped import register_exn_handler ++from _ped import clear_exn_handler ++ + from alignment import Alignment + from constraint import Constraint + from device import Device +@@ -122,6 +125,29 @@ from _ped import DISK_GPT_PMBR_BOOT + from _ped import DISK_TYPE_EXTENDED + from _ped import DISK_TYPE_PARTITION_NAME + ++from _ped import EXCEPTION_TYPE_INFORMATION ++from _ped import EXCEPTION_TYPE_WARNING ++from _ped import EXCEPTION_TYPE_ERROR ++from _ped import EXCEPTION_TYPE_FATAL ++from _ped import EXCEPTION_TYPE_BUG ++from _ped import EXCEPTION_TYPE_NO_FEATURE ++ ++from _ped import EXCEPTION_RESOLVE_UNHANDLED ++from _ped import EXCEPTION_RESOLVE_FIX ++from _ped import EXCEPTION_RESOLVE_YES ++from _ped import EXCEPTION_RESOLVE_NO ++from _ped import EXCEPTION_RESOLVE_OK ++from _ped import EXCEPTION_RESOLVE_RETRY ++from _ped import EXCEPTION_RESOLVE_IGNORE ++from _ped import EXCEPTION_RESOLVE_CANCEL ++ ++from _ped import EXCEPTION_OPT_OK_CANCEL ++from _ped import EXCEPTION_OPT_YES_NO ++from _ped import EXCEPTION_OPT_YES_NO_CANCEL ++from _ped import EXCEPTION_OPT_IGNORE_CANCEL ++from _ped import EXCEPTION_OPT_RETRY_CANCEL ++from _ped import EXCEPTION_OPT_RETRY_IGNORE_CANCEL ++ + from decorators import localeC + + partitionTypesDict = { +-- +2.4.0 + diff --git a/SPECS/pyparted.spec b/SPECS/pyparted.spec index dbe24e1..2b6a7a7 100644 --- a/SPECS/pyparted.spec +++ b/SPECS/pyparted.spec @@ -2,7 +2,7 @@ Summary: Python module for GNU parted Name: pyparted Epoch: 1 Version: 3.9 -Release: 11%{?dist} +Release: 13%{?dist} License: GPLv2+ Group: System Environment/Libraries URL: http://fedorahosted.org/pyparted @@ -16,6 +16,11 @@ Patch5: pyparted-3.9-aarch64.patch Patch6: Makefile_enable_coverage_for_testsuite.patch Patch7: 0001-Fix-some-tests-under-python-coverage-1057626.patch Patch8: 0001-support-ppc64le-in-pyparted.patch +Patch9: 0004-Add-new-functions-to-extend-exception-handling.patch +Patch10: 0005-PyInt_FromLong-doesn-t-exist-in-python3-so-always-us.patch +Patch11: 0006-Remember-to-pass-the-arguments-to-the-exception-hand.patch +Patch12: 0007-Put-new-_ped-constants-and-functions-into-the-parted.patch + BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(id -u -n) BuildRequires: python-devel @@ -42,6 +47,10 @@ partition tables. %endif %patch7 -p 1 %patch8 -p 1 +%patch9 -p 1 +%patch10 -p 1 +%patch11 -p 1 +%patch12 -p 1 %build make %{?_smp_mflags} @@ -64,6 +73,14 @@ rm -rf %{buildroot} %{python_sitearch}/%{name}-%{version}-*.egg-info %changelog +* Tue Jun 23 2015 David Cantrell - 1:3.9-13 +- Rebuild + Resolves: rhbz#1188163 + +* Thu Jun 11 2015 Brian C. Lane - 1:3.9-12 +- Backport support for register_exn_handler (#1188163) + Related: rhbz#1188163 + * Tue Aug 19 2014 David Cantrell - 1:3.9-11 - Fix invalid rpm changelog entries Related: rhbz#1125656