From e684ff969e9442f4832943bcfb4f08f6e3dfc746 Mon Sep 17 00:00:00 2001 From: Graham Dumpleton Date: Sun, 6 Oct 2024 15:25:32 +1100 Subject: [PATCH] Added proxy support for __format__() dunder method. --- docs/changes.rst | 5 +++++ src/wrapt/_wrappers.c | 19 +++++++++++++++++++ src/wrapt/wrappers.py | 3 +++ tests/test_object_proxy.py | 7 +++++++ 4 files changed, 34 insertions(+) diff --git a/docs/changes.rst b/docs/changes.rst index d28d108..7e42084 100644 --- a/docs/changes.rst +++ b/docs/changes.rst @@ -7,6 +7,11 @@ Version 1.17.0 Note that version 1.17.0 drops support for Python 3.6 and 3.7. Python version 3.8 or later is required. +**New Features** + +* Add `__format__()` method to `ObjectProxy` class to allow formatting of + wrapped object. + **Bugs Fixed** * When a normal function or builtin function which had `wrapt.decorator` or a diff --git a/src/wrapt/_wrappers.c b/src/wrapt/_wrappers.c index cebb185..31029c7 100644 --- a/src/wrapt/_wrappers.c +++ b/src/wrapt/_wrappers.c @@ -1284,6 +1284,24 @@ static PyObject *WraptObjectProxy_bytes( /* ------------------------------------------------------------------------- */ +static PyObject *WraptObjectProxy_format( + WraptObjectProxyObject *self, PyObject *args) +{ + PyObject *format_spec = NULL; + + if (!self->wrapped) { + PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + return NULL; + } + + if (!PyArg_ParseTuple(args, "|O:format", &format_spec)) + return NULL; + + return PyObject_Format(self->wrapped, format_spec); +} + +/* ------------------------------------------------------------------------- */ + static PyObject *WraptObjectProxy_reversed( WraptObjectProxyObject *self, PyObject *args) { @@ -1797,6 +1815,7 @@ static PyMethodDef WraptObjectProxy_methods[] = { { "__getattr__", (PyCFunction)WraptObjectProxy_getattr, METH_VARARGS , 0 }, { "__bytes__", (PyCFunction)WraptObjectProxy_bytes, METH_NOARGS, 0 }, + { "__format__", (PyCFunction)WraptObjectProxy_format, METH_VARARGS, 0 }, { "__reversed__", (PyCFunction)WraptObjectProxy_reversed, METH_NOARGS, 0 }, #if PY_MAJOR_VERSION >= 3 { "__round__", (PyCFunction)WraptObjectProxy_round, METH_NOARGS, 0 }, diff --git a/src/wrapt/wrappers.py b/src/wrapt/wrappers.py index 8106a8a..68b99c9 100644 --- a/src/wrapt/wrappers.py +++ b/src/wrapt/wrappers.py @@ -126,6 +126,9 @@ def __repr__(self): type(self.__wrapped__).__name__, id(self.__wrapped__)) + def __format__(self, format_spec): + return format(self.__wrapped__, format_spec) + def __reversed__(self): return reversed(self.__wrapped__) diff --git a/tests/test_object_proxy.py b/tests/test_object_proxy.py index 91a010b..7851647 100644 --- a/tests/test_object_proxy.py +++ b/tests/test_object_proxy.py @@ -1583,6 +1583,13 @@ def test_repr(self): self.assertNotEqual(repr(value).find('ObjectProxy at'), -1) + def test_format(self): + value = 1 + + proxy = wrapt.ObjectProxy(1) + + self.assertEqual("{:0>3}".format(proxy), "{:0>3}".format(value)) + class TestDerivedClassCreation(unittest.TestCase): def test_derived_new(self):