fix(triggers): use absolute import for constants module

The component scanner (lfx.interface.components._process_single_module)
discovers a component class, instantiates it, and then re-evaluates the
class's *source code* via lfx.custom.validate.create_class to extract
its frontend template. That re-evaluation runs the module body in a
flat namespace — there is no package context, so relative imports
('from .constants import …') resolve to a non-existent top-level
'constants' module and raise ModuleNotFoundError.

The exception is swallowed silently inside _process_single_module
(it appends to a per-module failed_count and continues), so the
scanner returns an EMPTY component dict for the triggers package and
the entire category disappears from the frontend palette — exactly
the symptom: build_component_index / LFX_DEV scans complete with no
'triggers' key in the result.

Fix: switch to absolute import (lfx.components.triggers.constants).
Mirrors the convention used by every other built-in component;
relative imports of sibling helpers are not safe in this codebase
because of how the validator re-evaluates the source.

Verified via _process_single_module('lfx.components.triggers.cron_trigger'):
returns ('triggers', {'CronTrigger': <template>}) — the category now
surfaces to the frontend. 63/63 unit tests still pass.
This commit is contained in:
Tarcio
2026-05-21 14:55:42 -03:00
parent d153be2801
commit ed9fedfa28

View File

@ -30,6 +30,13 @@ from __future__ import annotations
from datetime import datetime, timezone
from lfx.components.triggers.constants import (
COMMON_TIMEZONES,
DEFAULT_CRON_EXPRESSION,
DEFAULT_MAX_ATTEMPTS,
DEFAULT_TIMEZONE,
MAX_ATTEMPTS_LIMIT,
)
from lfx.custom.custom_component.component import Component
from lfx.field_typing.range_spec import RangeSpec
from lfx.io import (
@ -41,14 +48,6 @@ from lfx.io import (
)
from lfx.schema.message import Message
from .constants import (
COMMON_TIMEZONES,
DEFAULT_CRON_EXPRESSION,
DEFAULT_MAX_ATTEMPTS,
DEFAULT_TIMEZONE,
MAX_ATTEMPTS_LIMIT,
)
class CronTriggerComponent(Component):
display_name = "Cron Trigger"