Skip to content

fix: coerce condition predicate result to bool before comparing to target#741

Open
gaoflow wants to merge 1 commit into
pytransitions:masterfrom
gaoflow:fix-condition-bool-coercion
Open

fix: coerce condition predicate result to bool before comparing to target#741
gaoflow wants to merge 1 commit into
pytransitions:masterfrom
gaoflow:fix-condition-bool-coercion

Conversation

@gaoflow

@gaoflow gaoflow commented Jun 24, 2026

Copy link
Copy Markdown

Summary

Condition.check() used strict equality (==) to compare the predicate
return value against self.target (True or False). This silently
fails for any non-bool truthy or falsy value because Python's ==
operator only considers 0/False and 1/True as equal — all other
truthy/falsy values compare unequal:

'yes' == True   # False  ← should pass a conditions= callback
[1,2] == True   # False  ← should pass a conditions= callback
''    == False  # False  ← should pass an unless= callback
None  == False  # False  ← should pass an unless= callback

Reproducer:

from transitions import Machine

class Model:
    def my_cond(self):
        return "yes"   # truthy, non-bool

m = Model()
machine = Machine(model=m, states=["A", "B"],
                  transitions=[{"trigger": "go", "source": "A",
                                 "dest": "B", "conditions": "my_cond"}],
                  initial="A")
m.go()
print(m.state)   # prints 'A'  ← expected 'B'

Fix

Wrap the predicate result in bool() before the == self.target
comparison, matching how Python's if-statement handles truthiness.
The same bug was present in AsyncCondition.check().

All 71 existing tests pass.

…rget

Condition.check() compared the predicate return value directly with
self.target using ==, which fails for non-bool truthy/falsy values:

    'yes' == True   → False  (should pass a truthy condition)
    [1,2] == True   → False  (should pass a truthy condition)
    ''    == False  → False  (should pass an unless condition)
    None  == False  → False  (should pass an unless condition)

Python's == operator only considers 0/False and 1/True as equal;
any other truthy or falsy value compares unequal to True or False.

Fix by wrapping the predicate result in bool() before the comparison,
mirroring how Python's if-statement handles truthiness. The same
one-liner bug existed in AsyncCondition.check().
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant