CodeSampleX

サンプル

wrapt 2.2.2: Invoke wrapt universal decorators and monkey-patch wrappers with 4-arg signatures without double-binding instance or decorating patch hooks

検証済みサンプル — pypi wrapt 2.2.2: Invoke wrapt universal decorators and monkey-patch wrappers with 4-arg signatures without double-binding instance or decorating…

sha256:7a13d82fc8fc99b353d10c003fde6ab931c335ba8d42b8cf245f5a18f4524a1d

このネットワークが提供するのは一つだけです。ビルドされるサンプル。サンドボックスで実行し、署名済みの受領証を保管します。等級はつけず、何も保証しません — 同じコードがあなたの環境でビルドされるかは測定していません。 合格した契約受領証を提出した異なる署名鍵の数です。1 なら作者だけ、2 以上なら他の誰かもビルドしています。鍵は自己生成で背後に登録された身元がないため、数えているのは人ではなく鍵です。 MIT-0

実行証拠

宣言された環境と署名済みの実行を分けてあります。このサンプルが何をどこで実行したかをそのまま確認できます。

証拠の基準
署名済みコントラクト合格
検証レシート
3
ビルドした署名鍵
3
宣言された環境 python linux x64 python python pip

検証実行環境

環境 コントラクト ステージ 実行日
python 3.12 · linux alpine/x64 · docker ed25519:d91480838ac982c9 PASS compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS
CONTAINER_RUN · python@1
2026-08-16
python 3.12 · linux alpine/x64 · docker ed25519:2175b912ea1c23b1 PASS compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS
CONTAINER_RUN · python@1
2026-08-18
python 3.12 · linux debian/x64 · docker ed25519:c1973797be207ac4 PASS compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS
CONTAINER_RUN · python@1python:3.12-slim@sha256:09f7da3bc104…
2026-09-08

ケース

HOW
ゴール
Invoke wrapt universal decorators and monkey-patch wrappers with 4-arg signatures without double-binding instance or decorating patch hooks
パッケージ
シンボル
  • wrapt.decorator
  • wrapt.wrap_function_wrapper
  • wrapt.adapter_factory
  • wrapt.FunctionWrapper
環境
python
作成日
2026-08-16T07:09:19Z

コントラクト

  1. assert wrapt decorator passes instance separately and strips self or cls from positional args
  2. assert wrapped is already bound so passing instance to wrapped(*args) raises TypeError
  3. assert passing a @wrapt.decorator function to wrap_function_wrapper silently returns FunctionWrapper instead of the target return value
  4. assert @wrapt.decorator rejects custom decorator keyword arguments and requires an outer factory function
  5. assert enabled=False returns the unwrapped function while enabled=callable dynamically evaluates per invocation
  6. assert @wrapt.adapter_factory customizes inspect.signature without changing underlying wrapper execution

ファイル

  • NOTES.md
  • csx.json
  • requirements.txt
  • src/__init__.py
  • src/decorators.py
  • test/contract.py

ソースアーティファクトをダウンロード (tar.gz)

ソース

NOTES.md
# Notes on wrapt Universal Decorator & Monkey-Patching Contracts

## Existing CSX Solutions Found
`search_known_solution` returned sample `sha256:61d02a30076981ae851aad530bd2d9dbce05537be4411337993c75500740cdd6` ("Subclass the right object proxy base in wrapt 2.x so iteration works"), which focuses on `BaseObjectProxy` vs `ObjectProxy` dunder iteration changes in wrapt 2.x.
We selected a different core area: the `@wrapt.decorator` 4-argument signature protocol `(wrapped, instance, args, kwargs)`, instance pre-binding, monkey-patching hooks in `wrapt.wrap_function_wrapper`, custom decorator argument factories, and signature adaptation.

## What a Competent Model Would Have Written Instead
- Competent models reaching for `@wrapt.decorator` often inspect `instance` and write `if instance: return wrapped(instance, *args, **kwargs)` (or assume `args[0]` contains `self`), apply `@wrapt.decorator` to the `wrapper` argument of `wrapt.wrap_function_wrapper`, or pass custom configuration directly as keyword arguments to `@wrapt.decorator(prefix=...)`.

## Failure Mode (Loud vs Silent)
- Double-passing `instance` to `wrapped(instance, *args, **kwargs)` fails loudly with `TypeError: ... takes N positional arguments but N+1 were given`, whereas applying `@wrapt.decorator` to a `wrap_function_wrapper` hook fails silently with a green build because calling the patched method returns a `wrapt.FunctionWrapper` instance (truthy in boolean checks) rather than executing the target function and returning its value.
csx.json
{"case":{"caseId":"case:sha256:146f1ea397de419787dfe056ff9075ad18639932f410ab1b7361a80618d195e7","contract":["assert wrapt decorator passes instance separately and strips self or cls from positional args","assert wrapped is already bound so passing instance to wrapped(*args) raises TypeError","assert passing a @wrapt.decorator function to wrap_function_wrapper silently returns FunctionWrapper instead of the target return value","assert @wrapt.decorator rejects custom decorator keyword arguments and requires an outer factory function","assert enabled=False returns the unwrapped function while enabled=callable dynamically evaluates per invocation","assert @wrapt.adapter_factory customizes inspect.signature without changing underlying wrapper execution"],"goal":"Invoke wrapt universal decorators and monkey-patch wrappers with 4-arg signatures without double-binding instance or decorating patch hooks","kind":"HOW","packages":["pkg:pypi/wrapt@2.2.2"],"schemaVersion":1,"symbols":["wrapt.decorator","wrapt.wrap_function_wrapper","wrapt.adapter_factory","wrapt.FunctionWrapper"]},"contractCommand":["python","test/contract.py"],"environment":{"arch":"x64","ecosystem":"pypi","executionContext":"python","language":"python","os":"linux","packageManager":"pip","runtime":"python","schemaVersion":1},"license":"MIT-0","packages":["pkg:pypi/wrapt@2.2.2"],"schemaVersion":1,"symbols":["wrapt.decorator","wrapt.wrap_function_wrapper","wrapt.adapter_factory","wrapt.FunctionWrapper"],"verifierAdapter":"python@1"}
requirements.txt
wrapt==2.2.2
src/__init__.py
# wrapt decorator patterns and monkeypatching contract source
src/decorators.py
"""Wrapt universal decorator patterns, binding rules, and monkeypatching adapters.

Wrapt's universal decorator protocol uses a 4-argument signature:
    wrapper(wrapped, instance, args, kwargs)

Key behavioral rules:
1. `instance` separation: When decorating an instance method or class method,
   `instance` receives `self` or `cls`, and `args` has `self`/`cls` stripped.
2. `wrapped` binding: `wrapped` is ALREADY bound to `instance`. Calling
   `wrapped(*args, **kwargs)` is always required; passing `instance` explicitly
   double-passes the target and raises a TypeError.
3. Decorators with arguments: `@wrapt.decorator` only accepts (wrapper, enabled,
   adapter, proxy). Custom decorator arguments must use an outer factory function.
4. Monkey-patching: `wrapt.wrap_function_wrapper` expects a raw 4-arg callable,
   NOT a `@wrapt.decorator` wrapped object. Passing a decorated wrapper silently
   returns a FunctionWrapper instead of executing the wrapped target.
5. Signature adaptation: `@wrapt.adapter_factory` or `adapter=` customizes
   the advertised signature reported by `inspect.signature`.
"""

import inspect
import wrapt


@wrapt.decorator
def universal_passthrough(wrapped, instance, args, kwargs):
    """A standard wrapt decorator that inspects instance and passes args cleanly."""
    return wrapped(*args, **kwargs)


def prefix_decorator_factory(prefix="LOG"):
    """Correct pattern for a wrapt decorator with custom arguments."""
    @wrapt.decorator
    def wrapper(wrapped, instance, args, kwargs):
        result = wrapped(*args, **kwargs)
        return f"{prefix}: {result}"
    return wrapper


def raw_patch_wrapper(wrapped, instance, args, kwargs):
    """Raw 4-argument callable intended for wrapt.wrap_function_wrapper."""
    return wrapped(*args, **kwargs) * 2


@wrapt.decorator
def double_wrapped_patch(wrapped, instance, args, kwargs):
    """Common anti-pattern: applying @wrapt.decorator to a wrap_function_wrapper hook."""
    return wrapped(*args, **kwargs) * 2


@wrapt.adapter_factory
def drop_first_arg_adapter(wrapped):
    """Adapter factory that provides a signature omitting the first parameter."""
    sig = inspect.signature(wrapped)
    params = list(sig.parameters.values())[1:]
    new_sig = sig.replace(parameters=params)

    def prototype(*args, **kwargs):
        pass

    prototype.__signature__ = new_sig
    return prototype


@wrapt.decorator(adapter=drop_first_arg_adapter)
def inject_context_decorator(wrapped, instance, args, kwargs):
    """Decorator that injects a default context string as first argument."""
    return wrapped("default_context", *args, **kwargs)
test/contract.py
import inspect
import os
import sys
import types
import wrapt

sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))

from src.decorators import (
    double_wrapped_patch,
    inject_context_decorator,
    prefix_decorator_factory,
    raw_patch_wrapper,
    universal_passthrough,
)

# -----------------------------------------------------------------------------
# 1. Instance separation and argument stripping across call kinds
# -----------------------------------------------------------------------------
call_state = {}


@wrapt.decorator
def inspect_call(wrapped, instance, args, kwargs):
    call_state["instance"] = instance
    call_state["args"] = args
    call_state["kwargs"] = kwargs
    return wrapped(*args, **kwargs)


class Calculator:
    def add(self, a, b):
        return a + b

    @classmethod
    def multiply(cls, a, b):
        return a * b

    @staticmethod
    def negate(a):
        return -a


calc = Calculator()

# Standalone function
@inspect_call
def standalone_sub(a, b):
    return a - b


assert standalone_sub(10, 3) == 7
assert call_state["instance"] is None
assert call_state["args"] == (10, 3)

# Instance method: instance is calc, args has self stripped!
dec_add = inspect_call(calc.add)
assert dec_add(10, 3) == 13
assert call_state["instance"] is calc
assert call_state["args"] == (10, 3)  # self is NOT in args!

# Class method: instance is Calculator class, args has cls stripped!
dec_mul = inspect_call(Calculator.multiply)
assert dec_mul(4, 5) == 20
assert call_state["instance"] is Calculator
assert call_state["args"] == (4, 5)  # cls is NOT in args!

# Static method: instance is None
dec_neg = inspect_call(Calculator.negate)
assert dec_neg(42) == -42
assert call_state["instance"] is None
assert call_state["args"] == (42,)

# -----------------------------------------------------------------------------
# 2. Trap: Calling wrapped(instance, *args) raises TypeError
# Naive models assume wrapped is unbound when instance is present and try to pass instance.
# -----------------------------------------------------------------------------
@wrapt.decorator
def naive_instance_passer(wrapped, instance, args, kwargs):
    if instance is not None:
        # NAIVE ERROR: wrapped is ALREADY bound to instance!
        return wrapped(instance, *args, **kwargs)
    return wrapped(*args, **kwargs)


bound_bad_add = naive_instance_passer(calc.add)
try:
    bound_bad_add(10, 3)
    raise AssertionError("Expected TypeError: wrapped is already bound")
except TypeError as err:
    # Error message confirms double-passing instance:
    # "Calculator.add() takes 3 positional arguments but 4 were given"
    assert "takes" in str(err) and "positional argument" in str(err)

# -----------------------------------------------------------------------------
# 3. Trap: wrap_function_wrapper with @wrapt.decorator silently returns FunctionWrapper
# Passing a decorated wrapper instead of a raw 4-arg function corrupts return values without raising.
# -----------------------------------------------------------------------------
class TargetService:
    def compute(self, x):
        return x + 1


target_good = TargetService()
wrapt.wrap_function_wrapper(target_good, "compute", raw_patch_wrapper)
assert target_good.compute(5) == 12  # (5 + 1) * 2 = 12

target_bad = TargetService()
wrapt.wrap_function_wrapper(target_bad, "compute", double_wrapped_patch)
bad_result = target_bad.compute(5)

# SILENT TRAP: bad_result is NOT an int (12) -- it is a FunctionWrapper object!
assert isinstance(bad_result, wrapt.FunctionWrapper)
assert bad_result != 12
assert bool(bad_result) is True  # Truthiness test would deceptively pass

# -----------------------------------------------------------------------------
# 4. Trap: Custom arguments to @wrapt.decorator vs factory function
# -----------------------------------------------------------------------------
# Direct custom keyword argument to @wrapt.decorator raises TypeError immediately
try:
    @wrapt.decorator(prefix="CUSTOM")
    def bad_direct_args(wrapped, instance, args, kwargs):
        return wrapped(*args, **kwargs)

    raise AssertionError("Expected TypeError on unknown kwarg to wrapt.decorator")
except TypeError as err:
    assert "unexpected keyword argument 'prefix'" in str(err)

# Extra default parameter on wrapper called as factory raises IndexError
@wrapt.decorator
def flawed_factory_wrapper(wrapped, instance, args, kwargs, prefix="DEFAULT"):
    return f"{prefix}: {wrapped(*args, **kwargs)}"


try:
    @flawed_factory_wrapper(prefix="CUSTOM")
    def doomed_target():
        return "ok"

    raise AssertionError("Expected IndexError when invoking wrapper with kwargs")
except IndexError as err:
    assert "tuple index out of range" in str(err)

# Correct factory pattern works as expected
custom_dec = prefix_decorator_factory(prefix="VERIFIED")


@custom_dec
def greet(name):
    return f"Hello {name}"


assert greet("Alice") == "VERIFIED: Hello Alice"

# -----------------------------------------------------------------------------
# 5. Dynamic enabled flag: boolean vs callable predicate
# -----------------------------------------------------------------------------
# Static enabled=False returns the unwrapped function directly (no wrapper created)
def plain_fn():
    return "original"


@wrapt.decorator(enabled=False)
def inactive_wrapper(wrapped, instance, args, kwargs):
    return "interceptor"


disabled_dec = inactive_wrapper(plain_fn)
assert disabled_dec is plain_fn

# Callable enabled predicate evaluates per call
feature_flag = True


@wrapt.decorator(enabled=lambda: feature_flag)
def toggled_dec(wrapped, instance, args, kwargs):
    return f"INTERCEPTED: {wrapped(*args, **kwargs)}"


@toggled_dec
def query_value():
    return "data"


assert query_value() == "INTERCEPTED: data"
feature_flag = False
assert query_value() == "data"  # Bypasses wrapper body

# -----------------------------------------------------------------------------
# 6. Preserving and adapting signatures via wrapt.adapter_factory
# -----------------------------------------------------------------------------
# Default wrapt.decorator preserves the wrapped function's original signature
assert str(inspect.signature(standalone_sub)) == "(a, b)"
assert str(inspect.signature(greet)) == "(name)"

# Adapter factory modifies advertised inspect.signature
def endpoint_handler(ctx, x, y):
    return f"{ctx}: {x + y}"


adapted_endpoint = inject_context_decorator(endpoint_handler)

# Advertised signature omits the injected 'ctx' parameter
assert str(inspect.signature(adapted_endpoint)) == "(x, y)"
# Invocation injects 'default_context' and passes x, y
assert adapted_endpoint(10, 20) == "default_context: 30"

print("CONTRACT PASS: wrapt universal decorator binding, monkeypatching, and adapter contracts verified")

オリジンシーダー

csx-seed