Skip to content

Commit f362076

Browse files
committed
Update wrapt to 2.0.1
1 parent 2888d85 commit f362076

File tree

5 files changed

+86
-12
lines changed

5 files changed

+86
-12
lines changed

newrelic/packages/requirements.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,5 @@
44
# to the New Relic Python Agent's dependencies in newrelic/packages/.
55
opentelemetry_proto==1.32.1
66
urllib3==2.6.2
7-
wrapt==2.0.0
7+
wrapt==2.0.1
88
asgiref==3.6.0 # We only vendor asgiref.compatibility.py

newrelic/packages/wrapt/LICENSE

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
Copyright (c) 2013-2019, Graham Dumpleton
1+
Copyright (c) 2013-2025, Graham Dumpleton
22
All rights reserved.
33

44
Redistribution and use in source and binary forms, with or without

newrelic/packages/wrapt/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
Wrapt is a library for decorators, wrappers and monkey patching.
33
"""
44

5-
__version_info__ = ("2", "0", "0")
5+
__version_info__ = ("2", "0", "1")
66
__version__ = ".".join(__version_info__)
77

88
from .__wrapt__ import (
@@ -53,6 +53,7 @@
5353
"when_imported",
5454
"apply_patch",
5555
"function_wrapper",
56+
"lazy_import",
5657
"patch_function_wrapper",
5758
"resolve_path",
5859
"transient_function_wrapper",

newrelic/packages/wrapt/__init__.pyi

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,16 @@ if sys.version_info >= (3, 10):
3737
# LazyObjectProxy
3838

3939
class LazyObjectProxy(AutoObjectProxy[T]):
40-
def __init__(self, callback: Callable[[], T] | None) -> None: ...
40+
def __init__(
41+
self, callback: Callable[[], T] | None, *, interface: Any = ...
42+
) -> None: ...
4143

4244
@overload
4345
def lazy_import(name: str) -> LazyObjectProxy[ModuleType]: ...
4446
@overload
45-
def lazy_import(name: str, attribute: str) -> LazyObjectProxy[Any]: ...
47+
def lazy_import(
48+
name: str, attribute: str, *, interface: Any = ...
49+
) -> LazyObjectProxy[Any]: ...
4650

4751
# CallableObjectProxy
4852

newrelic/packages/wrapt/proxies.py

Lines changed: 76 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
"""Variants of ObjectProxy for different use cases."""
22

3+
from collections.abc import Callable
4+
from types import ModuleType
5+
36
from .__wrapt__ import BaseObjectProxy
47
from .decorators import synchronized
58

@@ -30,7 +33,12 @@ def __iter__(self):
3033
# object and add special dunder methods.
3134

3235

33-
def __wrapper_call__(self, *args, **kwargs):
36+
def __wrapper_call__(*args, **kwargs):
37+
def _unpack_self(self, *args):
38+
return self, args
39+
40+
self, args = _unpack_self(*args)
41+
3442
return self.__wrapped__(*args, **kwargs)
3543

3644

@@ -136,7 +144,7 @@ def __new__(cls, wrapped):
136144
if cls is AutoObjectProxy:
137145
name = BaseObjectProxy.__name__
138146

139-
return super().__new__(type(name, (cls,), namespace))
147+
return super(AutoObjectProxy, cls).__new__(type(name, (cls,), namespace))
140148

141149
def __wrapped_setattr_fixups__(self):
142150
"""Adjusts special dunder methods on the class as needed based on the
@@ -218,10 +226,64 @@ class LazyObjectProxy(AutoObjectProxy):
218226
when it is first needed.
219227
"""
220228

221-
def __new__(cls, callback=None):
222-
return super().__new__(cls, None)
229+
def __new__(cls, callback=None, *, interface=...):
230+
"""Injects special dunder methods into a dynamically created subclass
231+
as needed based on the wrapped object.
232+
"""
233+
234+
if interface is ...:
235+
interface = type(None)
236+
237+
namespace = {}
238+
239+
interface_attrs = dir(interface)
240+
class_attrs = set(dir(cls))
241+
242+
if "__call__" in interface_attrs and "__call__" not in class_attrs:
243+
namespace["__call__"] = __wrapper_call__
244+
245+
if "__iter__" in interface_attrs and "__iter__" not in class_attrs:
246+
namespace["__iter__"] = __wrapper_iter__
247+
248+
if "__next__" in interface_attrs and "__next__" not in class_attrs:
249+
namespace["__next__"] = __wrapper_next__
250+
251+
if "__aiter__" in interface_attrs and "__aiter__" not in class_attrs:
252+
namespace["__aiter__"] = __wrapper_aiter__
253+
254+
if "__anext__" in interface_attrs and "__anext__" not in class_attrs:
255+
namespace["__anext__"] = __wrapper_anext__
223256

224-
def __init__(self, callback=None):
257+
if (
258+
"__length_hint__" in interface_attrs
259+
and "__length_hint__" not in class_attrs
260+
):
261+
namespace["__length_hint__"] = __wrapper_length_hint__
262+
263+
# Note that not providing compatibility with generator-based coroutines
264+
# (PEP 342) here as they are removed in Python 3.11+ and were deprecated
265+
# in 3.8.
266+
267+
if "__await__" in interface_attrs and "__await__" not in class_attrs:
268+
namespace["__await__"] = __wrapper_await__
269+
270+
if "__get__" in interface_attrs and "__get__" not in class_attrs:
271+
namespace["__get__"] = __wrapper_get__
272+
273+
if "__set__" in interface_attrs and "__set__" not in class_attrs:
274+
namespace["__set__"] = __wrapper_set__
275+
276+
if "__delete__" in interface_attrs and "__delete__" not in class_attrs:
277+
namespace["__delete__"] = __wrapper_delete__
278+
279+
if "__set_name__" in interface_attrs and "__set_name__" not in class_attrs:
280+
namespace["__set_name__"] = __wrapper_set_name__
281+
282+
name = cls.__name__
283+
284+
return super(AutoObjectProxy, cls).__new__(type(name, (cls,), namespace))
285+
286+
def __init__(self, callback=None, *, interface=...):
225287
"""Initialize the object proxy with wrapped object as `None` but due
226288
to presence of special `__wrapped_factory__` attribute addded first,
227289
this will actually trigger the deferred creation of the wrapped object
@@ -263,14 +325,21 @@ def __wrapped_get__(self):
263325
return self.__wrapped__
264326

265327

266-
def lazy_import(name, attribute=None):
328+
def lazy_import(name, attribute=None, *, interface=...):
267329
"""Lazily imports the module `name`, returning a `LazyObjectProxy` which
268330
will import the module when it is first needed. When `name is a dotted name,
269331
then the full dotted name is imported and the last module is taken as the
270332
target. If `attribute` is provided then it is used to retrieve an attribute
271333
from the module.
272334
"""
273335

336+
if attribute is not None:
337+
if interface is ...:
338+
interface = Callable
339+
else:
340+
if interface is ...:
341+
interface = ModuleType
342+
274343
def _import():
275344
module = __import__(name, fromlist=[""])
276345

@@ -279,4 +348,4 @@ def _import():
279348

280349
return module
281350

282-
return LazyObjectProxy(_import)
351+
return LazyObjectProxy(_import, interface=interface)

0 commit comments

Comments
 (0)