mirror of
https://github.com/BerriAI/litellm.git
synced 2026-08-28 05:25:59 +00:00
* test: unshadow the module handles the F811 sweep left behind, and pin the two live tests that went red with it The F811 sweep in #37878 removed the fixture-local `import litellm` from four conftests, but the bare `import litellm.proxy.proxy_server` a few lines below still binds `litellm` as a function local, so `importlib.reload(litellm)` runs before the name is assigned and every test in those directories errors at setup. The `hasattr` guard on the line above already proves the module is loaded, so the import only ever bound the name. Drop it, and enable F823 in ruff-tests.toml, which flags all four sites at the failing line and would have blocked the sweep The same sweep renamed the `check_non_streaming_response` parameter but left one read of `completion`, which now resolves to `litellm.completion`, and removed an import whose side effect was the only thing making `litellm.proxy.proxy_server` reachable in the moderation hook test. That test already takes `monkeypatch`, so patch the router through it and stop leaking the router into later tests `test_content_policy_exception_openai` passed vacuously until #37887 turned it into a real `pytest.raises`, and OpenAI no longer rejects a lyrics prompt with a content policy error. Inject an AsyncOpenAI client whose transport answers with OpenAI's own `content_policy_violation` rejection so the mapping to ContentPolicyViolationError is exercised every run `test_async_create_batch` hit a 409 cancelling a batch OpenAI had already marked failed. The cancel step tolerated a completed batch but not a failed one. Fold both guards into one helper that tolerates a failed batch only when OpenAI's recorded error is the org's enqueued token limit, and prints the batch's errors so the reason is in the log either way * test: close the injected AsyncOpenAI client after the content policy test * chore(lint): ratchet TQ005 down by the global mutation this branch cleared * chore(lint): ratchet TQ005 to 2660 on the merged tree * chore(lint): ratchet TQ005 to 2561 on the merged tree * chore(lint): ratchet TQ005 to 2548 on the merged tree
66 lines
3.5 KiB
TOML
66 lines
3.5 KiB
TOML
# Lint config for the test tree, which ruff.toml excludes from `ruff check`.
|
|
#
|
|
# Every rule here catches a test that cannot fail. Rules land one at a time, each
|
|
# with its existing violations already fixed, so this list never needs a budget
|
|
# file or a ratchet.
|
|
#
|
|
# F821 a name that does not exist raises NameError, and a test body wrapped in
|
|
# `except Exception: pass` swallows that NameError and reports green
|
|
# B011 `assert False` inside `try:` raises AssertionError, which the `except
|
|
# Exception` below it catches. `pytest.fail` raises BaseException and escapes
|
|
# PT015 same site as B011, from the pytest ruleset
|
|
# B015 a bare `a == b` statement is evaluated and thrown away; the missing `assert`
|
|
# means the test checks nothing
|
|
# B018 a bare attribute access or literal, usually a call missing its parens
|
|
# PLW0127 `x = x` self-assignment, dead code that reads like a narrowing or a fixup
|
|
# PLR0133 comparison of two constants, e.g. `assert True == True`
|
|
# B017 `pytest.raises(Exception)` accepts the TypeError a refactor introduced just as
|
|
# readily as the rejection under test, so a crash reads as a pass. Narrow to the
|
|
# real type, or add `match=` where the code genuinely raises a bare Exception
|
|
# PT012 a `pytest.raises` block that runs on past the raising call. Everything after
|
|
# that call is dead, so an `assert` sitting there is never checked. Keep the
|
|
# block to the call itself and put the assertions below it
|
|
# PT011 `pytest.raises(Exception)` / `(ValueError)` / `(OSError)` with no `match=`. The
|
|
# block passes on any error that broad, so the TypeError a refactor introduced
|
|
# reads as the rejection under test. Pin the message the code actually raises
|
|
# PT014 the same `parametrize` case listed twice. The copy re-runs an assertion that
|
|
# already passed and adds no coverage, and it usually marks a case someone meant
|
|
# to vary and forgot to edit
|
|
# F811 a name bound twice where the first binding was never used. Mostly a repeated
|
|
# import, but the same rule is what catches a second `def test_x` silently
|
|
# replacing the first, and a local that shadows an import the module still calls
|
|
# PT017 an `assert` on the caught error inside `except`. Nothing runs the handler when
|
|
# the call stops raising, so the test goes green on the exact regression it was
|
|
# written to catch. `pytest.raises` fails when the call succeeds
|
|
# RUF043 a `match=` pattern carrying regex metacharacters in a plain string. `match=` is
|
|
# `re.search`, so a `.` copied out of an error message is a wildcard and the block
|
|
# accepts messages the author never meant to accept. Mark a real regex raw, wrap a
|
|
# literal message in `re.escape`, and the pattern says which one it is
|
|
# F823 a module-level name read inside a function that also binds it lower down. The
|
|
# later binding makes the name local for the whole body, so the read raises
|
|
# UnboundLocalError, and in an autouse fixture that takes every test in the
|
|
# directory down with it
|
|
#
|
|
# No target-version here on purpose: it resolves from requires-python (>=3.10), so
|
|
# 3.11-only builtins like BaseExceptionGroup are correctly flagged in a tree that
|
|
# still has to run on 3.10.
|
|
|
|
line-length = 120
|
|
|
|
lint.select = [
|
|
"F811",
|
|
"F821",
|
|
"B011",
|
|
"B015",
|
|
"B017",
|
|
"B018",
|
|
"PT011",
|
|
"PT012",
|
|
"PT014",
|
|
"PT015",
|
|
"PT017",
|
|
"PLR0133",
|
|
"PLW0127",
|
|
"RUF043",
|
|
"F823",
|
|
]
|