Handle extended enum values for QNetworkReqest.setAttribute in PyQt6

Since this is an enum designed to be extended in c++ (eg by adding
values after Qt's user role), we have to do some fancy wrapping
in order to make these extended roles look like the types
acceptable to the PyQt function.

This has been designed to allow other functions to be wrapped
which rely on custom enum values.
This commit is contained in:
Nyall Dawson 2024-01-27 10:31:37 +10:00
parent 4c7cfb457a
commit 59bd0befb5
3 changed files with 63 additions and 0 deletions

View File

@ -2,6 +2,7 @@ set (QGIS_PYQT_DIR ${Python_SITEARCH}/qgis/PyQt)
set(PYQT_COMPAT_FILES
__init__.py
common.py
QtWidgets.py
QtCore.py
QtGui.py

View File

@ -22,6 +22,7 @@ __date__ = 'March 2016'
__copyright__ = '(C) 2016, Juergen E. Fischer'
from PyQt@QT_VERSION_MAJOR@.QtNetwork import *
from .common import install_extended_enum_wrapper
if @QT_VERSION_MAJOR@ == 6:
# patch back in Qt flags removed in PyQt
@ -33,3 +34,6 @@ if @QT_VERSION_MAJOR@ == 6:
QNetworkInterface.InterfaceFlags = lambda flags=0: QNetworkInterface.InterfaceFlag(flags)
QNetworkProxy.Capabilities = lambda flags=0: QNetworkProxy.Capability(flags)
QSsl.SslOptions = lambda flags=0: QSsl.SslOption(flags)
QNetworkRequest.setAttribute = install_extended_enum_wrapper(QNetworkRequest.setAttribute)

View File

@ -0,0 +1,58 @@
"""
***************************************************************************
common.py
---------------------
Date : January 2024
Copyright : (C) 2024 by Nyall Dawson
Email : nyall dot dawson at gmail dot com
***************************************************************************
* *
* 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. *
* *
***************************************************************************
"""
import functools
from enum import Enum
def _handle_extended_enum_values(v):
"""
If v is an Enum, returns an integer representation of its value wrapped
in the Enum class.
Otherwise returns v unchanged.
"""
if isinstance(v, Enum):
# v may be an Enum value which itself is an Enum value!
# E.g. QNetworkRequest.Attribute(QgsNetworkRequestParameters.RequestAttributes.AttributeInitiatorClass)
# in this case v is an Enum of the class QNetworkRequest.Attribute, while v.value is an Enum of the
# class QgsNetworkRequestParameters.RequestAttributes. For this to work, we need to extract the integer
# value from QgsNetworkRequestParameters.RequestAttributes.AttributeInitiatorClass and then convert it
# to a QNetworkRequest.Attribute enum value!
if isinstance(v.value, Enum):
return v.__class__(int(v.value.value))
return v.__class__(int(v.value))
return v
def _extended_enum_wrapper(method):
"""
Calls a function, first converting all passed Enum arguments to integer
values so that extended enum values work correctly.
"""
@functools.wraps(method)
def wrapped(*args, **kwargs):
parsed_args = [_handle_extended_enum_values(arg) for arg in args]
parsed_kwargs = {k: _handle_extended_enum_values(v) for k, v in kwargs.items()}
return method(*parsed_args, **parsed_kwargs)
return wrapped
def install_extended_enum_wrapper(f):
"""
Installs a wrapper on a function so that all passed extended Enum arguments are handled correctly.
"""
return _extended_enum_wrapper(f)