public inbox for git-commits@fedoraproject.org
help / color / mirror / Atom feed
* [rpms/python-dmidecode] main: Patched for libxml2-2.15.4
@ 2026-09-17 19:03 Antonio Trande
0 siblings, 0 replies; only message in thread
From: Antonio Trande @ 2026-09-17 19:03 UTC (permalink / raw)
To: git-commits
A new commit has been pushed.
Repo : rpms/python-dmidecode
Branch : main
Commit : b807f4cd332538f0668b1ac00df13dcbb74b68ef
Author : Antonio Trande <sagitter@fedoraproject.org>
Date : 2026-09-17T21:02:56+02:00
Stats : +752/-4 in 2 file(s)
URL : https://src.fedoraproject.org/rpms/python-dmidecode/c/b807f4cd332538f0668b1ac00df13dcbb74b68ef?branch=main
Log:
Patched for libxml2-2.15.4
---
diff --git a/python-dmidecode-libxml2.patch b/python-dmidecode-libxml2.patch
new file mode 100644
index 0000000..f82c8c0
--- /dev/null
+++ b/python-dmidecode-libxml2.patch
@@ -0,0 +1,737 @@
+From 4ad2e4ca0f6ca6c40fb994a72f8972d24b890554 Mon Sep 17 00:00:00 2001
+From: Yuzuru10 <yuzuru_10@proton.me>
+Date: Sat, 5 Jul 2025 20:21:14 +0300
+Subject: [PATCH] Fix XML handling and update libxml2 bindings in python-dmidecode
+
+diff --git a/dmidecode.py b/dmidecode.py
+index ac81365..19379f4 100644
+--- a/dmidecode.py
++++ b/dmidecode.py
+@@ -25,24 +25,25 @@
+ # are deemed to be part of the source code.
+ #
+
+-import libxml2
++try:
++ from lxml import etree
++except ImportError:
++ raise ImportError("lxml is required. Install with: pip install lxml")
++
+ from dmidecodemod import *
++from lxml import etree
++from dmidecodemod import xmlapi
+
+-DMIXML_NODE='n'
+-DMIXML_DOC='d'
++DMIXML_NODE = 'n'
++DMIXML_DOC = 'd'
+
+ class dmidecodeXML:
+ "Native Python API for retrieving dmidecode information as XML"
+-
++
+ def __init__(self):
+- self.restype = DMIXML_NODE;
++ self.restype = DMIXML_NODE
+
+ def SetResultType(self, type):
+- """
+- Sets the result type of queries. The value can be DMIXML_NODE or DMIXML_DOC,
+- which will return an libxml2::xmlNode or libxml2::xmlDoc object, respectively
+- """
+-
+ if type == DMIXML_NODE:
+ self.restype = DMIXML_NODE
+ elif type == DMIXML_DOC:
+@@ -52,38 +53,308 @@ def SetResultType(self, type):
+ return True
+
+ def QuerySection(self, sectname):
+- """
+- Queries the DMI data structure for a given section name. A section
+- can often contain several DMI type elements
+- """
+- if self.restype == DMIXML_NODE:
+- ret = libxml2.xmlNode( _obj = xmlapi(query_type='s',
+- result_type=self.restype,
+- section=sectname) )
+- elif self.restype == DMIXML_DOC:
+- ret = libxml2.xmlDoc( _obj = xmlapi(query_type='s',
+- result_type=self.restype,
+- section=sectname) )
+- else:
+- raise TypeError("Invalid result type value")
++ try:
++ query_args = {
++ 'query_type': 's',
++ 'result_type': 'n' if self.restype == DMIXML_NODE else 'd',
++ 'section': sectname
++ }
++
++ xml_string = xmlapi(**query_args)
+
+- return ret
++ if not xml_string or not isinstance(xml_string, str):
++ raise RuntimeError("C module did not return a valid XML string")
+
++ if self.restype == DMIXML_NODE:
++ return etree.fromstring(xml_string)
++ elif self.restype == DMIXML_DOC:
++ return etree.ElementTree(etree.fromstring(xml_string))
++ else:
++ raise TypeError("Invalid result type value")
++
++ except Exception as e:
++ raise RuntimeError(f"Failed to query section '{sectname}': {str(e)}")
+
+ def QueryTypeId(self, tpid):
+- """
+- Queries the DMI data structure for a specific DMI type.
+- """
+- if self.restype == DMIXML_NODE:
+- ret = libxml2.xmlNode( _obj = xmlapi(query_type='t',
+- result_type=self.restype,
+- typeid=tpid))
+- elif self.restype == DMIXML_DOC:
+- ret = libxml2.xmlDoc( _obj = xmlapi(query_type='t',
+- result_type=self.restype,
+- typeid=tpid))
+- else:
+- raise TypeError("Invalid result type value")
++ try:
++ tpid = int(tpid)
++ query_args = {
++ 'query_type': 't',
++ 'result_type': 'n' if self.restype == DMIXML_NODE else 'd',
++ 'typeid': tpid
++ }
++
++ xml_string = xmlapi(**query_args)
++
++ if not xml_string or not isinstance(xml_string, str):
++ raise RuntimeError("C module did not return a valid XML string")
++
++ if self.restype == DMIXML_NODE:
++ return etree.fromstring(xml_string)
++ elif self.restype == DMIXML_DOC:
++ return etree.ElementTree(etree.fromstring(xml_string))
++ else:
++ raise TypeError("Invalid result type value")
++
++ except Exception as e:
++ raise RuntimeError(f"Failed to query type ID '{tpid}': {str(e)}")
++
++# Convenience functions for backward compatibility
++def query_section(sectname, result_type=DMIXML_NODE):
++ """
++ Convenience function to query a section and return lxml object
++ """
++ dmi = dmidecodeXML()
++ dmi.SetResultType(result_type)
++ return dmi.QuerySection(sectname)
++
++def query_type_id(tpid, result_type=DMIXML_NODE):
++ """
++ Convenience function to query a type ID and return lxml object
++ """
++ dmi = dmidecodeXML()
++ dmi.SetResultType(result_type)
++ return dmi.QueryTypeId(tpid)
++
++# Backward compatibility class for older API
++class DMIDecode:
++ def __init__(self):
++ self.dmi = dmidecodeXML()
++
++ def get(self, section=None, type_id=None):
++ try:
++ if section is not None:
++ section = str(section)
++ xml_data = self.dmi.QuerySection(section)
++ elif type_id is not None:
++ if isinstance(type_id, dict):
++ try:
++ type_id = int(list(type_id.keys())[0], 16)
++ except Exception as e:
++ raise ValueError(f"Invalid type_id dict format: {type_id}") from e
++ else:
++ type_id = int(type_id)
++ xml_data = self.dmi.QueryTypeId(type_id)
++ else:
++ raise ValueError("Either section or type_id must be specified")
++
++ if xml_data is None:
++ return {}
++
++ return self._xml_to_dict(xml_data)
++
++ except Exception as e:
++ import traceback
++ traceback.print_exc()
++ return {}
++
++ def _xml_to_dict(self, xml_element):
++ result = {}
++ if xml_element.attrib:
++ result.update(xml_element.attrib)
++ if xml_element.text and xml_element.text.strip():
++ if len(xml_element) == 0:
++ return xml_element.text.strip()
++ else:
++ result['_text'] = xml_element.text.strip()
++ for child in xml_element:
++ child_data = self._xml_to_dict(child)
++ if child.tag in result:
++ if not isinstance(result[child.tag], list):
++ result[child.tag] = [result[child.tag]]
++ result[child.tag].append(child_data)
++ else:
++ result[child.tag] = child_data
++ return result
++
++ def system(self):
++ """Get system information"""
++ return self.get(section="system")
++
++ def bios(self):
++ """Get BIOS information"""
++ return self.get(type_id=0)
++
++ def baseboard(self):
++ """Get baseboard information"""
++ return self.get(type_id=2)
++
++ def chassis(self):
++ """Get chassis information"""
++ return self.get(type_id=3)
++
++ def processor(self):
++ """Get processor information"""
++ return self.get(type_id=4)
++
++ def memory(self):
++ """Get memory information"""
++ return self.get(section="memory")
++
++ def model(self):
++ """Get system model information"""
++ try:
++ system_info = self.get(section="system")
++ if system_info and isinstance(system_info, dict):
++ # Try to find model/product name in the system info
++ # Look for common keys that might contain model info
++ for key in ['product', 'model', 'product_name', 'system_product_name']:
++ if key in system_info:
++ return system_info[key]
++
++ # If it's nested, try to find it in nested structures
++ for value in system_info.values():
++ if isinstance(value, dict):
++ for subkey in ['product', 'model', 'product_name']:
++ if subkey in value:
++ return value[subkey]
++
++ return "Unknown"
++ except Exception as e:
++ print(f"Error getting model info: {e}")
++ return "Unknown"
++
++ def manufacturer(self):
++ """Get system manufacturer"""
++ try:
++ system_info = self.get(section="system")
++ if system_info and isinstance(system_info, dict):
++ for key in ['manufacturer', 'vendor', 'system_manufacturer']:
++ if key in system_info:
++ return system_info[key]
++
++ # Check nested structures
++ for value in system_info.values():
++ if isinstance(value, dict):
++ for subkey in ['manufacturer', 'vendor']:
++ if subkey in value:
++ return value[subkey]
++
++ return "Unknown"
++ except Exception as e:
++ print(f"Error getting manufacturer info: {e}")
++ return "Unknown"
++
++ def version(self):
++ """Get system version"""
++ try:
++ system_info = self.get(section="system")
++ if system_info and isinstance(system_info, dict):
++ for key in ['version', 'system_version']:
++ if key in system_info:
++ return system_info[key]
++
++ # Check nested structures
++ for value in system_info.values():
++ if isinstance(value, dict):
++ if 'version' in value:
++ return value['version']
++
++ return "Unknown"
++ except Exception as e:
++ print(f"Error getting version info: {e}")
++ return "Unknown"
++
++ def serial(self):
++ """Get system serial number"""
++ try:
++ system_info = self.get(section="system")
++ if system_info and isinstance(system_info, dict):
++ for key in ['serial', 'serial_number', 'system_serial']:
++ if key in system_info:
++ return system_info[key]
++
++ # Check nested structures
++ for value in system_info.values():
++ if isinstance(value, dict):
++ for subkey in ['serial', 'serial_number']:
++ if subkey in value:
++ return value[subkey]
++
++ return "Unknown"
++ except Exception as e:
++ print(f"Error getting serial info: {e}")
++ return "Unknown"
++
++ def cpu_type(self):
++ """Get CPU type/model information"""
++ try:
++ # Try processor section first
++ proc_info = self.get(type_id=4) # Type 4 is processor
++ if proc_info and isinstance(proc_info, dict):
++ # Look for CPU model/type info
++ for key in ['version', 'model', 'name', 'processor_version', 'processor_name']:
++ if key in proc_info:
++ return proc_info[key]
++
++ # Check nested structures
++ for value in proc_info.values():
++ if isinstance(value, dict):
++ for subkey in ['version', 'model', 'name']:
++ if subkey in value:
++ return value[subkey]
++
++ # If that fails, try a different approach
++ return "Unknown"
++ except Exception as e:
++ print(f"Error getting CPU type: {e}")
++ return "Unknown"
++
++ def cpu(self):
++ """Alias for cpu_type() for compatibility"""
++ return self.cpu_type()
+
+- return ret
++# Example usage functions
++def get_system_info():
++ """
++ Get system information as a convenient dictionary
++ """
++ try:
++ root = query_section("system")
++ if root is None:
++ return None
++
++ system_info = {}
++
++ # Extract common system information
++ for elem in root.iter():
++ if elem.tag == "manufacturer":
++ system_info["manufacturer"] = elem.text
++ elif elem.tag == "product":
++ system_info["product"] = elem.text
++ elif elem.tag == "version":
++ system_info["version"] = elem.text
++ elif elem.tag == "serial":
++ system_info["serial"] = elem.text
++ elif elem.tag == "uuid":
++ system_info["uuid"] = elem.text
++ elif elem.tag == "family":
++ system_info["family"] = elem.text
++
++ return system_info
++ except Exception as e:
++ print(f"Error getting system info: {e}")
++ return None
+
++def get_memory_info():
++ """
++ Get memory information as a list of memory modules
++ """
++ try:
++ root = query_section("memory")
++ if root is None:
++ return None
++
++ memory_modules = []
++
++ # This is a simplified example - you'd need to adjust based on actual XML structure
++ for device in root.findall(".//memory_device"):
++ module = {}
++ for child in device:
++ module[child.tag] = child.text
++ memory_modules.append(module)
++
++ return memory_modules
++ except Exception as e:
++ print(f"Error getting memory info: {e}")
++ return None
+
+diff --git a/src/dmidecodemodule.c b/src/dmidecodemodule.c
+index efa730b..2b3f67f 100644
+--- a/src/dmidecodemodule.c
++++ b/src/dmidecodemodule.c
+@@ -42,8 +42,6 @@
+ #include <Python.h>
+
+ #include <libxml/tree.h>
+-#include "libxml_wrap.h"
+-
+ #include "dmidecodemodule.h"
+ #include "dmixml.h"
+ #include "dmierror.h"
+@@ -431,6 +429,7 @@ xmlNode *__dmidecode_xml_getsection(options *opt, const char *section) {
+
+ dmixml_n = xmlNewNode(NULL, (xmlChar *) "dmidecode");
+ assert( dmixml_n != NULL );
++
+ // Append DMI version info
+ if( opt->dmiversion_n != NULL ) {
+ xmlAddChild(dmixml_n, xmlCopyNode(opt->dmiversion_n, 1));
+@@ -439,7 +438,6 @@ xmlNode *__dmidecode_xml_getsection(options *opt, const char *section) {
+ // Fetch the Mapping XML file
+ if( (group_n = load_mappingxml(opt)) == NULL) {
+ xmlFreeNode(dmixml_n);
+- // Exception already set by calling function
+ return NULL;
+ }
+
+@@ -468,36 +466,35 @@ xmlNode *__dmidecode_xml_getsection(options *opt, const char *section) {
+ continue;
+ }
+
+- // The children of <Mapping> tags must only be <TypeMap> and
+- // they must have an 'id' attribute
+ if( (typeid == NULL) || (xmlStrcmp(group_n->name, (xmlChar *) "TypeMap") != 0) ) {
+ PyReturnError(PyExc_RuntimeError, "Invalid TypeMap node in mapping XML");
+ }
+
+- // Parse the typeid string to a an integer
+ opt->type = parse_opt_type(opt->logdata, typeid);
+ if(opt->type == -1) {
+ char *err = log_retrieve(opt->logdata, LOG_ERR);
+ log_clear_partial(opt->logdata, LOG_ERR, 0);
+- _pyReturnError(PyExc_RuntimeError, "Invalid type id '%s' -- %s", typeid, err);
++ PyErr_Format(PyExc_RuntimeError, "Invalid type id '%s' -- %s", typeid, err);
+ free(err);
+ return NULL;
+ }
+
+- // Parse the DMI data and put the result into dmixml_n node chain.
+ if( dmidecode_get_xml(opt, dmixml_n) != 0 ) {
+- PyReturnError(PyExc_RuntimeError, "Error decoding DMI data");
++ return NULL;
+ }
+ }
++
+ #if 0 // DEBUG - will dump generated XML to stdout
+ xmlDoc *doc = xmlNewDoc((xmlChar *) "1.0");
+ xmlDocSetRootElement(doc, xmlCopyNode(dmixml_n, 1));
+ xmlSaveFormatFileEnc("-", doc, "UTF-8", 1);
+ xmlFreeDoc(doc);
+ #endif
++
+ return dmixml_n;
+ }
+
++
+ static PyObject *dmidecode_get_group(options *opt, const char *section)
+ {
+ int efi;
+@@ -692,73 +689,127 @@ static PyObject *dmidecode_get_type(PyObject * self, PyObject * args)
+
+ static PyObject *dmidecode_xmlapi(PyObject *self, PyObject *args, PyObject *keywds)
+ {
+- static char *keywordlist[] = {"query_type", "result_type", "section", "typeid", NULL};
+- PyObject *pydata = NULL;
+- xmlDoc *dmixml_doc = NULL;
+- xmlNode *dmixml_n = NULL;
+- char *sect_query = NULL, *qtype = NULL, *rtype = NULL;
+- int type_query = -1;
++ static char *keywordlist[] = {"query_type", "result_type", "section", "typeid", NULL};
++ PyObject *pydata = NULL;
++ xmlDoc *dmixml_doc = NULL;
++ xmlNode *dmixml_n = NULL;
++ char *sect_query = NULL, *qtype = NULL, *rtype = NULL;
++ int type_query = -1;
++ xmlBuffer *buffer = NULL;
++ xmlChar *xml_string = NULL;
++ int xml_size = 0;
++
++ if (!PyArg_ParseTupleAndKeywords(args, keywds, "ss|si", keywordlist,
++ &qtype, &rtype, §_query, &type_query))
++ return NULL;
++
++ if (!qtype || !rtype) {
++ PyErr_SetString(PyExc_TypeError, "query_type and result_type cannot be NULL");
++ return NULL;
++ }
++
++ switch (*qtype) {
++ case 's':
++ if (!sect_query) {
++ PyErr_SetString(PyExc_TypeError, "section keyword cannot be NULL");
++ return NULL;
++ }
++ dmixml_n = __dmidecode_xml_getsection(global_options, sect_query);
++ if (!dmixml_n) {
++ PyErr_Format(PyExc_RuntimeError, "DMI section '%s' returned NULL - possibly unsupported or bad permissions", sect_query);
++ return NULL;
++ }
++ break;
++ case 't':
++ if (type_query < 0) {
++ PyErr_SetString(PyExc_TypeError, "typeid keyword must be set and positive integer");
++ return NULL;
++ }
++ if (type_query > 255) {
++ PyErr_SetString(PyExc_ValueError, "typeid must be between 0 and 255");
++ return NULL;
++ }
++ dmixml_n = __dmidecode_xml_gettypeid(global_options, type_query);
++ if (!dmixml_n) {
++ PyErr_Format(PyExc_RuntimeError, "DMI type '%d' returned NULL - possibly unsupported or bad permissions", type_query);
++ return NULL;
++ }
++ break;
++ default:
++ PyErr_Format(PyExc_TypeError, "Invalid query type '%c' - must be 's' or 't'", *qtype);
++ return NULL;
++ }
++
++ if (!dmixml_n) // ekstra kontrol, zaten hata set edildi
++ return NULL;
+
+- // Parse the keywords - we only support keywords, as this is an internal API
+- if( !PyArg_ParseTupleAndKeywords(args, keywds, "ss|si", keywordlist,
+- &qtype, &rtype, §_query, &type_query) ) {
++ switch (*rtype) {
++ case 'n': // XML node string
++ buffer = xmlBufferCreate();
++ if (!buffer) {
++ xmlFreeNode(dmixml_n);
++ PyErr_SetString(PyExc_MemoryError, "Could not create XML buffer");
+ return NULL;
+- }
++ }
+
+- // Check for sensible arguments and retrieve the xmlNode with DMI data
+- switch( *qtype ) {
+- case 's': // Section / GroupName
+- if( sect_query == NULL ) {
+- PyReturnError(PyExc_TypeError, "section keyword cannot be NULL")
+- }
+- dmixml_n = __dmidecode_xml_getsection(global_options, sect_query);
+- break;
+-
+- case 't': // TypeID / direct TypeMap
+- if( type_query < 0 ) {
+- PyReturnError(PyExc_TypeError,
+- "typeid keyword must be set and must be a positive integer");
+- } else if( type_query > 255 ) {
+- PyReturnError(PyExc_ValueError,
+- "typeid keyword must be an integer between 0 and 255");
+- }
+- dmixml_n = __dmidecode_xml_gettypeid(global_options, type_query);
+- break;
++ if (xmlNodeDump(buffer, dmixml_n->doc, dmixml_n, 0, 1) < 0) {
++ xmlBufferFree(buffer);
++ xmlFreeNode(dmixml_n);
++ PyErr_SetString(PyExc_RuntimeError, "Could not dump XML node to buffer");
++ return NULL;
++ }
+
+- default:
+- PyReturnError(PyExc_TypeError, "Internal error - invalid query type '%c'", *qtype);
+- }
++ pydata = PyUnicode_FromString((const char *)xmlBufferContent(buffer));
++ xmlBufferFree(buffer);
++ xmlFreeNode(dmixml_n);
++ break;
+
+- // Check if we got any data
+- if( dmixml_n == NULL ) {
+- // Exception already set
++ case 'd': // Full XML document string
++ dmixml_doc = xmlNewDoc((xmlChar *)"1.0");
++ if (!dmixml_doc) {
++ xmlFreeNode(dmixml_n);
++ PyErr_SetString(PyExc_MemoryError, "Could not create new XML document");
+ return NULL;
+- }
++ }
+
+- // Check for sensible return type and wrap the correct type into a Python Object
+- switch( *rtype ) {
+- case 'n':
+- pydata = libxml_xmlNodePtrWrap((xmlNode *) dmixml_n);
+- break;
++ xmlNode *root_node = xmlCopyNode(dmixml_n, 1);
++ if (!root_node) {
++ xmlFreeDoc(dmixml_doc);
++ xmlFreeNode(dmixml_n);
++ PyErr_SetString(PyExc_MemoryError, "Could not copy XML node");
++ return NULL;
++ }
+
+- case 'd':
+- dmixml_doc = xmlNewDoc((xmlChar *) "1.0");
+- if( dmixml_doc == NULL ) {
+- PyReturnError(PyExc_MemoryError, "Could not create new XML document");
+- }
+- xmlDocSetRootElement(dmixml_doc, dmixml_n);
+- pydata = libxml_xmlDocPtrWrap((xmlDoc *) dmixml_doc);
+- break;
++ xmlDocSetRootElement(dmixml_doc, root_node);
++
++ xmlDocDumpMemory(dmixml_doc, &xml_string, &xml_size);
++ if (!xml_string) {
++ xmlFreeDoc(dmixml_doc);
++ xmlFreeNode(dmixml_n);
++ PyErr_SetString(PyExc_RuntimeError, "Could not dump XML document to memory");
++ return NULL;
++ }
++
++ pydata = PyUnicode_FromString((const char *)xml_string);
++
++ xmlFree(xml_string);
++ xmlFreeDoc(dmixml_doc);
++ xmlFreeNode(dmixml_n);
++ break;
+
+ default:
+- PyReturnError(PyExc_TypeError, "Internal error - invalid result type '%c'", *rtype);
+- }
++ xmlFreeNode(dmixml_n);
++ PyErr_Format(PyExc_TypeError, "Invalid result type '%c' - must be 'n' or 'd'", *rtype);
++ return NULL;
++ }
+
+- // Return XML data
+- Py_INCREF(pydata);
+- return pydata;
+-}
++ if (!pydata) {
++ PyErr_SetString(PyExc_RuntimeError, "Could not create Python string from XML data");
++ return NULL;
++ }
+
++ return pydata;
++}
+
+
+ static PyObject *dmidecode_dump(PyObject * self, PyObject * null)
+@@ -913,8 +964,12 @@ static PyMethodDef DMIDataMethods[] = {
+ {(char *)"pythonmap", dmidecode_set_pythonxmlmap, METH_O,
+ (char *) "Use another python dict map definition. The default file is " PYTHON_XML_MAP},
+
+- {(char *)"xmlapi", dmidecode_xmlapi, METH_VARARGS | METH_KEYWORDS,
+- (char *) "Internal API for retrieving data as raw XML data"},
++ {
++ .ml_name = "xmlapi",
++ .ml_meth = (PyCFunction)(void(*)(void))dmidecode_xmlapi,
++ .ml_flags = METH_VARARGS | METH_KEYWORDS,
++ .ml_doc = "Get DMI data as XML"
++ },
+
+
+ {(char *)"get_warnings", dmidecode_get_warnings, METH_NOARGS,
+@@ -926,48 +981,49 @@ static PyMethodDef DMIDataMethods[] = {
+ {NULL, NULL, 0, NULL}
+ };
+
+-void destruct_options(void *ptr)
++void destruct_options(PyObject *capsule)
+ {
+-#ifdef IS_PY3K
+- ptr = PyCapsule_GetPointer(ptr, NULL);
+-#endif
++ void *ptr = PyCapsule_GetPointer(capsule, NULL);
++ if (ptr) {
+ options *opt = (options *) ptr;
+
+ if( opt->mappingxml != NULL ) {
+- xmlFreeDoc(opt->mappingxml);
+- opt->mappingxml = NULL;
++ xmlFreeDoc(opt->mappingxml);
++ opt->mappingxml = NULL;
+ }
+
+ if( opt->python_xml_map != NULL ) {
+- free(opt->python_xml_map);
+- opt->python_xml_map = NULL;
++ free(opt->python_xml_map);
++ opt->python_xml_map = NULL;
+ }
+
+ if( opt->dmiversion_n != NULL ) {
+- xmlFreeNode(opt->dmiversion_n);
+- opt->dmiversion_n = NULL;
++ xmlFreeNode(opt->dmiversion_n);
++ opt->dmiversion_n = NULL;
+ }
+
+ if( opt->dumpfile != NULL ) {
+- free(opt->dumpfile);
+- opt->dumpfile = NULL;
++ free(opt->dumpfile);
++ opt->dumpfile = NULL;
+ }
+
+ if( opt->logdata != NULL ) {
+- char *warn = NULL;
++ char *warn = NULL;
+
+- log_clear_partial(opt->logdata, LOG_WARNING, 0);
+- warn = log_retrieve(opt->logdata, LOG_WARNING);
+- if( warn ) {
+- fprintf(stderr, "\n** COLLECTED WARNINGS **\n%s** END OF WARNINGS **\n\n", warn);
+- free(warn);
+- }
+- log_close(opt->logdata);
++ log_clear_partial(opt->logdata, LOG_WARNING, 0);
++ warn = log_retrieve(opt->logdata, LOG_WARNING);
++ if( warn ) {
++ fprintf(stderr, "\n** COLLECTED WARNINGS **\n%s** END OF WARNINGS **\n\n", warn);
++ free(warn);
++ }
++ log_close(opt->logdata);
+ }
+
+ free(ptr);
++ }
+ }
+
++
+ #ifdef IS_PY3K
+ static struct PyModuleDef dmidecodemod_def = {
+ PyModuleDef_HEAD_INIT,
+diff --git a/src/setup_common.py b/src/setup_common.py
+index aec1f9b..90d88c3 100644
+--- a/setup_common.py
++++ b/setup_common.py
+@@ -69,7 +69,7 @@ def libxml2_lib(libdir, libs):
+ libs.append(l.replace("-l", "", 1))
+
+ # this library is not reported and we need it anyway
+- libs.append('xml2mod')
++ #libs.append('xml2mod')
+
+
+
+
diff --git a/python-dmidecode.spec b/python-dmidecode.spec
index f210ac1..128409a 100644
--- a/python-dmidecode.spec
+++ b/python-dmidecode.spec
@@ -13,18 +13,23 @@
Name: python-dmidecode
Summary: Python module to access DMI data
Version: 3.12.3
-Release: 19%{date}%{shortcommit}%{?dist}
+Release: 20%{date}%{shortcommit}%{?dist}
License: GPL-2.0-only
URL: https://github.com/nima/python-dmidecode
Source0: %{url}/archive/%{version}/%{name}-%{version}.tar.gz
Patch0: python-dmidecode-rhbz2154949.patch
+# This patch derives by a fork,
+# https://github.com/Yuzuru10/python-dmidecode/commit/4ad2e4ca0f6ca6c40fb994a72f8972d24b890554
+Patch1: python-dmidecode-libxml2.patch
+
BuildRequires: make
BuildRequires: gcc
BuildRequires: libxml2-devel
BuildRequires: python3-devel
BuildRequires: libxml2-python3
+BuildRequires: python3-lxml
%global _description\
python-dmidecode is a python extension module that uses the\
@@ -38,6 +43,7 @@ as python data structures or as XML data using libxml2.\
%package -n python3-dmidecode
Summary: Python 3 module to access DMI data
Requires: libxml2-python3
+Requires: python3-lxml
%description -n python3-dmidecode %_description
@@ -49,6 +55,10 @@ Requires: libxml2-python3
# we need the setup.py file in PWD to make the setuptools build backend see it
mv src/setup*.py .
+%if 0%{?fedora} > 45
+%patch 1 -p1 -b .libxml2
+%endif
+
%generate_buildrequires
%pyproject_buildrequires
@@ -65,20 +75,21 @@ export CXX=g++
%pyproject_install
%pyproject_save_files -L dmidecode dmidecodemod
-
%check
%pyproject_check_import
export PYTHONPATH=%{buildroot}%{python3_sitearch}
-export PYTHON_BIN=%{__python3}
+%{py3_test_envvars}
make -C unit-tests
-
%files -n python3-dmidecode -f %{pyproject_files}
%license doc/LICENSE
%doc README doc/AUTHORS doc/AUTHORS.upstream
%{_datadir}/%{name}/
%changelog
+* Thu Sep 17 2026 Antonio Trande <sagitter@fedoraproject.org> - 3.12.3-20
+- Patched for libxml2-2.15.4
+
* Wed Jul 22 2026 Python Maint <python-maint@redhat.com> - 3.12.3-19
- Rebuilt for Python 3.15.0b4 ABI change
^ permalink raw reply related [flat|nested] only message in thread
only message in thread, other threads:[~2026-09-17 19:03 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-09-17 19:03 [rpms/python-dmidecode] main: Patched for libxml2-2.15.4 Antonio Trande
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox