API Reference
The entire implementation is a C extension (conditional_method._c); cfg is a thin
import shim.
cfg module
from conditional_method import (
cfg,
if_,
cm,
cfg_attr,
assert_all_true,
_get_failed,
debug,
debug_enabled,
)
@cfg(condition=...)
Conditional method selection. Aliases: @cm, @if_
— all three are the same object (cm is if_ is cfg
is True).
condition: bool | Callable[[Callable], bool]— required.- Use as a factory (
@cfg(condition=...)) or directly (cfg(func, condition=...)).
@cfg_attr(condition=..., decorators=[...])
Conditionally apply decorators.
condition: bool | Callable[[Callable], bool]— required.decorators: Sequence[Callable]— applied in order when true.
debug(message) / debug_enabled() -> bool
Opt-in C debug logging, gated by the __conditional_method_debug__
environment variable (any value other than "false" enables it).
export __conditional_method_debug__=true
_get_mod_qual_func_name(func) -> str
Internal helper returning module.qualname for a function, unwrapping
__wrapped__ / __func__ / fget as needed. Raises TypeError when no
name can be determined.
assert_all_true() -> None
Eager module-level validation. Selection is per name, so a decorated name fails only when all of its candidate implementations are false; a single true candidate is enough.
Raises TypeError naming every decorated name that ended up as a
_TypeErrorRaiser with no condition=True winner (i.e. every name whose
candidates were all false). A name with at least one true candidate is never
reported. Returns None when every decorated name is satisfied.
Call it as the last line of a config/feature-flag module to fail fast at import time instead of at first call:
from conditional_method import cfg, assert_all_true
# One true candidate is enough, so `work` is NOT reported.
@cfg(condition=ENV == "production")
def work(): ...
@cfg(condition=ENV == "development")
def work(): ...
# Every candidate for this name is false, so `broken` IS reported.
@cfg(condition=False)
def broken(): ...
assert_all_true() # TypeError naming `broken` only
_get_failed() -> list[str]
Returns the list of qualified names whose decorated condition ended up with
no true winner (i.e. that became a _TypeErrorRaiser; empty when all
conditions are true). Useful for introspection and tests; it is what
assert_all_true() checks under the hood.
The recorded failures are append-only per name: _failed_qualnames
grows as false-only names are decorated and is not wiped when a raiser is
created or called. A name is removed from the list only when a later
condition=True winner for that same name resolves it (or when the set is
cleared explicitly, e.g. conditional_method._c._failed_qualnames.clear()).
This means assert_all_true()/_get_failed() report every failing name
across the module/process, not just the most recent one.
conditional_method._c internals
Exposed for testing only (names prefixed with _ are not part of the
public API):
| Name | Purpose |
|---|---|
_cm_cache / _cfg_attr_cache |
module-level implementation caches; values are weakrefs to true-condition winners (and strong refs to _TypeErrorRaiser placeholders), so they do not pin functions/modules alive after their class is collected. Swept of dead entries once they exceed an internal high-water mark |
_TypeErrorRaiser |
placeholder object raising TypeError on call/__set_name__ |
_CfgCallable |
callable heap type wrapping the module aliases (cm._cache) |
_raise_exec |
create a _TypeErrorRaiser |
_cm_wrapper / cfg_attr_wrapper |
internal decorator wrappers |
_failed_qualnames |
append-only set of names with no true winner (backing _get_failed/assert_all_true) |
set_alloc_fail_count |
test-only (PY_CFG_TESTING builds) allocation-failure injection |
Errors
| Situation | Raised |
|---|---|
@cfg with no condition |
TypeError |
@cfg used without brackets |
TypeError |
| no condition true at class build | TypeError: None of the conditions is true for ... |
condition callable raises TypeError |
TypeError: Error calling \condition` for ...` |
cfg_attr with a non-sequence decorators |
TypeError: decorators must be a sequence |
cfg_attr with no condition |
ValueError / TypeError |
See Errors for details.