feat: add global tinctures support via tavern-global-cfg (fixes #969)#1033
feat: add global tinctures support via tavern-global-cfg (fixes #969)#1033devimano2011 wants to merge 13 commits intotaverntesting:masterfrom
Conversation
…n_stage (fixes taverntesting#969) - step 3/3method Merge global tinctures from test config to fix issue taverntesting#969.
📝 WalkthroughWalkthroughThe changes extend the test configuration structure to support globally configured tinctures. A new Changes
Estimated code review effort🎯 2 (Simple) | ⏱️ ~8 minutes 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Review rate limit: 7/8 reviews remaining, refill in 7 minutes and 30 seconds.Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@tavern/_core/pytest/config.py`:
- Around line 36-38: The dataclass defines the field tinctures with a default
before the non-default tavern_internal, causing a dataclass field ordering
TypeError; fix by reordering or giving tavern_internal a default. Specifically,
in the dataclass that declares tinctures and tavern_internal, move the
tavern_internal field above tinctures (so tavern_internal is declared before
tinctures) or assign a default/default_factory to tavern_internal so all fields
with defaults follow non-default fields.
In `@tavern/_core/pytest/util.py`:
- Line 203: At config-load time, normalize global_cfg_dict["tinctures"] before
assigning to tinctures: if the value is a dict wrap it into a single-element
list, if it is None use an empty list, if it is a list validate that every
element is a mapping/dict and raise a TypeError (or ValueError) for any other
type; update the assignment that currently reads
tinctures=global_cfg_dict.get("tinctures", []) to perform these checks and
normalization so downstream code that iterates tinctures always sees a list of
dicts.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 5b4fc8db-5c6f-4633-83ad-16bee77d2bbe
📒 Files selected for processing (3)
tavern/_core/pytest/config.pytavern/_core/pytest/util.pytavern/_core/run.py
| tinctures: list = dataclasses.field(default_factory=list) | ||
|
|
||
| tavern_internal: TavernInternalConfig |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
cat -n tavern/_core/pytest/config.py | head -60Repository: taverntesting/tavern
Length of output: 2442
🏁 Script executed:
cd tavern && python3 -c "from _core.pytest.config import TestConfig; print('Import successful')" 2>&1Repository: taverntesting/tavern
Length of output: 462
🏁 Script executed:
python3 << 'EOF'
import dataclasses
`@dataclasses.dataclass`(frozen=True)
class TavernInternalConfig:
pytest_hook_caller: object
backends: dict
`@dataclasses.dataclass`(frozen=True)
class TestConfig:
variables: dict
strict: object
follow_redirects: bool
stages: list
tinctures: list = dataclasses.field(default_factory=list)
tavern_internal: TavernInternalConfig
print("No error - dataclass defined successfully")
EOFRepository: taverntesting/tavern
Length of output: 637
Dataclass field ordering is invalid and prevents module import.
Line 36 introduces a field with a default value before the non-defaulted field at line 38, which violates Python dataclass field ordering rules. This raises a TypeError at class definition time.
Proposed fix
variables: dict
strict: StrictLevel
follow_redirects: bool
stages: list
- tinctures: list = dataclasses.field(default_factory=list)
-
tavern_internal: TavernInternalConfig
+ tinctures: list = dataclasses.field(default_factory=list)🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@tavern/_core/pytest/config.py` around lines 36 - 38, The dataclass defines
the field tinctures with a default before the non-default tavern_internal,
causing a dataclass field ordering TypeError; fix by reordering or giving
tavern_internal a default. Specifically, in the dataclass that declares
tinctures and tavern_internal, move the tavern_internal field above tinctures
(so tavern_internal is declared before tinctures) or assign a
default/default_factory to tavern_internal so all fields with defaults follow
non-default fields.
| backends=_load_global_backends(pytest_config), | ||
| ), | ||
| stages=global_cfg_dict.get("stages", []), | ||
| tinctures=global_cfg_dict.get("tinctures", []), |
There was a problem hiding this comment.
Normalise global tinctures shape at config load time.
Line 203 assumes a list shape; a single mapping-form tincture will later be iterated as keys and fail at runtime. Please coerce dict -> [dict] (and reject unsupported types) here.
💡 Proposed fix
- global_cfg = TestConfig(
+ raw_tinctures = global_cfg_dict.get("tinctures", [])
+ if raw_tinctures is None:
+ tinctures = []
+ elif isinstance(raw_tinctures, list):
+ tinctures = raw_tinctures
+ elif isinstance(raw_tinctures, dict):
+ tinctures = [raw_tinctures]
+ else:
+ raise exceptions.BadSchemaError(
+ f"Badly formatted 'tinctures' block in global config: {type(raw_tinctures)}"
+ )
+
+ global_cfg = TestConfig(
variables=variables,
strict=_load_global_strictness(pytest_config),
follow_redirects=_load_global_follow_redirects(pytest_config),
tavern_internal=TavernInternalConfig(
pytest_hook_caller=pytest_config.hook,
backends=_load_global_backends(pytest_config),
),
stages=global_cfg_dict.get("stages", []),
- tinctures=global_cfg_dict.get("tinctures", []),
+ tinctures=tinctures,
)🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@tavern/_core/pytest/util.py` at line 203, At config-load time, normalize
global_cfg_dict["tinctures"] before assigning to tinctures: if the value is a
dict wrap it into a single-element list, if it is None use an empty list, if it
is a list validate that every element is a mapping/dict and raise a TypeError
(or ValueError) for any other type; update the assignment that currently reads
tinctures=global_cfg_dict.get("tinctures", []) to perform these checks and
normalization so downstream code that iterates tinctures always sees a list of
dicts.
fix: move tinctures field before tavern_internal to fix dataclass ordering TypeError
…es helper with type validation and normalization Add function to normalize tinctures configuration value.
fix: move tinctures field after tavern_internal to fix dataclass TypeError
michaelboulton
left a comment
There was a problem hiding this comment.
Please also:
- Add some unit tests (eg, that call run_test and ensure that the 'global' tinctures are called)
- Add integration tests if possible (though this might be a bit difficult to do?)
- Update the docs in external_code.md
| # Merge global tinctures from test config (fixes #969) | ||
| from tavern._core.extfunctions import get_wrapped_response_function |
There was a problem hiding this comment.
Make this import global and remove the comment
This file contains unit tests for global tinctures support using Tavern. It includes tests for tinctures normalization, merging global tinctures with stage tinctures, and handlingtest: add unit tests for global tinctures normalization and run_stage merging of invalid types.
Correct encoding issues and improve formatting for clarity.
Merge global tinctures from test config to stage tinctures.
Refactor patch statements to use context manager for better readability.
Fixes #969
Problem
Tinctures could only be applied per-test/stage. Users could not apply a tincture globally to all tests via
tavern-global-cfg, despite variables and stages already supporting this.Solution
This PR adds global tinctures support across 3 files:
tavern/_core/pytest/config.py- Addedtinctures: listfield toTestConfigdataclasstavern/_core/pytest/util.py- Loadstincturesfrom global config files (same asstagesandvariables)tavern/_core/run.py- Merges global tinctures into stage tinctures inrun_stage()Usage
Users can now add global tinctures in their
tavern-global-cfgfile:Summary by CodeRabbit