Generate audiobooks from EPUBs, PDFs and text with synchronized captions.
This report summarizes scanner evidence for denizsafak/abogen, a Python project with 6,107 GitHub stars. SynthScan examined 86,432 lines of code across 309 source files, recording 2320 pattern matches distributed across 18 syntactic categories. The legacy adjusted pattern signal is 39.6 (High pattern signal); it is not an authorship estimate.
Use the findings to ask whether maintainers can explain intent, verify dependencies, simplify unnecessary scaffolding, and focus review effort. Risk Payload v1 adds ownership, supply-chain, over-engineering, and review-effort vectors when available. These are prompts for human verification, not probabilities, security findings, or measured maintenance costs.
Use each vector to guide manual verification of the underlying findings.
Can maintainers explain intent, assumptions, and trade-offs? 1245 finding(s).
Are imports declared and package/API names verified? 406 finding(s).
Are wrappers, guards, and repeated structures necessary? 1731 finding(s).
Which changes need focused human review? 2320 finding(s).
This chart tracks the legacy adjusted pattern score across scan runs. Changes can reflect source changes, scan coverage, or detector/scoring versions; they do not measure AI adoption or prove that a team refactored code. Compare runs only when their scoring versions are compatible. The dashed line tracks the raw pattern-hit count.
Groups findings by configured severity weight. Severity is not a confidence estimate, security rating, or proof that a package is missing. Verify imports against the project's manifests and inspect each finding in its local design context.
This horizontal bar chart shows where configured pattern scores accumulate across directories. Treat the bars as locations to inspect, not as evidence of authorship or code quality. Use the file-level findings to decide whether a directory needs a focused ownership, dependency, complexity, or review check.
The scanner identified 2320 distinct pattern matches across 18 syntactic categories. Each entry below represents a discrete location in the source code where the engine recorded a detector match to inspect in context. Expand any category row to inspect the individual file paths, line numbers, code snippets, and the lexical context (CODE, COMMENT, or STRING) in which each match was detected.
Reading the findings table: The Severity column indicates the configured finding weight (CRITICAL / HIGH / MEDIUM / LOW). The Context column identifies whether the match occurred inside executable code, an inline comment, or a string literal — legacy comment-context matches receive a ×1.5 score weight. The ⚡ bolt icon marks clustered matches: three or more patterns within a 10-line window, each receiving an additional ×1.5 density multiplier under the legacy scoring model.
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | plugins/supertonic/__init__.py | 35 | def _load_supertonic_pipeline(language: Any = None) -> Any: | CODE |
| LOW | plugins/supertonic/pipeline.py | 83 | def _parse_unsupported_characters(error: BaseException) -> list[str]: | CODE |
| LOW | plugins/supertonic/pipeline.py | 114 | def _remove_unsupported_characters(text: str, unsupported: Iterable[str]) -> str: | CODE |
| LOW | plugins/supertonic/pipeline.py | 123 | def _configure_supertonic_gpu() -> None: | CODE |
| LOW | tests/test_voice_utils.py | 16 | def test_empty_returns_fallback(self): | CODE |
| LOW | tests/test_voice_utils.py | 19 | def test_supertonic_uppercase(self): | CODE |
| LOW | tests/test_voice_utils.py | 39 | def test_formula_uses_fallback(self): | CODE |
| LOW | tests/test_voice_utils.py | 42 | def test_both_empty_uses_default(self): | CODE |
| LOW | tests/test_epub_heuristic_nav.py | 31 | def test_heuristic_nav_discovery(self): | CODE |
| LOW | tests/test_opds_import_metadata_mapping.py | 6 | def test_opds_metadata_overrides_maps_author_and_subtitle() -> None: | CODE |
| LOW | tests/test_opds_import_metadata_mapping.py | 29 | def test_opds_metadata_overrides_accepts_author_string() -> None: | CODE |
| LOW⚡ | tests/test_kokoro_plugin.py | 108 | def test_plugin_loads_successfully(self, kokoro_plugin_dir: Path) -> None: | CODE |
| LOW⚡ | tests/test_kokoro_plugin.py | 114 | def test_plugin_has_valid_manifest(self, kokoro_plugin_dir: Path) -> None: | CODE |
| LOW⚡ | tests/test_kokoro_plugin.py | 123 | def test_plugin_has_model_requirements(self, kokoro_plugin_dir: Path) -> None: | CODE |
| LOW⚡ | tests/test_kokoro_plugin.py | 129 | def test_plugin_manifest_capabilities(self, kokoro_plugin_dir: Path) -> None: | CODE |
| LOW⚡ | tests/test_kokoro_plugin.py | 134 | def test_plugin_manifest_engine(self, kokoro_plugin_dir: Path) -> None: | CODE |
| LOW⚡ | tests/test_kokoro_plugin.py | 158 | def test_engine_satisfies_protocol(self, kokoro_plugin_dir: Path, host_context: HostContext) -> None: | CODE |
| LOW | tests/test_kokoro_plugin.py | 222 | def test_language_for_code_fallbacks(self) -> None: | CODE |
| LOW | tests/test_kokoro_plugin.py | 229 | def test_language_for_voice_id(self) -> None: | CODE |
| LOW⚡ | tests/test_pronunciation.py | 34 | def test_skips_entries_without_pronunciation(self): | CODE |
| LOW⚡ | tests/test_pronunciation.py | 40 | def test_skips_entries_without_token(self): | CODE |
| LOW⚡ | tests/test_pronunciation.py | 46 | def test_deduplication_by_casefold(self): | CODE |
| LOW⚡ | tests/test_pronunciation.py | 56 | def test_longer_token_sorted_first(self): | CODE |
| LOW⚡ | tests/test_pronunciation.py | 67 | def test_normalized_fallback_to_entity_token(self): | CODE |
| LOW⚡ | tests/test_pronunciation.py | 74 | def test_pattern_is_case_insensitive(self): | CODE |
| LOW⚡ | tests/test_pronunciation.py | 82 | def test_non_mapping_items_skipped(self): | CODE |
| LOW⚡ | tests/test_pronunciation.py | 115 | def test_skips_without_sentence(self): | CODE |
| LOW⚡ | tests/test_pronunciation.py | 121 | def test_skips_without_choice(self): | CODE |
| LOW⚡ | tests/test_pronunciation.py | 127 | def test_skips_when_no_matching_option(self): | CODE |
| LOW⚡ | tests/test_pronunciation.py | 189 | def test_possessive_preserved(self): | CODE |
| LOW⚡ | tests/test_pronunciation.py | 196 | def test_usage_counter_increments(self): | CODE |
| LOW⚡ | tests/test_pronunciation.py | 204 | def test_case_insensitive_match(self): | CODE |
| LOW | tests/test_pronunciation.py | 150 | def test_longer_sentence_sorted_first(self): | CODE |
| LOW | tests/test_pronunciation.py | 243 | def test_no_match_left_unchanged(self): | CODE |
| LOW | tests/test_pronunciation.py | 277 | def test_pronunciation_overrides_included(self): | CODE |
| LOW | tests/test_pronunciation.py | 293 | def test_manual_overrides_win(self): | CODE |
| LOW | tests/test_pronunciation.py | 311 | def test_speaker_entries_included(self): | CODE |
| LOW | tests/test_chunk_utils.py | 37 | def test_none_returns_default(self): | CODE |
| LOW | tests/test_chunk_utils.py | 42 | def test_garbage_returns_default(self): | CODE |
| LOW⚡ | tests/test_chunk_utils.py | 61 | def test_non_mapping_returns_empty(self): | CODE |
| LOW⚡ | tests/test_chunk_utils.py | 71 | def test_empty_dict_returns_empty(self): | CODE |
| LOW⚡ | tests/test_chunk_utils.py | 76 | def test_whitespace_only_returns_empty(self): | CODE |
| LOW | tests/test_chunk_utils.py | 110 | def test_fallback_token_from_normalized(self): | CODE |
| LOW | tests/test_chunk_utils.py | 118 | def test_handles_exception_gracefully(self): | CODE |
| LOW⚡ | tests/test_chapter_merge_normalize.py | 28 | def test_basic_override_by_index(self): | CODE |
| LOW⚡ | tests/test_chapter_merge_normalize.py | 38 | def test_override_by_source_title(self): | CODE |
| LOW⚡ | tests/test_chapter_merge_normalize.py | 46 | def test_disabled_override_skipped(self): | CODE |
| LOW⚡ | tests/test_chapter_merge_normalize.py | 54 | def test_metadata_updates_collected(self): | CODE |
| LOW⚡ | tests/test_chapter_merge_normalize.py | 62 | def test_no_matching_chapter_diagnostic(self): | CODE |
| LOW⚡ | tests/test_chapter_merge_normalize.py | 70 | def test_non_dict_override_skipped(self): | CODE |
| LOW⚡ | tests/test_chapter_merge_normalize.py | 76 | def test_text_from_base_when_not_provided(self): | CODE |
| LOW⚡ | tests/test_chapter_merge_normalize.py | 84 | def test_default_title_when_no_base(self): | CODE |
| LOW⚡ | tests/test_chapter_merge_normalize.py | 123 | def test_none_value_deletes_key(self): | CODE |
| LOW⚡ | tests/test_chapter_merge_normalize.py | 129 | def test_none_values_in_extracted_skipped(self): | CODE |
| LOW⚡ | tests/test_chapter_merge_normalize.py | 135 | def test_numeric_values_stringified(self): | CODE |
| LOW⚡ | tests/test_voice_formulas_pairs.py | 23 | def test_all_zero_returns_none(self): | CODE |
| LOW⚡ | tests/test_voice_formulas_pairs.py | 31 | def test_none_values_filtered(self): | CODE |
| LOW⚡ | tests/test_voice_formulas_pairs.py | 35 | def test_weight_normalization(self): | CODE |
| LOW | tests/test_epub_content_slicing.py | 31 | def test_single_file_multiple_chapters(self): | CODE |
| LOW | tests/test_chunk_text_for_tts_prefers_raw.py | 4 | def test_chunk_text_for_tts_prefers_text_over_normalized_text(): | CODE |
| 998 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| MEDIUM⚡ | tests/test_kokoro_plugin.py | 102 | # ────────────────────────────────────────────────────────────── | COMMENT |
| MEDIUM⚡ | tests/test_kokoro_plugin.py | 104 | # ────────────────────────────────────────────────────────────── | COMMENT |
| MEDIUM⚡ | tests/test_kokoro_plugin.py | 143 | # ────────────────────────────────────────────────────────────── | COMMENT |
| MEDIUM⚡ | tests/test_kokoro_plugin.py | 145 | # ────────────────────────────────────────────────────────────── | COMMENT |
| MEDIUM⚡ | tests/test_kokoro_plugin.py | 166 | # ────────────────────────────────────────────────────────────── | COMMENT |
| MEDIUM⚡ | tests/test_kokoro_plugin.py | 168 | # ────────────────────────────────────────────────────────────── | COMMENT |
| MEDIUM⚡ | tests/test_kokoro_plugin.py | 178 | # ────────────────────────────────────────────────────────────── | COMMENT |
| MEDIUM⚡ | tests/test_kokoro_plugin.py | 180 | # ────────────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | tests/test_kokoro_plugin.py | 34 | # ────────────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | tests/test_kokoro_plugin.py | 36 | # ────────────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | tests/test_kokoro_plugin.py | 73 | # ────────────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | tests/test_kokoro_plugin.py | 75 | # ────────────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | tests/test_kokoro_plugin.py | 201 | # ────────────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | tests/test_kokoro_plugin.py | 203 | # ────────────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | tests/test_pronunciation.py | 9 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM | tests/test_pronunciation.py | 13 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM | tests/test_chunk_utils.py | 14 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM | tests/test_chunk_utils.py | 16 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/test_chunk_utils.py | 53 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/test_chunk_utils.py | 55 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/test_chunk_utils.py | 82 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/test_chunk_utils.py | 84 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM | tests/test_chapter_merge_normalize.py | 12 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM | tests/test_chapter_merge_normalize.py | 14 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/test_chapter_merge_normalize.py | 92 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/test_chapter_merge_normalize.py | 94 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/test_chapter_merge_normalize.py | 142 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/test_chapter_merge_normalize.py | 144 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/test_output_paths.py | 146 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/test_output_paths.py | 148 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM | tests/test_output_paths.py | 16 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM | tests/test_output_paths.py | 18 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM | tests/test_output_paths.py | 52 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM | tests/test_output_paths.py | 54 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM | tests/test_output_paths.py | 76 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM | tests/test_output_paths.py | 78 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM | tests/test_output_paths.py | 91 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM | tests/test_output_paths.py | 93 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM | tests/test_output_paths.py | 113 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM | tests/test_output_paths.py | 115 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM | tests/test_output_paths.py | 222 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM | tests/test_output_paths.py | 224 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/test_domain_speaker_metadata.py | 86 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/test_domain_speaker_metadata.py | 88 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/test_domain_speaker_metadata.py | 263 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/test_domain_speaker_metadata.py | 265 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM | tests/test_domain_speaker_metadata.py | 15 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM | tests/test_domain_speaker_metadata.py | 17 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM | tests/test_domain_speaker_metadata.py | 212 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM | tests/test_domain_speaker_metadata.py | 214 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM | tests/test_domain_speaker_metadata.py | 471 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM | tests/test_domain_speaker_metadata.py | 473 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/test_supertonic_plugin.py | 116 | # ────────────────────────────────────────────────────────────── | COMMENT |
| MEDIUM⚡ | tests/test_supertonic_plugin.py | 118 | # ────────────────────────────────────────────────────────────── | COMMENT |
| MEDIUM⚡ | tests/test_supertonic_plugin.py | 157 | # ────────────────────────────────────────────────────────────── | COMMENT |
| MEDIUM⚡ | tests/test_supertonic_plugin.py | 159 | # ────────────────────────────────────────────────────────────── | COMMENT |
| MEDIUM⚡ | tests/test_supertonic_plugin.py | 180 | # ────────────────────────────────────────────────────────────── | COMMENT |
| MEDIUM⚡ | tests/test_supertonic_plugin.py | 182 | # ────────────────────────────────────────────────────────────── | COMMENT |
| MEDIUM⚡ | tests/test_supertonic_plugin.py | 192 | # ────────────────────────────────────────────────────────────── | COMMENT |
| MEDIUM⚡ | tests/test_supertonic_plugin.py | 194 | # ────────────────────────────────────────────────────────────── | COMMENT |
| 165 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| HIGH | plugins/supertonic/pipeline.py | 269 | except Exception: | CODE |
| HIGH | tests/conftest.py | 29 | except Exception: | CODE |
| HIGH | tests/conftest.py | 36 | except Exception: | CODE |
| HIGH | tests/conftest.py | 14 | except Exception: | CODE |
| HIGH | tests/test_preview_applies_manual_overrides.py | 55 | except Exception: | CODE |
| HIGH | tests/test_domain_normalization_pipeline.py | 280 | except ImportError: | CODE |
| HIGH | tests/__init__.py | 25 | except Exception: | CODE |
| HIGH | tests/test_domain_audio_sink.py | 17 | except AttributeError: | CODE |
| HIGH | tests/test_domain_audio_sink.py | 116 | except Exception: | CODE |
| HIGH | abogen/spacy_utils.py | 146 | except Exception: | CODE |
| HIGH | abogen/pronunciation_store.py | 85 | except Exception: | CODE |
| HIGH | abogen/predownload_gui.py | 192 | except Exception: | CODE |
| HIGH | abogen/predownload_gui.py | 562 | except Exception: | CODE |
| HIGH | abogen/shutdown.py | 62 | except Exception: | CODE |
| HIGH | abogen/shutdown.py | 71 | except Exception: | CODE |
| HIGH | abogen/shutdown.py | 95 | except Exception: | CODE |
| HIGH | abogen/shutdown.py | 104 | except Exception: | CODE |
| HIGH | abogen/shutdown.py | 143 | except Exception: | CODE |
| HIGH | abogen/shutdown.py | 44 | except Exception: | CODE |
| HIGH | abogen/shutdown.py | 127 | except Exception: | CODE |
| HIGH | abogen/shutdown.py | 87 | except Exception: | CODE |
| HIGH | abogen/shutdown.py | 93 | except Exception: | CODE |
| HIGH | abogen/utils.py | 202 | except (ImportError, FileNotFoundError): | CODE |
| HIGH | abogen/utils.py | 222 | except Exception: | CODE |
| HIGH | abogen/utils.py | 546 | except Exception: | CODE |
| HIGH | abogen/utils.py | 257 | except OSError: | CODE |
| HIGH | abogen/utils.py | 264 | except OSError: | CODE |
| HIGH | abogen/utils.py | 632 | except Exception: | CODE |
| HIGH | abogen/utils.py | 524 | except Exception: | CODE |
| HIGH | abogen/voice_cache.py | 142 | except LocalEntryNotFoundError: | CODE |
| HIGH | abogen/check_cuda.py | 20 | except Exception: | CODE |
| HIGH | abogen/kokoro_text_normalization.py | 214 | except Exception: | CODE |
| HIGH | abogen/kokoro_text_normalization.py | 1992 | except ValueError: | CODE |
| HIGH | abogen/book_parser.py | 911 | except ValueError: | CODE |
| HIGH | abogen/book_parser.py | 898 | except ValueError: | CODE |
| HIGH | abogen/tts_plugin/utils.py | 216 | except Exception: | CODE |
| HIGH | abogen/tts_plugin/plugin_manager.py | 134 | except Exception: | CODE |
| HIGH | abogen/integrations/calibre_opds.py | 282 | except CalibreOPDSError: | CODE |
| HIGH | abogen/integrations/calibre_opds.py | 269 | except CalibreOPDSError: | CODE |
| HIGH | abogen/integrations/calibre_opds.py | 345 | except CalibreOPDSError: | CODE |
| HIGH | abogen/integrations/calibre_opds.py | 1277 | except CalibreOPDSError: | CODE |
| HIGH | abogen/integrations/calibre_opds.py | 311 | except CalibreOPDSError: | CODE |
| HIGH | abogen/integrations/calibre_opds.py | 1201 | except ValueError: | CODE |
| HIGH | abogen/integrations/calibre_opds.py | 299 | except CalibreOPDSError: | CODE |
| HIGH | abogen/webui/service.py | 837 | except Exception: | CODE |
| HIGH | abogen/webui/service.py | 60 | except Exception: | CODE |
| HIGH | abogen/webui/service.py | 870 | except Exception: | CODE |
| HIGH | abogen/webui/debug_tts_runner.py | 161 | except Exception: | CODE |
| HIGH | abogen/webui/debug_tts_runner.py | 249 | except Exception: | CODE |
| HIGH | abogen/webui/debug_tts_runner.py | 170 | except Exception: | CODE |
| HIGH | abogen/webui/debug_tts_runner.py | 159 | except (ValueError, AttributeError): | CODE |
| HIGH | abogen/webui/routes/main.py | 187 | except OSError: | CODE |
| HIGH | abogen/webui/routes/main.py | 248 | except OSError: | CODE |
| HIGH | abogen/webui/routes/utils/synthesize.py | 33 | except Exception: | CODE |
| HIGH | abogen/webui/routes/utils/form.py | 382 | except ValueError: | CODE |
| HIGH | abogen/webui/routes/utils/form.py | 464 | except ValueError: | CODE |
| HIGH | abogen/webui/routes/utils/form.py | 523 | except (ValueError, AttributeError): | CODE |
| HIGH | abogen/webui/services/settings_service.py | 42 | except (TypeError, ValueError): | CODE |
| HIGH | abogen/webui/services/settings_service.py | 46 | except (TypeError, ValueError): | CODE |
| HIGH | abogen/webui/services/settings_service.py | 62 | except ValueError: | CODE |
| 44 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | build_pypi.py | 38 | CODE | |
| LOW | plugins/supertonic/__init__.py | 13 | CODE | |
| LOW | plugins/supertonic/engine.py | 7 | CODE | |
| LOW | plugins/supertonic/engine.py | 16 | CODE | |
| LOW | plugins/supertonic/engine.py | 17 | CODE | |
| LOW | plugins/supertonic/engine.py | 17 | CODE | |
| LOW | plugins/supertonic/pipeline.py | 8 | CODE | |
| LOW | plugins/kokoro/__init__.py | 13 | CODE | |
| LOW | plugins/kokoro/engine.py | 11 | CODE | |
| LOW | plugins/kokoro/engine.py | 19 | CODE | |
| LOW | plugins/kokoro/engine.py | 20 | CODE | |
| LOW | plugins/kokoro/engine.py | 20 | CODE | |
| LOW | tests/test_opds_import_metadata_mapping.py | 1 | CODE | |
| LOW | tests/test_kokoro_plugin.py | 11 | CODE | |
| LOW | tests/test_kokoro_plugin.py | 19 | CODE | |
| LOW | tests/test_kokoro_plugin.py | 23 | CODE | |
| LOW | tests/test_kokoro_plugin.py | 23 | CODE | |
| LOW | tests/test_kokoro_plugin.py | 23 | CODE | |
| LOW | tests/test_kokoro_plugin.py | 23 | CODE | |
| LOW | tests/test_kokoro_plugin.py | 40 | CODE | |
| LOW | tests/test_pronunciation.py | 3 | CODE | |
| LOW | tests/test_pronunciation.py | 5 | CODE | |
| LOW | tests/test_pronunciation.py | 6 | CODE | |
| LOW | tests/test_chunk_utils.py | 6 | CODE | |
| LOW | tests/test_chunk_utils.py | 11 | CODE | |
| LOW | tests/test_chapter_merge_normalize.py | 6 | CODE | |
| LOW | tests/test_chapter_merge_normalize.py | 8 | CODE | |
| LOW | tests/test_regression_webui_domain.py | 7 | CODE | |
| LOW | tests/test_output_paths.py | 6 | CODE | |
| LOW | tests/test_output_paths.py | 9 | CODE | |
| LOW | tests/test_output_paths.py | 11 | CODE | |
| LOW | tests/test_output_paths.py | 13 | CODE | |
| LOW | tests/test_domain_metadata_overrides.py | 3 | CODE | |
| LOW | tests/test_subtitle_generation.py | 3 | CODE | |
| LOW | tests/test_domain_normalization_pipeline.py | 5 | CODE | |
| LOW | tests/test_domain_normalization_pipeline.py | 6 | CODE | |
| LOW | tests/test_domain_pipeline_factory.py | 1 | CODE | |
| LOW | tests/test_service.py | 1 | CODE | |
| LOW | tests/test_domain_speaker_metadata.py | 7 | CODE | |
| LOW | tests/test_domain_speaker_metadata.py | 9 | CODE | |
| LOW | tests/test_domain_speaker_metadata.py | 9 | CODE | |
| LOW | tests/test_domain_speaker_metadata.py | 12 | CODE | |
| LOW | tests/test_domain_conversion_pipeline.py | 4 | CODE | |
| LOW | tests/test_domain_conversion_pipeline.py | 4 | CODE | |
| LOW | tests/test_domain_conversion_pipeline.py | 5 | CODE | |
| LOW | tests/test_domain_conversion_pipeline.py | 8 | CODE | |
| LOW | tests/test_domain_audio_buffer_extras.py | 4 | CODE | |
| LOW | tests/test_settings_integrations_secrets.py | 1 | CODE | |
| LOW | tests/test_settings_integrations_secrets.py | 3 | CODE | |
| LOW | tests/test_supertonic_plugin.py | 11 | CODE | |
| LOW | tests/test_supertonic_plugin.py | 19 | CODE | |
| LOW | tests/test_supertonic_plugin.py | 40 | CODE | |
| LOW | tests/test_split_pattern.py | 6 | CODE | |
| LOW | tests/test_audio_buffer.py | 4 | CODE | |
| LOW | tests/test_ffmetadata.py | 1 | CODE | |
| LOW | tests/test_epub_ncx_parsing.py | 10 | CODE | |
| LOW | tests/test_metadata_helpers_abs.py | 2 | CODE | |
| LOW | tests/test_metadata_helpers_abs.py | 125 | CODE | |
| LOW | tests/test_audiobookshelf_client.py | 1 | CODE | |
| LOW | tests/test_audio_helpers.py | 6 | CODE | |
| 336 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | build_pypi.py | 26 | except Exception: | CODE |
| LOW | plugins/supertonic/__init__.py | 135 | except Exception as e: | CODE |
| LOW | plugins/supertonic/engine.py | 158 | except Exception as e: | CODE |
| LOW | plugins/supertonic/pipeline.py | 95 | except Exception: | CODE |
| LOW | plugins/supertonic/pipeline.py | 141 | except Exception as exc: | CODE |
| LOW | plugins/supertonic/pipeline.py | 182 | except Exception as exc: # pragma: no cover | CODE |
| LOW | plugins/supertonic/pipeline.py | 269 | except Exception: | CODE |
| LOW | plugins/kokoro/__init__.py | 185 | except Exception as e: | CODE |
| LOW | plugins/kokoro/engine.py | 176 | except Exception as e: | CODE |
| LOW | tests/conftest.py | 14 | except Exception: | CODE |
| LOW | tests/conftest.py | 29 | except Exception: | CODE |
| LOW | tests/conftest.py | 36 | except Exception: | CODE |
| LOW | tests/test_preview_applies_manual_overrides.py | 55 | except Exception: | CODE |
| LOW | tests/__init__.py | 25 | except Exception: | CODE |
| LOW⚡ | tests/test_domain_audio_sink.py | 116 | except Exception: | CODE |
| LOW | tests/test_epub_missing_file_error_handling.py | 97 | except Exception as e: | CODE |
| LOW | abogen/spacy_utils.py | 54 | except Exception: | CODE |
| LOW | abogen/spacy_utils.py | 113 | except Exception as e: | CODE |
| LOW | abogen/spacy_utils.py | 119 | except Exception as e: | CODE |
| LOW | abogen/spacy_utils.py | 146 | except Exception: | CODE |
| LOW | abogen/is_nvidia.py | 7 | except Exception: | CODE |
| MEDIUM | abogen/is_nvidia.py | 4 | def check(): | CODE |
| LOW | abogen/pronunciation_store.py | 85 | except Exception: | CODE |
| MEDIUM | abogen/pronunciation_store.py | 19 | def _store_path() -> Path: | CODE |
| LOW | abogen/voice_profiles.py | 29 | except Exception: | CODE |
| MEDIUM | abogen/predownload_gui.py | 476 | def _check_kokoro_model(self) -> bool: | CODE |
| MEDIUM | abogen/predownload_gui.py | 489 | def _check_kokoro_config(self) -> bool: | CODE |
| LOW | abogen/predownload_gui.py | 40 | except Exception: | CODE |
| LOW | abogen/predownload_gui.py | 100 | except Exception as exc: # pragma: no cover - best-effort reporting | CODE |
| LOW | abogen/predownload_gui.py | 111 | except Exception: | CODE |
| LOW | abogen/predownload_gui.py | 137 | except Exception as exc: | CODE |
| LOW | abogen/predownload_gui.py | 148 | except Exception: | CODE |
| LOW | abogen/predownload_gui.py | 168 | except Exception as exc: | CODE |
| LOW | abogen/predownload_gui.py | 192 | except Exception: | CODE |
| LOW | abogen/predownload_gui.py | 198 | except Exception: | CODE |
| LOW | abogen/predownload_gui.py | 224 | except Exception as exc: | CODE |
| LOW | abogen/predownload_gui.py | 471 | except Exception: | CODE |
| LOW | abogen/predownload_gui.py | 486 | except Exception: | CODE |
| LOW | abogen/predownload_gui.py | 499 | except Exception: | CODE |
| LOW | abogen/predownload_gui.py | 562 | except Exception: | CODE |
| LOW | abogen/word_substitution.py | 211 | except Exception: | CODE |
| MEDIUM | abogen/word_substitution.py | 206 | def replace_number(match): | CODE |
| MEDIUM | abogen/text_extractor.py | 547 | def _extract_cover(self) -> Tuple[Optional[bytes], Optional[str]]: | CODE |
| LOW⚡ | abogen/text_extractor.py | 457 | except Exception as exc: | CODE |
| LOW⚡ | abogen/text_extractor.py | 466 | except Exception as exc: | CODE |
| LOW⚡ | abogen/text_extractor.py | 473 | except Exception as exc: | CODE |
| LOW⚡ | abogen/text_extractor.py | 480 | except Exception as exc: | CODE |
| LOW⚡ | abogen/text_extractor.py | 491 | except Exception as exc: | CODE |
| LOW⚡ | abogen/text_extractor.py | 498 | except Exception as exc: | CODE |
| LOW⚡ | abogen/text_extractor.py | 506 | except Exception as exc: | CODE |
| LOW | abogen/text_extractor.py | 417 | except Exception as exc: | CODE |
| LOW | abogen/text_extractor.py | 554 | except Exception as exc: | CODE |
| LOW | abogen/text_extractor.py | 569 | except Exception as exc: | CODE |
| LOW | abogen/text_extractor.py | 637 | except Exception as exc: | CODE |
| LOW | abogen/text_extractor.py | 711 | except Exception: | CODE |
| LOW | abogen/text_extractor.py | 762 | except Exception as exc: | CODE |
| LOW | abogen/text_extractor.py | 899 | except Exception: | CODE |
| LOW⚡ | abogen/shutdown.py | 62 | except Exception: | CODE |
| LOW⚡ | abogen/shutdown.py | 71 | except Exception: | CODE |
| LOW⚡ | abogen/shutdown.py | 79 | except Exception: | CODE |
| 238 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | plugins/supertonic/pipeline.py | 44 | CODE | |
| LOW | plugins/supertonic/pipeline.py | 189 | CODE | |
| LOW | tests/test_epub_heuristic_nav.py | 31 | CODE | |
| LOW | tests/test_epub_content_slicing.py | 31 | CODE | |
| LOW | tests/test_epub_content_slicing.py | 118 | CODE | |
| LOW | tests/test_domain_normalization_pipeline.py | 268 | CODE | |
| LOW | tests/test_epub_standard_nav.py | 32 | CODE | |
| LOW | tests/test_epub_html_nav_parsing.py | 29 | CODE | |
| LOW | tests/test_epub_missing_file_error_handling.py | 36 | CODE | |
| LOW | tests/plugins/conftest.py | 23 | CODE | |
| LOW | abogen/voice_profiles.py | 16 | CODE | |
| LOW | abogen/predownload_gui.py | 521 | CODE | |
| LOW | abogen/text_extractor.py | 574 | CODE | |
| LOW | abogen/text_extractor.py | 655 | CODE | |
| LOW | abogen/subtitle_utils.py | 121 | CODE | |
| LOW | abogen/subtitle_utils.py | 229 | CODE | |
| LOW | abogen/subtitle_utils.py | 299 | CODE | |
| LOW | abogen/speaker_analysis.py | 479 | CODE | |
| LOW | abogen/heteronym_overrides.py | 213 | CODE | |
| LOW | abogen/utils.py | 126 | CODE | |
| LOW | abogen/utils.py | 445 | CODE | |
| LOW | abogen/utils.py | 585 | CODE | |
| LOW | abogen/utils.py | 621 | CODE | |
| LOW | abogen/llm_client.py | 129 | CODE | |
| LOW | abogen/check_cuda.py | 7 | CODE | |
| LOW | abogen/entity_analysis.py | 204 | CODE | |
| LOW | abogen/kokoro_text_normalization.py | 981 | CODE | |
| LOW | abogen/kokoro_text_normalization.py | 1666 | CODE | |
| LOW | abogen/kokoro_text_normalization.py | 1871 | CODE | |
| LOW | abogen/book_parser.py | 697 | CODE | |
| LOW | abogen/book_parser.py | 781 | CODE | |
| LOW | abogen/book_parser.py | 984 | CODE | |
| LOW | abogen/book_parser.py | 1035 | CODE | |
| LOW | abogen/tts_plugin/utils.py | 84 | CODE | |
| LOW | abogen/tts_plugin/loader.py | 112 | CODE | |
| LOW | abogen/tts_plugin/plugin_manager.py | 34 | CODE | |
| LOW | abogen/epub3/exporter.py | 81 | CODE | |
| LOW | abogen/integrations/calibre_opds.py | 221 | CODE | |
| LOW | abogen/integrations/calibre_opds.py | 243 | CODE | |
| LOW | abogen/integrations/calibre_opds.py | 274 | CODE | |
| LOW | abogen/integrations/calibre_opds.py | 377 | CODE | |
| LOW | abogen/integrations/calibre_opds.py | 612 | CODE | |
| LOW | abogen/integrations/calibre_opds.py | 1249 | CODE | |
| LOW | abogen/integrations/calibre_opds.py | 1375 | CODE | |
| LOW | abogen/integrations/audiobookshelf.py | 127 | CODE | |
| LOW | abogen/integrations/audiobookshelf.py | 208 | CODE | |
| LOW | abogen/integrations/audiobookshelf.py | 386 | CODE | |
| LOW | abogen/webui/service.py | 704 | CODE | |
| LOW | abogen/webui/routes/voices.py | 84 | CODE | |
| LOW | abogen/webui/routes/api.py | 247 | CODE | |
| LOW | abogen/webui/routes/main.py | 266 | CODE | |
| LOW | abogen/webui/routes/utils/form.py | 76 | CODE | |
| LOW | abogen/webui/routes/utils/form.py | 592 | CODE | |
| LOW | abogen/webui/routes/utils/form.py | 839 | CODE | |
| LOW | abogen/webui/routes/utils/settings.py | 68 | CODE | |
| LOW | abogen/webui/routes/utils/epub.py | 106 | CODE | |
| LOW | abogen/webui/routes/utils/epub.py | 206 | CODE | |
| LOW | abogen/application/conversion_planner.py | 87 | CODE | |
| LOW | abogen/application/conversion_planner.py | 164 | CODE | |
| LOW | abogen/application/conversion_executor.py | 147 | CODE | |
| 49 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| HIGH | plugins/supertonic/__init__.py | 115 | Create a SuperTonic engine instance. This function is the plugin entry point. It must be atomic: succeed fully | STRING |
| HIGH | plugins/kokoro/__init__.py | 150 | Create a Kokoro engine instance. This function is the plugin entry point. It must be atomic: succeed fully or r | STRING |
| HIGH | tests/plugins/conftest.py | 84 | Load a plugin and return its load result. This fixture loads the plugin using the loader, providing access to: | STRING |
| HIGH | abogen/tts_plugin/engine.py | 31 | Synthesize audio from text. Args: request: The synthesis request containing text, voice, parameters | STRING |
| HIGH | abogen/tts_plugin/capabilities.py | 23 | List available voices for a given source. Args: sourceId: The voice source identifier. Ret | STRING |
| HIGH | abogen/tts_plugin/capabilities.py | 45 | Generate a preview audio for a voice. Args: voice: Voice selection for the preview. tex | STRING |
| HIGH | abogen/tts_plugin/capabilities.py | 69 | Synthesize audio in streaming mode. Args: request: The synthesis request. Yields: | STRING |
| HIGH | abogen/tts_plugin/plugin.py | 39 | Create an engine instance. This is the factory function that creates an Engine from a plugin. It must b | STRING |
| HIGH | abogen/tts_plugin/plugin_manager.py | 88 | Create an engine instance for the given plugin. Args: plugin_id: The plugin identifier (e.g., "koko | STRING |
| HIGH | abogen/application/conversion_service.py | 35 | Execute a conversion request and return the result. This is the single entry point for both UIs. It orchestrates: | STRING |
| HIGH | abogen/application/conversion_planner.py | 31 | Build a complete conversion plan from a request. This is the single entry point that both UIs will call. It han | STRING |
| HIGH | abogen/application/conversion_executor.py | 156 | Execute a conversion plan and return the result. Args: plan: The conversion plan from build_conversion_plan | STRING |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | plugins/supertonic/engine.py | 28 | logger = logging.getLogger(__name__) | CODE |
| LOW | plugins/supertonic/pipeline.py | 17 | logger = logging.getLogger(__name__) | CODE |
| LOW | plugins/kokoro/engine.py | 32 | logger = logging.getLogger(__name__) | CODE |
| LOW⚡ | abogen/predownload_gui.py | 425 | def _update_model_status(self, ok: bool) -> None: | CODE |
| LOW⚡ | abogen/predownload_gui.py | 432 | def _update_config_status(self, ok: bool) -> None: | CODE |
| LOW⚡ | abogen/predownload_gui.py | 439 | def _update_spacy_status(self, ok: bool, missing: List[str]) -> None: | CODE |
| LOW | abogen/predownload_gui.py | 266 | def _setup_ui(self) -> None: | CODE |
| LOW | abogen/predownload_gui.py | 413 | def _update_voices_status(self, ok: bool, missing: List[str]) -> None: | CODE |
| LOW | abogen/predownload_gui.py | 452 | def _set_status(self, key: str, text: str, color: str) -> None: | CODE |
| LOW | abogen/voice_formula_gui.py | 11 | __all__ = ["VoiceFormulaDialog"] | CODE |
| LOW | abogen/text_extractor.py | 22 | logger = logging.getLogger(__name__) | CODE |
| LOW | abogen/shutdown.py | 162 | __all__ = ["register_shutdown", "install_qt_hook", "request_shutdown", "register_cleanup"] | CODE |
| LOW | abogen/queue_manager_gui.py | 11 | __all__ = ["QueueManager"] | CODE |
| LOW | abogen/utils.py | 19 | logger = logging.getLogger(__name__) | CODE |
| LOW | abogen/gui.py | 11 | __all__ = ["abogen"] | CODE |
| LOW | abogen/kokoro_text_normalization.py | 24 | logger = logging.getLogger(__name__) | CODE |
| LOW | abogen/spacy_contraction_resolver.py | 17 | logger = logging.getLogger(__name__) | CODE |
| LOW | abogen/tts_plugin/__init__.py | 121 | __all__ = [ | CODE |
| LOW | abogen/epub3/__init__.py | 3 | __all__ = ["EPUB3PackageBuilder", "build_epub3_package"] | CODE |
| LOW | abogen/integrations/audiobookshelf.py | 15 | logger = logging.getLogger(__name__) | CODE |
| LOW | abogen/webui/service.py | 740 | def _update_queue_positions_locked(self) -> None: | CODE |
| LOW | abogen/webui/__init__.py | 1 | __all__ = ["create_app"] | CODE |
| LOW | abogen/webui/routes/__init__.py | 9 | __all__ = [ | CODE |
| LOW | abogen/webui/routes/jobs.py | 31 | logger = logging.getLogger(__name__) | CODE |
| LOW | abogen/webui/routes/main.py | 27 | logger = logging.getLogger(__name__) | CODE |
| LOW | abogen/application/integration_hooks.py | 34 | logger = logging.getLogger(__name__) | CODE |
| LOW | abogen/application/cleanup.py | 73 | __all__ = [ | CODE |
| LOW | abogen/infrastructure/subtitle_writer.py | 377 | __all__ = [ | CODE |
| LOW | abogen/infrastructure/exporters.py | 23 | logger = logging.getLogger(__name__) | CODE |
| LOW | abogen/infrastructure/exporters.py | 321 | __all__ = [ | CODE |
| LOW | abogen/domain/subtitle_processor.py | 32 | logger = logging.getLogger(__name__) | CODE |
| LOW | abogen/domain/metadata_extraction.py | 16 | logger = logging.getLogger(__name__) | CODE |
| LOW | abogen/domain/conversion_pipeline.py | 22 | logger = logging.getLogger(__name__) | CODE |
| LOW⚡ | abogen/pyqt/predownload_gui.py | 425 | def _update_model_status(self, ok: bool) -> None: | CODE |
| LOW⚡ | abogen/pyqt/predownload_gui.py | 432 | def _update_config_status(self, ok: bool) -> None: | CODE |
| LOW⚡ | abogen/pyqt/predownload_gui.py | 439 | def _update_spacy_status(self, ok: bool, missing: List[str]) -> None: | CODE |
| LOW | abogen/pyqt/predownload_gui.py | 266 | def _setup_ui(self) -> None: | CODE |
| LOW | abogen/pyqt/predownload_gui.py | 413 | def _update_voices_status(self, ok: bool, missing: List[str]) -> None: | CODE |
| LOW | abogen/pyqt/predownload_gui.py | 452 | def _set_status(self, key: str, text: str, color: str) -> None: | CODE |
| LOW | abogen/pyqt/conversion.py | 54 | logger = logging.getLogger(__name__) | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| MEDIUM | tests/test_epub_content_slicing.py | 39 | # Create a single content file with two sections | COMMENT |
| MEDIUM | tests/test_conversion_executor_unified.py | 80 | # Create a fake segment object | COMMENT |
| MEDIUM | tests/test_epub_html_nav_parsing.py | 46 | # Create the Nav item manually to control the HTML structure exactly | COMMENT |
| MEDIUM | tests/plugins/test_all_plugins.py | 170 | # Create a minimal request (won't actually synthesize, just test error) | COMMENT |
| MEDIUM | tests/plugins/import_error/__init__.py | 8 | # The following code will never be reached, but is here for documentation | COMMENT |
| MEDIUM | tests/contracts/test_plugin_manager_contract.py | 153 | # Create a session by calling | COMMENT |
| MEDIUM | abogen/pyqt/voice_formula_gui.py | 440 | # Create main container layout with profile section and mixer section | STRING |
| MEDIUM | abogen/pyqt/voice_formula_gui.py | 1429 | # Create the profile with the new name | COMMENT |
| MEDIUM | abogen/pyqt/conversion.py | 1440 | # Create a unique filename based on voice_id, language, and speed | COMMENT |
| MEDIUM | abogen/pyqt/book_handler.py | 168 | # Create a centered loading overlay and show it while background load runs | COMMENT |
| MEDIUM | abogen/pyqt/gui.py | 3812 | # Create the directory if it doesn't exist | COMMENT |
| MEDIUM | abogen/pyqt/gui.py | 4212 | # Create a custom message box with checkbox | COMMENT |
| MEDIUM | abogen/pyqt/gui.py | 3849 | icon = target # Create a more direct PowerShell command | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | build_pypi.py | 31 | # Check if build module is installed, install if not | COMMENT |
| LOW | tests/plugins/test_all_plugins.py | 195 | # Check if listVoices method exists | COMMENT |
| LOW | abogen/pronunciation_store.py | 43 | # Check if table exists | COMMENT |
| LOW | abogen/subtitle_utils.py | 156 | # Check if first line is timestamp | COMMENT |
| LOW | abogen/kokoro_text_normalization.py | 1985 | # Check if it really looks like a number (e.g. 1.05) | COMMENT |
| LOW | abogen/hf_tracker.py | 28 | if show_warning_signal_emitter: # Check if the emitter is set | CODE |
| LOW | abogen/book_parser.py | 258 | # Check if this page STARTS bookmarks | COMMENT |
| LOW | abogen/tts_plugin/loader.py | 223 | # Check if directory exists | COMMENT |
| LOW | abogen/tts_plugin/loader.py | 300 | # Check if any errors occurred | COMMENT |
| LOW | abogen/integrations/calibre_opds.py | 256 | # Check if it has a navigation link | COMMENT |
| LOW | abogen/integrations/calibre_opds.py | 327 | # Check if the server ignored the query and returned the default feed | COMMENT |
| LOW | abogen/integrations/calibre_opds.py | 1132 | # Check if all tokens match at least one fragment | COMMENT |
| LOW | abogen/domain/subtitle_generation.py | 301 | # Check if we've hit a sentence boundary or max words | COMMENT |
| LOW | abogen/pyqt/conversion.py | 413 | # Check if input is a subtitle file for additional configuration | COMMENT |
| LOW | abogen/pyqt/conversion.py | 464 | # Check if the input is a subtitle file or timestamp text file | COMMENT |
| LOW | abogen/pyqt/book_handler.py | 347 | # Check if content is already cached | COMMENT |
| LOW | abogen/pyqt/queue_manager_gui.py | 547 | # Read file content and calculate total_char_count using calculate_text_length | COMMENT |
| LOW⚡ | abogen/pyqt/gui.py | 2738 | # Check if path is a directory (for multiple chapter files) | COMMENT |
| LOW⚡ | abogen/pyqt/gui.py | 2754 | # Check if path exists and is a file before opening | COMMENT |
| LOW | abogen/pyqt/gui.py | 724 | # Check if text is empty based on character count | COMMENT |
| LOW | abogen/pyqt/gui.py | 733 | # Check if we need to warn about overwriting a non-temporary file | COMMENT |
| LOW | abogen/pyqt/gui.py | 1717 | # Check if this is a cache file | COMMENT |
| LOW | abogen/pyqt/gui.py | 1727 | # Check if this is a cache file | COMMENT |
| LOW | abogen/pyqt/gui.py | 1793 | # Check if current file is a subtitle file | COMMENT |
| LOW | abogen/pyqt/gui.py | 2468 | # Check if override was active (this determines which settings were ACTUALLY used) | COMMENT |
| LOW | abogen/pyqt/gui.py | 3283 | # Check if this is a timestamp detection (-1) or chapter detection | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW⚡ | tests/contracts/test_integration.py | 124 | # Step 1: Consumer gets plugin | COMMENT |
| LOW⚡ | tests/contracts/test_integration.py | 127 | # Step 2: Plugin creates engine | COMMENT |
| LOW⚡ | tests/contracts/test_integration.py | 132 | # Step 3: Engine creates session | COMMENT |
| LOW⚡ | tests/contracts/test_integration.py | 137 | # Step 4: Session synthesizes | COMMENT |
| LOW⚡ | tests/contracts/test_integration.py | 146 | # Step 5: Result returned | COMMENT |
| LOW | abogen/book_parser.py | 212 | # Step 1: Build the Skeleton Tree from TOC | COMMENT |
| LOW | abogen/book_parser.py | 238 | # Step 3: Add gap pages. | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW⚡ | tests/contracts/test_integration.py | 124 | # Step 1: Consumer gets plugin | COMMENT |
| LOW⚡ | tests/contracts/test_integration.py | 127 | # Step 2: Plugin creates engine | COMMENT |
| LOW⚡ | tests/contracts/test_integration.py | 132 | # Step 3: Engine creates session | COMMENT |
| LOW⚡ | tests/contracts/test_integration.py | 137 | # Step 4: Session synthesizes | COMMENT |
| LOW⚡ | tests/contracts/test_integration.py | 146 | # Step 5: Result returned | COMMENT |
| LOW | abogen/book_parser.py | 212 | # Step 1: Build the Skeleton Tree from TOC | COMMENT |
| LOW | abogen/book_parser.py | 238 | # Step 3: Add gap pages. | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW⚡ | tests/test_title_builder.py | 23 | result = build_title_intro_text({"title": "My Book", "author": "John Doe"}, "book.epub") | CODE |
| LOW | tests/test_title_builder.py | 49 | result = build_outro_text({"author": "John Doe"}, "book.epub") | CODE |
| LOW | tests/test_title_builder.py | 53 | result = build_outro_text({"title": "My Book", "author": "John Doe"}, "book.epub") | CODE |
| LOW⚡ | tests/test_subtitle_scenarios.py | 397 | "text": "Lorem ipsum... Lorem... Lorem...", "whitespace": ""}], | CODE |
| LOW⚡ | tests/test_subtitle_scenarios.py | 402 | assert [e[2] for e in entries] == ["Lorem ipsum...", "Lorem...", "Lorem..."] | CODE |
| LOW | tests/test_subtitle_scenarios.py | 378 | assert [e[2] for e in entries] == ["Test.", "Lorem ipsum...", "Lorem..."] | CODE |
| LOW | tests/test_subtitle_scenarios.py | 353 | 'Lorem ipsum... Lorem...' stayed a single subtitle entry. And | STRING |
| LOW⚡ | tests/test_regression_fixes.py | 96 | normalized = normalize("Test. Lorem ipsum...\n\nLorem...\n\nLorem ...") | CODE |
| LOW | tests/test_metadata_helpers.py | 50 | assert format_author_sentence("John Doe") == "By John Doe" | CODE |
| LOW | abogen/domain/subtitle_generation.py | 240 | # boundary ("Lorem ipsum... Lorem..." stays one sentence), so ellipsis | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| MEDIUM⚡ | tests/test_domain_normalization_pipeline.py | 11 | """Tests for the comprehensive TTS text preparation pipeline.""" | STRING |
| LOW | abogen/integrations/calibre_opds.py | 1450 | # Only add if not found elsewhere? Or just add small amount? | COMMENT |
| LOW⚡ | abogen/webui/routes/api.py | 588 | # For now, just use base settings as in original code (presumably) | COMMENT |
| LOW | abogen/infrastructure/subtitle_writer.py | 242 | # For now, just return the text with the highlight color | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| MEDIUM | abogen/infrastructure/exporters.py | 316 | CODE | |
| MEDIUM | abogen/infrastructure/exporters.py | 318 | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | abogen/kokoro_text_normalization.py | 289 | CODE | |
| LOW | abogen/webui/service.py | 349 | CODE | |
| LOW | abogen/domain/subtitle_processor.py | 146 | CODE | |
| LOW | abogen/domain/conversion_pipeline.py | 293 | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | docker-compose.yaml | 6 | # Usage: | COMMENT |
| LOW | docker-compose.webui.yml | 6 | # Usage: | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | docker-compose.yaml | 1 | # Docker Compose for Abogen | COMMENT |
| LOW | docker-compose.yaml | 61 | # Runtime flag is only honored by legacy docker-compose (v1) CLI. | COMMENT |
| LOW | docker-compose.webui.yml | 1 | # Docker Compose for Abogen Web UI (Flask-based interface) | COMMENT |