[codex] Fix numeric sequence candidate selection#114
Conversation
📝 WalkthroughWalkthroughSequence detection's numeric fallback in ChangesNumeric sequence detection fix
Estimated code review effort: 2 (Simple) | ~10 minutes Sequence Diagram(s)sequenceDiagram
participant Caller
participant SequenceDetector
participant Helper as _find_best_numeric_sequence_candidate
Caller->>SequenceDetector: detect_sequence(filename)
SequenceDetector->>SequenceDetector: re.finditer(numeric pattern)
SequenceDetector->>Helper: evaluate all numeric matches
loop for each numeric match
Helper->>Helper: _find_frames_by_numeric_pattern(match)
end
Helper-->>SequenceDetector: best candidate (match, frame_numbers)
SequenceDetector-->>Caller: Sequence(pattern, frame_numbers)
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
src/renderkit/core/sequence.py (1)
202-234: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick winRepeated full directory scans per numeric candidate.
_find_best_numeric_sequence_candidatecalls_find_frames_by_numeric_patternonce per numeric group in the filename, and each call performs its ownbase_path.iterdir()scan (Line 260). For filenames with several numeric tokens (e.g.shot_010_v003.1001.exr) sitting in directories with many sibling frames, this results in multiple full directory listings where one would suffice.Consider listing the directory once and reusing the sibling filenames across all candidate evaluations.
♻️ Suggested refactor
`@staticmethod` def _find_best_numeric_sequence_candidate( base_path: Path, filename: str, numeric_matches: list[re.Match[str]] ) -> Optional[tuple[re.Match[str], list[int]]]: ... + sibling_names = ( + [p.name for p in base_path.iterdir() if p.is_file()] if base_path.exists() else [] + ) candidates: list[tuple[re.Match[str], list[int]]] = [] for numeric_match in numeric_matches: frame_numbers = SequenceDetector._find_frames_by_numeric_pattern( - base_path, filename, numeric_match + sibling_names, filename, numeric_match ) if frame_numbers: candidates.append((numeric_match, frame_numbers))`@staticmethod` def _find_frames_by_numeric_pattern( - base_path: Path, filename: str, numeric_match: re.Match[str] + sibling_names: list[str], filename: str, numeric_match: re.Match[str] ) -> list[int]: ... frame_numbers: list[int] = [] start_pos, end_pos = numeric_match.span() prefix = filename[:start_pos] suffix = filename[end_pos:] - # Try to find files with same prefix/suffix but different numbers - if base_path.exists(): - padding = end_pos - start_pos - pattern_regex = re.compile( - rf"^{re.escape(prefix)}(\d{{{padding}}}){re.escape(suffix)}$" - ) - for file_path in base_path.iterdir(): - if file_path.is_file(): - match = pattern_regex.match(file_path.name) - if match: - try: - frame_num = int(match.group(1)) - frame_numbers.append(frame_num) - except ValueError: - continue + padding = end_pos - start_pos + pattern_regex = re.compile(rf"^{re.escape(prefix)}(\d{{{padding}}}){re.escape(suffix)}$") + for name in sibling_names: + match = pattern_regex.match(name) + if match: + try: + frame_numbers.append(int(match.group(1))) + except ValueError: + continue return sorted(frame_numbers)Also applies to: 236-270
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/renderkit/core/sequence.py` around lines 202 - 234, _{}_Repeated directory scans are happening in SequenceDetector._find_best_numeric_sequence_candidate because each numeric candidate re-invokes _find_frames_by_numeric_pattern, which walks base_path repeatedly. Refactor the candidate evaluation to list the directory once, cache the sibling filenames, and pass that shared data into the per-candidate frame detection logic so each numeric_match can be scored without additional base_path.iterdir() calls.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@src/renderkit/core/sequence.py`:
- Around line 202-234: _{}_Repeated directory scans are happening in
SequenceDetector._find_best_numeric_sequence_candidate because each numeric
candidate re-invokes _find_frames_by_numeric_pattern, which walks base_path
repeatedly. Refactor the candidate evaluation to list the directory once, cache
the sibling filenames, and pass that shared data into the per-candidate frame
detection logic so each numeric_match can be scored without additional
base_path.iterdir() calls.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 8fa35a81-4f70-4070-9fdd-0c9489a37fef
📒 Files selected for processing (2)
src/renderkit/core/sequence.pytests/test_sequence.py
|



Summary
shot_v001.0001.exrlayer1,2k, versions, or shot IDs as frame numbersRoot cause
Direct numeric detection used to grab the first digit group, while PR #113 tried always using the last digit group. Both are too broad for production filenames with shot IDs, versions, resolution tags, or layer tags.
This keeps the fallback intentionally narrow: direct numeric filenames are treated as frame sequences only when the candidate token looks like
.<3-5 digits>., and the last such token is used as the frame number.Verification
uv --system-certs run --extra dev python -m pytest tests/test_sequence.py -quv --system-certs run --extra dev ruff check src/renderkit/core/sequence.py tests/test_sequence.pyuv --system-certs run --extra dev ruff format --check src/renderkit/core/sequence.py tests/test_sequence.pyuv --system-certs run --extra dev python -m pytest -qFixes #94