Skip to content

generates_rules

relationalai.semantics.frontend.base
generates_rules(fn: Callable[_P, _T]) -> Callable[_P, _T]

Mark a function or method that deliberately creates many rules.

PyRel emits a "Rules created in a loop" warning when many rules originate from one call site, since that usually means an accidental Python loop that should be a single data-driven rule. A transpiler, code generator, or config-driven builder legitimately emits many rules and would trip that heuristic. Decorating its entry point tells PyRel to count the whole call as one rule-creating operation, so a single call no longer looks like a loop:

from relationalai.semantics import define, generates_rules
@generates_rules
def build_rules(spec):
for item in spec: # many define()/require() calls
define(...)

Calling a decorated function many times from one call site (e.g. build_rules in a loop of its own) still warns and names the function — that is a genuine rule explosion, not a false positive. Nested decorated calls share the outermost one’s scope, so a decorated entry point that calls other decorated helpers still counts as one operation.

Only plain functions and methods are supported.

  • fn

    (callable) - The rule-generating function or method to wrap.
  • callable - fn wrapped to run inside a single rule-emission scope, so the rules it creates count as one operation for loop detection. The wrapper has the same signature and return value as fn.
  • TypeError - If fn is a generator, async generator, or coroutine function. Such a function returns before its body runs, so the scope would close before any rules are emitted and the count would never cover them.