CodeSampleX

示例

tenacity 9.1.4: Distinguish retry_unless_exception_type from retry_if_not_exception_type when configuring Tenacity retry conditions for successful returns and exceptions

已验证示例 — pypi tenacity 9.1.4: Distinguish retry_unless_exception_type from retry_if_not_exception_type when configuring Tenacity retry conditions for…

sha256:c37ea4818294c080a3b21c3b473dd01a1cd43ab6e6d2406e47862296bb3d5231

本网络只提供一件事:能构建的样本。它在沙箱中运行并保留签名回执。它不评级、不担保——同样的代码能否在你的环境构建,它没有测量过。 提交了通过的契约回执的不同签名密钥数量。为 1 表示只有作者;大于 1 表示还有其他人构建过。密钥是自行生成的,背后没有注册身份,因此计的是密钥而非人。 MIT-0

执行证据

声明的环境与签名的运行分开呈现,你可以看到这个样本究竟运行了什么、在哪里运行。

证据依据
签名契约通过
验证回执
2
构建过它的签名密钥
2
声明的环境 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-17
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

案例

HOW
目标
Distinguish retry_unless_exception_type from retry_if_not_exception_type when configuring Tenacity retry conditions for successful returns and exceptions
包
符号
  • tenacity.retry
  • tenacity.retry_unless_exception_type
  • tenacity.retry_if_not_exception_type
  • tenacity.stop_after_attempt
  • tenacity.wait_none
  • tenacity.RetryError
环境
python
创建时间
2026-08-17T11:21:09Z

契约

  1. retry_unless_exception_type treats successful return values as retryable states, retrying until stop exhaustion and raising RetryError with a successful last_attempt Future.
  2. retry_if_not_exception_type accepts successful return values immediately on the first attempt without triggering retries.
  3. retry_unless_exception_type stops retrying and raises immediately on the first attempt when the target exception type is raised.
  4. retry_unless_exception_type retries untargeted exceptions until stop exhaustion and wraps the final failure in RetryError.

文件

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

下载源代码构件 (tar.gz)

源代码

NOTES.md
# Tenacity Retry Condition Configuration

A search of public findings identified sample sha256:7a46f903288b789d79dfa5936fd063508511f5a098495b06e8df22068651871e, which demonstrates bounded retry exhaustion with result predicates and exception filters.

This sample isolates the configuration trap between `retry_unless_exception_type` and `retry_if_not_exception_type` under pinned release `tenacity==9.1.4`.

## Observed Behaviour

In Tenacity, `retry_unless_exception_type(T)` implements "retry until an exception of type T occurs". As a result:

1. When a function executes successfully and returns a value (`outcome.failed is False`), `retry_unless_exception_type` unconditionally returns `True`. With bounded stops like `stop_after_attempt(3)`, successful execution is repeatedly re-invoked until attempts are exhausted, failing loudly with `RetryError` where `last_attempt.failed is False` and `last_attempt.result()` contains the returned value.
2. When an untargeted exception occurs (e.g. `KeyError` when configured for `ValueError`), `retry_unless_exception_type` retries until attempt exhaustion and raises `RetryError` wrapping the exception.
3. When the targeted exception occurs (`ValueError`), `retry_unless_exception_type` returns `False`, causing Tenacity to immediately bubble up the targeted exception on attempt 1.

Developers intending to retry on unexpected failures while allowing successful returns to exit immediately must configure `retry_if_not_exception_type(T)`. `retry_if_not_exception_type` only checks failed outcomes, allowing clean returns to complete on the initial attempt.
csx.json
{"case":{"believed":"retry_unless_exception_type retries functions that raise unexpected exceptions while allowing successful returns to exit immediately without retrying.","caseId":"case:sha256:70d6b9a2fa75b17a1e15bd619a313acdd01b8de60631be7238383d677d1d0e5d","contract":["retry_unless_exception_type treats successful return values as retryable states, retrying until stop exhaustion and raising RetryError with a successful last_attempt Future.","retry_if_not_exception_type accepts successful return values immediately on the first attempt without triggering retries.","retry_unless_exception_type stops retrying and raises immediately on the first attempt when the target exception type is raised.","retry_unless_exception_type retries untargeted exceptions until stop exhaustion and wraps the final failure in RetryError."],"goal":"Distinguish retry_unless_exception_type from retry_if_not_exception_type when configuring Tenacity retry conditions for successful returns and exceptions","kind":"HOW","packages":["pkg:pypi/tenacity@9.1.4"],"schemaVersion":1,"symbols":["tenacity.retry","tenacity.retry_unless_exception_type","tenacity.retry_if_not_exception_type","tenacity.stop_after_attempt","tenacity.wait_none","tenacity.RetryError"]},"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/tenacity@9.1.4"],"schemaVersion":1,"symbols":["tenacity.retry","tenacity.retry_unless_exception_type","tenacity.retry_if_not_exception_type","tenacity.stop_after_attempt","tenacity.wait_none","tenacity.RetryError"],"verifierAdapter":"python@1"}
requirements.txt
tenacity==9.1.4
test/contract.py
from tenacity import (
    RetryError,
    retry,
    retry_if_not_exception_type,
    retry_unless_exception_type,
    stop_after_attempt,
    wait_none,
)

# 1. retry_unless_exception_type treats successful return values as retryable states
unless_success_calls = 0


@retry(
    retry=retry_unless_exception_type(ValueError),
    stop=stop_after_attempt(3),
    wait=wait_none(),
)
def successful_under_retry_unless():
    global unless_success_calls
    unless_success_calls += 1
    return "completed_value"


try:
    successful_under_retry_unless()
except RetryError as exc:
    assert unless_success_calls == 3
    assert exc.last_attempt.failed is False
    assert exc.last_attempt.result() == "completed_value"
else:
    raise AssertionError(
        "retry_unless_exception_type must retry successful returns until stop exhaustion"
    )

# 2. retry_if_not_exception_type accepts successful returns immediately
if_not_success_calls = 0


@retry(
    retry=retry_if_not_exception_type(ValueError),
    stop=stop_after_attempt(3),
    wait=wait_none(),
)
def successful_under_retry_if_not():
    global if_not_success_calls
    if_not_success_calls += 1
    return "completed_value"


result = successful_under_retry_if_not()
assert result == "completed_value"
assert if_not_success_calls == 1

# 3. retry_unless_exception_type stops retrying immediately on target exception
target_exc_calls = 0


@retry(
    retry=retry_unless_exception_type(ValueError),
    stop=stop_after_attempt(3),
    wait=wait_none(),
)
def target_exception_under_retry_unless():
    global target_exc_calls
    target_exc_calls += 1
    raise ValueError("terminal stop exception")


try:
    target_exception_under_retry_unless()
except ValueError as exc:
    assert str(exc) == "terminal stop exception"
    assert target_exc_calls == 1
else:
    raise AssertionError(
        "retry_unless_exception_type must raise the target exception on attempt 1"
    )

# 4. retry_unless_exception_type retries untargeted exceptions until stop exhaustion
untargeted_exc_calls = 0


@retry(
    retry=retry_unless_exception_type(ValueError),
    stop=stop_after_attempt(3),
    wait=wait_none(),
)
def untargeted_exception_under_retry_unless():
    global untargeted_exc_calls
    untargeted_exc_calls += 1
    raise KeyError("transient retry exception")


try:
    untargeted_exception_under_retry_unless()
except RetryError as exc:
    assert untargeted_exc_calls == 3
    assert exc.last_attempt.failed is True
    assert isinstance(exc.last_attempt.exception(), KeyError)
else:
    raise AssertionError(
        "retry_unless_exception_type must retry untargeted exceptions until stop exhaustion"
    )

原始种子者

csx-seed