-
Notifications
You must be signed in to change notification settings - Fork 394
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
Remove forbiddenfruit as dependency and rollback wrapt changes where forbiddenfruit was called. IAST: Patch builtins only when IAST is enabled. Co-authored-by: Alberto Vara <alberto.vara@datadoghq.com>
- Loading branch information
1 parent
619db15
commit 56b6086
Showing
6 changed files
with
107 additions
and
35 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
import ctypes | ||
import gc | ||
|
||
from ddtrace.internal.logger import get_logger | ||
from ddtrace.vendor.wrapt import FunctionWrapper | ||
from ddtrace.vendor.wrapt import resolve_path | ||
|
||
|
||
log = get_logger(__name__) | ||
|
||
|
||
def try_wrap_function_wrapper(module, name, wrapper): | ||
try: | ||
wrap_object(module, name, FunctionWrapper, (wrapper,)) | ||
except (ImportError, AttributeError): | ||
log.debug("IAST patching. Module %s.%s not exists", module, name) | ||
|
||
|
||
def apply_patch(parent, attribute, replacement): | ||
try: | ||
setattr(parent, attribute, replacement) | ||
except (TypeError, AttributeError): | ||
patch_builtins(parent, attribute, replacement) | ||
|
||
|
||
def wrap_object(module, name, factory, args=(), kwargs={}): | ||
(parent, attribute, original) = resolve_path(module, name) | ||
wrapper = factory(original, *args, **kwargs) | ||
apply_patch(parent, attribute, wrapper) | ||
return wrapper | ||
|
||
|
||
def patchable_builtin(klass): | ||
refs = gc.get_referents(klass.__dict__) | ||
assert len(refs) == 1 | ||
return refs[0] | ||
|
||
|
||
def patch_builtins(klass, attr, value): | ||
"""Based on forbiddenfruit package: | ||
https://github.com/clarete/forbiddenfruit/blob/master/forbiddenfruit/__init__.py#L421 | ||
--- | ||
Patch a built-in `klass` with `attr` set to `value` | ||
This function monkey-patches the built-in python object `attr` adding a new | ||
attribute to it. You can add any kind of argument to the `class`. | ||
It's possible to attach methods as class methods, just do the following: | ||
>>> def myclassmethod(cls): | ||
... return cls(1.5) | ||
>>> curse(float, "myclassmethod", classmethod(myclassmethod)) | ||
>>> float.myclassmethod() | ||
1.5 | ||
Methods will be automatically bound, so don't forget to add a self | ||
parameter to them, like this: | ||
>>> def hello(self): | ||
... return self * 2 | ||
>>> curse(str, "hello", hello) | ||
>>> "yo".hello() | ||
"yoyo" | ||
""" | ||
dikt = patchable_builtin(klass) | ||
|
||
old_value = dikt.get(attr, None) | ||
old_name = "_c_%s" % attr # do not use .format here, it breaks py2.{5,6} | ||
|
||
# Patch the thing | ||
dikt[attr] = value | ||
|
||
if old_value: | ||
dikt[old_name] = old_value | ||
|
||
try: | ||
dikt[attr].__name__ = old_value.__name__ | ||
except (AttributeError, TypeError): # py2.5 will raise `TypeError` | ||
pass | ||
try: | ||
dikt[attr].__qualname__ = old_value.__qualname__ | ||
except AttributeError: | ||
pass | ||
|
||
ctypes.pythonapi.PyType_Modified(ctypes.py_object(klass)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
6 changes: 6 additions & 0 deletions
6
releasenotes/notes/fix-forbiddenfruit-error-ffbb174ade1c6d57.yaml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
--- | ||
fixes: | ||
- | | ||
Remove ``forbiddenfruit`` as dependency and rollback ``wrapt`` changes where ``forbiddenfruit`` was called. | ||
IAST: Patch builtins only when IAST is enabled. | ||
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters