Skip to content

Commit 8b1eeac

Browse files
committed
Eliminate the generator/profile cyclic import for real
The prior TYPE_CHECKING-guarded import wasn't a real runtime cycle, but CodeQL's py/unsafe-cyclic-import flagged it anyway, and inline codeql[] suppression comments didn't take for this query (still 4 findings after adding them). Simpler to actually remove the cycle: RampParams moves to its own core/ramp_params.py with no dependency on either generator.py or profile.py, so profile.py can import it directly instead of only under TYPE_CHECKING.
1 parent 3a9386e commit 8b1eeac

5 files changed

Lines changed: 24 additions & 29 deletions

File tree

‎invforge/core/generator.py‎

Lines changed: 3 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -9,31 +9,18 @@
99
from __future__ import annotations
1010

1111
import re
12-
from dataclasses import dataclass
1312
from typing import Literal
1413

15-
# Not a real runtime cycle: profile.py's reciprocal import of this module
16-
# is guarded by `if TYPE_CHECKING:` (see profile.py), which is False at
17-
# runtime, so Python never executes that import line. mypy resolves the
18-
# annotation-only cycle fine too, since every module here uses
19-
# `from __future__ import annotations`.
20-
from .profile import Profile # codeql[py/unsafe-cyclic-import]
21-
from .scenario import Scenario # codeql[py/unsafe-cyclic-import]
14+
from .profile import Profile
15+
from .ramp_params import RampParams
16+
from .scenario import Scenario
2217

2318
_RAMP_RE = re.compile(
2419
r"^linear-(?P<direction>drain|charge)-(?P<start>\d+(?:\.\d+)?)-to-"
2520
r"(?P<end>\d+(?:\.\d+)?)-(?P<duration>\d+(?:\.\d+)?)s$"
2621
)
2722

2823

29-
@dataclass(frozen=True)
30-
class RampParams:
31-
direction: Literal["drain", "charge"]
32-
start_pct: float
33-
end_pct: float
34-
duration_s: float
35-
36-
3724
def resolve_generated(name: str, profile: Profile) -> Scenario | None:
3825
"""None if `name` doesn't match the generator's naming convention, or
3926
the profile has no ramp_builder -- caller falls back to the static

‎invforge/core/profile.py‎

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,10 @@
88
from collections.abc import Callable
99
from dataclasses import dataclass, field
1010
from pathlib import Path
11-
from typing import TYPE_CHECKING
1211

12+
from .ramp_params import RampParams
1313
from .registers import RegisterDef
1414

15-
if TYPE_CHECKING:
16-
# Not a real runtime cycle -- this only ever executes for a type
17-
# checker (TYPE_CHECKING is False at runtime), and generator.py's
18-
# reciprocal import of Profile is fine to resolve after the fact
19-
# since every module here uses `from __future__ import annotations`.
20-
from .generator import RampParams # codeql[py/unsafe-cyclic-import]
21-
2215

2316
@dataclass(frozen=True)
2417
class Profile:

‎invforge/core/ramp_params.py‎

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
"""RampParams lives in its own module, separate from generator.py, so
2+
that profile.py (which needs the type for Profile.ramp_builder) doesn't
3+
have to import back into generator.py (which imports profile.py) --
4+
avoids a cyclic import rather than working around one.
5+
"""
6+
7+
from __future__ import annotations
8+
9+
from dataclasses import dataclass
10+
from typing import Literal
11+
12+
13+
@dataclass(frozen=True)
14+
class RampParams:
15+
direction: Literal["drain", "charge"]
16+
start_pct: float
17+
end_pct: float
18+
duration_s: float

‎invforge/core/scenario.py‎

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,7 @@
3535

3636
import yaml
3737

38-
# Not a real runtime cycle: profile.py never imports this module except
39-
# under `if TYPE_CHECKING:` (see profile.py), which doesn't execute at
40-
# runtime.
41-
from .profile import Profile # codeql[py/unsafe-cyclic-import]
38+
from .profile import Profile
4239
from .registers import DType, RegisterDef, normalize_scenario_value
4340

4441

‎invforge/profiles/sigenergy/firmwares/V100R001C21SPC116/ramps.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616

1717
from __future__ import annotations
1818

19-
from invforge.core.generator import RampParams
19+
from invforge.core.ramp_params import RampParams
2020

2121
_RATED_CAPACITY_KWH = 18.0 # matches this firmware's other synthetic fixtures' 30083 (gain 100 -> raw 1800)
2222

0 commit comments

Comments
 (0)