Skip to content

Commit b8c1600

Browse files
JarbasAlclaude
andauthored
fix: drop unhashable Session from lru_cache key (ovos-bus-client 2.x compat) (#60)
* fix: drop unhashable Session from lru_cache key ovos-bus-client 2.x makes Session unhashable (Session.__hash__ is None), so passing it as an lru_cache argument to _calc_padacioso_intent raised TypeError: unhashable type: 'Session' on every match attempt. Pass the two blacklist sets the matcher actually reads as frozensets (hashable) instead of the whole Session, restoring caching and matching under bus-client 2.x. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix: invalidate padacioso match cache on register/detach _calc_padacioso_intent is @lru_cache-keyed on the intent_container object, which is mutated in place by register/detach. After detaching an intent the cache returned the stale pre-detach match (no complete_intent_failure emitted), breaking the detach e2e tests. Clear the cache whenever a container is mutated. --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
1 parent 8d85875 commit b8c1600

1 file changed

Lines changed: 16 additions & 4 deletions

File tree

padacioso/opm.py

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,8 @@ def __detach_intent(self, intent_name):
147147
self.registered_intents.remove(intent_name)
148148
for lang in self.containers:
149149
self.containers[lang].remove_intent(intent_name)
150+
# the container was mutated; drop stale cached matches
151+
_calc_padacioso_intent.cache_clear()
150152

151153
def handle_detach_intent(self, message):
152154
"""Messagebus handler for detaching padacioso intent.
@@ -165,6 +167,8 @@ def __detach_entity(self, name, lang):
165167
"""
166168
if lang in self.containers:
167169
self.containers[lang].remove_entity(name)
170+
# the container was mutated; drop stale cached matches
171+
_calc_padacioso_intent.cache_clear()
168172

169173
def handle_detach_skill(self, message):
170174
"""Messagebus handler for detaching all intents for skill.
@@ -204,6 +208,8 @@ def _register_object(self, message, object_name, register_func):
204208
samples = [line.strip() for line in f.readlines()]
205209

206210
register_func(name, samples)
211+
# the container was mutated; drop stale cached matches
212+
_calc_padacioso_intent.cache_clear()
207213

208214
def register_intent(self, message):
209215
"""Messagebus handler for registering intents.
@@ -261,9 +267,14 @@ def calc_intent(self, utterances: List[str], lang: str = None,
261267
return None
262268

263269
sess = SessionManager.get(message)
270+
# Session is not hashable, so it cannot be an lru_cache key. Pass the
271+
# blacklists it carries as frozensets (hashable) instead.
272+
blacklisted_intents = frozenset(sess.blacklisted_intents or [])
273+
blacklisted_skills = frozenset(sess.blacklisted_skills or [])
264274

265275
intent_container = self.containers.get(lang)
266-
intents = [_calc_padacioso_intent(utt, intent_container, sess)
276+
intents = [_calc_padacioso_intent(utt, intent_container,
277+
blacklisted_intents, blacklisted_skills)
267278
for utt in utterances]
268279
intents = [i for i in intents if i is not None]
269280
# select best
@@ -285,7 +296,8 @@ def shutdown(self):
285296
@lru_cache(maxsize=128) # covers burst of multiple ASR hypotheses without thrashing
286297
def _calc_padacioso_intent(utt: str,
287298
intent_container: FallbackIntentContainer,
288-
sess: Session) -> \
299+
blacklisted_intents: frozenset = frozenset(),
300+
blacklisted_skills: frozenset = frozenset()) -> \
289301
Optional[PadaciosoIntent]:
290302
"""
291303
Try to match an utterance to an intent in an intent_container
@@ -295,8 +307,8 @@ def _calc_padacioso_intent(utt: str,
295307
try:
296308
intents = [i for i in intent_container.calc_intents(utt)
297309
if i is not None
298-
and i["name"] not in sess.blacklisted_intents
299-
and i["name"].split(":")[0] not in sess.blacklisted_skills]
310+
and i["name"] not in blacklisted_intents
311+
and i["name"].split(":")[0] not in blacklisted_skills]
300312
if len(intents) == 0:
301313
return None
302314
best_conf = max(x.get("conf", 0) for x in intents if x.get("name"))

0 commit comments

Comments
 (0)