Repository Analysis

teng-lin/notebooklm-py

Unofficial Python API and agentic skill for Google NotebookLM. Full programmatic access to NotebookLM's features—including capabilities the web UI doesn't expose—via Python, CLI, and AI agents like Claude Code, Codex, and OpenClaw.

34.5 Strong AI signal View on GitHub
34.5
Adjusted Score
34.5
Raw Score
100%
Time Factor
2026-05-30
Last Push
15,556
Stars
Python
Language
394,199
Lines of Code
755
Files
8902
Pattern Hits
2026-05-31
Scan Date

Score History

Severity Breakdown

CRITICAL 2HIGH 135MEDIUM 1787LOW 6978

Pattern Findings

8902 matches across 16 categories. Click a row to expand file-level details.

Decorative Section Separators1749 hits · 6525 pts
SeverityFileLineSnippet
MEDIUMtests/cassette_patterns.py449# =============================================================================
MEDIUMtests/cassette_patterns.py451# =============================================================================
MEDIUMtests/cassette_patterns.py458 # -------------------------------------------------------------------------
MEDIUMtests/cassette_patterns.py460 # -------------------------------------------------------------------------
MEDIUMtests/cassette_patterns.py479 # -------------------------------------------------------------------------
MEDIUMtests/cassette_patterns.py481 # -------------------------------------------------------------------------
MEDIUMtests/cassette_patterns.py488 # -------------------------------------------------------------------------
MEDIUMtests/cassette_patterns.py490 # -------------------------------------------------------------------------
MEDIUMtests/cassette_patterns.py498 # -------------------------------------------------------------------------
MEDIUMtests/cassette_patterns.py500 # -------------------------------------------------------------------------
MEDIUMtests/cassette_patterns.py507 # -------------------------------------------------------------------------
MEDIUMtests/cassette_patterns.py509 # -------------------------------------------------------------------------
MEDIUMtests/cassette_patterns.py518 # -------------------------------------------------------------------------
MEDIUMtests/cassette_patterns.py520 # -------------------------------------------------------------------------
MEDIUMtests/cassette_patterns.py571 # -------------------------------------------------------------------------
MEDIUMtests/cassette_patterns.py573 # -------------------------------------------------------------------------
MEDIUMtests/cassette_patterns.py583 # -------------------------------------------------------------------------
MEDIUMtests/cassette_patterns.py585 # -------------------------------------------------------------------------
MEDIUMtests/cassette_patterns.py603 # -------------------------------------------------------------------------
MEDIUMtests/cassette_patterns.py605 # -------------------------------------------------------------------------
MEDIUMtests/cassette_patterns.py610 # -------------------------------------------------------------------------
MEDIUMtests/cassette_patterns.py612 # -------------------------------------------------------------------------
MEDIUMtests/cassette_patterns.py104# =============================================================================
MEDIUMtests/cassette_patterns.py106# =============================================================================
MEDIUMtests/cassette_patterns.py222# =============================================================================
MEDIUMtests/cassette_patterns.py224# =============================================================================
MEDIUMtests/cassette_patterns.py275# =============================================================================
MEDIUMtests/cassette_patterns.py277# =============================================================================
MEDIUMtests/cassette_patterns.py291# =============================================================================
MEDIUMtests/cassette_patterns.py293# =============================================================================
MEDIUMtests/cassette_patterns.py331# =============================================================================
MEDIUMtests/cassette_patterns.py333# =============================================================================
MEDIUMtests/cassette_patterns.py373# =============================================================================
MEDIUMtests/cassette_patterns.py375# =============================================================================
MEDIUMtests/cassette_patterns.py537 # -------------------------------------------------------------------------
MEDIUMtests/cassette_patterns.py539 # -------------------------------------------------------------------------
MEDIUMtests/cassette_patterns.py552 # -------------------------------------------------------------------------
MEDIUMtests/cassette_patterns.py554 # -------------------------------------------------------------------------
MEDIUMtests/cassette_patterns.py625 # -------------------------------------------------------------------------
MEDIUMtests/cassette_patterns.py627 # -------------------------------------------------------------------------
MEDIUMtests/cassette_patterns.py649 # -------------------------------------------------------------------------
MEDIUMtests/cassette_patterns.py651 # -------------------------------------------------------------------------
MEDIUMtests/cassette_patterns.py664# =============================================================================
MEDIUMtests/cassette_patterns.py666# =============================================================================
MEDIUMtests/cassette_patterns.py909# =============================================================================
MEDIUMtests/cassette_patterns.py911# =============================================================================
MEDIUMtests/vcr_config.py271# =============================================================================
MEDIUMtests/vcr_config.py273# =============================================================================
MEDIUMtests/vcr_config.py656# =============================================================================
MEDIUMtests/vcr_config.py658# =============================================================================
MEDIUMtests/_lint/test_session_runtime_boundaries.py378# ---------------------------------------------------------------------------
MEDIUMtests/_lint/test_session_runtime_boundaries.py380# ---------------------------------------------------------------------------
MEDIUMtests/_lint/test_session_runtime_boundaries.py408# ---------------------------------------------------------------------------
MEDIUMtests/_lint/test_session_runtime_boundaries.py410# ---------------------------------------------------------------------------
MEDIUMtests/_lint/test_session_runtime_boundaries.py447# ---------------------------------------------------------------------------
MEDIUMtests/_lint/test_session_runtime_boundaries.py449# ---------------------------------------------------------------------------
MEDIUMtests/_lint/test_session_runtime_boundaries.py479# ---------------------------------------------------------------------------
MEDIUMtests/_lint/test_session_runtime_boundaries.py481# ---------------------------------------------------------------------------
MEDIUMtests/_lint/test_session_runtime_boundaries.py587# ---------------------------------------------------------------------------
MEDIUMtests/_lint/test_session_runtime_boundaries.py589# ---------------------------------------------------------------------------
1689 more matches not shown…
Hyper-Verbose Identifiers5728 hits · 5134 pts
SeverityFileLineSnippet
LOWtests/conftest.py184def pytest_collection_modifyitems(config, items):
LOWtests/conftest.py241def mock_list_notebooks_response():
LOWtests/cassette_patterns.py942def synthetic_error_cassette_name(mode: str, slug: str) -> str:
LOWtests/cassette_patterns.py959def build_synthetic_error_response(
LOWtests/vcr_config.py173def _substitute_synthetic_error(response: dict[str, Any]) -> dict[str, Any]:
LOWtests/_lint/test_integration_allow_no_vcr_allowlist.py9def test_integration_allow_no_vcr_taxonomy_policy_is_current() -> None:
LOWtests/_lint/test_no_session.py32def _is_deleted_module_string(value: str) -> bool:
LOWtests/_lint/test_no_session.py108def test_no_deleted_session_surface_in_source_or_tests() -> None:
LOWtests/_lint/test_no_session.py116def test_scan_source_catches_static_and_dynamic_deleted_surface() -> None:
LOWtests/_lint/test_no_session.py139def test_scan_source_allows_surviving_sibling_modules() -> None:
LOWtests/_lint/test_no_module_shadowing.py78def test_cmd_module_imports_as_real_module(name: str) -> None:
LOWtests/_lint/test_no_module_shadowing.py92def test_click_group_public_alias_preserved(public_name: str) -> None:
LOWtests/_lint/test_error_handler_allowlist.py51def _click_exception_call_sites() -> set[AllowedSite]:
LOWtests/_lint/test_error_handler_allowlist.py64def test_raw_system_exit_sites_are_error_handler_owned_or_allowlisted() -> None:
LOWtests/_lint/test_error_handler_allowlist.py78def test_click_exception_sites_match_input_validation_allowlist() -> None:
LOWtests/_lint/test_no_session_compat_bridges.py267def test_linter_catches_each_context(source: str, expected: list[tuple[int, str, str]]) -> None:
LOWtests/_lint/test_no_session_compat_bridges.py272def test_linter_does_not_flag_non_forbidden_attrs() -> None:
LOWtests/_lint/test_no_session_compat_bridges.py297def test_linter_dynamic_access_known_negatives(source: str) -> None:
LOWtests/_lint/test_no_session_compat_bridges.py307def test_is_carve_out_for_runtime_lifecycle() -> None:
LOWtests/_lint/test_no_session_compat_bridges.py318def test_no_session_compat_bridges() -> None:
LOWtests/_lint/test_session_runtime_boundaries.py383def test_lifecycle_host_symbol_does_not_appear_in_src() -> None:
LOWtests/_lint/test_session_runtime_boundaries.py413def test_no_cast_to_lifecycle_host_in_src() -> None:
LOWtests/_lint/test_session_runtime_boundaries.py452def test_refresh_auth_core_symbol_does_not_appear_in_src() -> None:
LOWtests/_lint/test_session_runtime_boundaries.py484def test_auth_session_module_has_no_host_protocol_residue() -> None:
LOWtests/_lint/test_session_runtime_boundaries.py235def _protocol_class_declares_kernel(class_def: ast.ClassDef) -> bool:
LOWtests/_lint/test_session_runtime_boundaries.py310def _format_receiver_for_diagnostic(receiver: ast.expr) -> str:
LOWtests/_lint/test_session_runtime_boundaries.py348def _moved_session_symbol_alias_violations(tree: ast.AST, *, rel: str) -> list[str]:
LOWtests/_lint/test_session_runtime_boundaries.py365def test_moved_session_symbols_are_not_reached_through_session_module_aliases() -> None:
LOWtests/_lint/test_session_runtime_boundaries.py621def test_find_symbol_appearances_catches_each_context(
LOWtests/_lint/test_session_runtime_boundaries.py634def test_find_symbol_appearances_ignores_unrelated_names() -> None:
LOWtests/_lint/test_session_runtime_boundaries.py668def test_cast_target_extraction(source: str, expected_target: str | None) -> None:
LOWtests/_lint/test_session_runtime_boundaries.py686def test_protocol_class_declares_kernel_positive() -> None:
LOWtests/_lint/test_session_runtime_boundaries.py696def test_protocol_class_declares_kernel_skips_non_protocol() -> None:
LOWtests/_lint/test_session_runtime_boundaries.py707def test_imports_session_class_catches_both_shapes() -> None:
LOWtests/_lint/test_session_runtime_boundaries.py759def test_is_coordinator_receiver_covers_both_shapes(source: str, is_coordinator: bool) -> None:
LOWtests/_lint/test_session_runtime_boundaries.py787def test_format_receiver_for_diagnostic_shapes() -> None:
LOWtests/_lint/test_session_runtime_boundaries.py800def test_moved_session_symbol_alias_guard_catches_synthetic_alias() -> None:
LOWtests/_lint/test_client_composition.py39def test_features_receive_specific_collaborators_not_whole_client() -> None:
LOWtests/_lint/test_client_composition.py60def test_notebooklm_client_does_not_inline_composition_holder_state() -> None:
LOWtests/_lint/test_client_composition.py77def test_client_composed_does_not_expose_collaborators_alias() -> None:
LOWtests/_lint/test_login_init_is_reexport_only.py80def test_login_init_reexport_only() -> None:
LOWtests/_lint/test_no_forbidden_monkeypatches.py264def test_no_forbidden_monkeypatches_outside_allowlist() -> None:
LOWtests/_lint/test_no_legacy_rpc_callable_aliases.py49def test_rpc_callable_guard_helpers_cover_unpacked_assignments_and_import_aliases() -> None:
LOWtests/_lint/test_no_legacy_rpc_callable_aliases.py73def test_retired_rpc_callable_names_do_not_return() -> None:
LOWtests/_lint/test_no_legacy_rpc_callable_aliases.py95def test_rpc_callback_stays_upload_only() -> None:
LOWtests/_lint/test_auth_source_consolidation.py32def test_auth_json_env_literal_is_centralized() -> None:
LOWtests/_lint/test_no_core_imports.py125def test_no_runtime_core_imports(rel_path: str, extra_banned: frozenset[str]) -> None:
LOW…sts/_lint/test_no_deprecated_public_rpc_call_kwargs.py44def _is_public_client_rpc_call(node: ast.Call) -> bool:
LOW…sts/_lint/test_no_deprecated_public_rpc_call_kwargs.py134def test_no_unauthorized_deprecated_public_rpc_call_kwargs() -> None:
LOWtests/_lint/test_asyncio_loop_affinity_guard.py147def _is_primitive_construction(
LOWtests/_lint/test_asyncio_loop_affinity_guard.py285def test_every_asyncio_primitive_is_loop_affinity_guarded() -> None:
LOWtests/_lint/test_asyncio_loop_affinity_guard.py324def test_loop_affinity_allowlist_has_no_stale_entries() -> None:
LOWtests/_lint/test_asyncio_loop_affinity_guard.py340def test_loop_affinity_followup_entries_reference_a_tracking_issue() -> None:
LOWtests/_lint/test_asyncio_loop_affinity_guard.py373def test_detector_handles_all_import_styles() -> None:
LOWtests/_helpers/client_factory.py32def build_client_shell_for_tests(
LOWtests/unit/test_middleware_context_contract.py129 def _record_context_dict_literal_assignment(
LOWtests/unit/test_middleware_context_contract.py150def test_allowed_rpc_context_keys_match_adr_vocabulary() -> None:
LOWtests/unit/test_middleware_context_contract.py163def test_context_literal_visitor_records_update_keyword_keys() -> None:
LOWtests/unit/test_middleware_context_contract.py178def test_production_context_literal_keys_stay_in_allowed_vocabulary() -> None:
LOWtests/unit/test_artifacts_helpers.py30def test_extract_data_table_rows_happy_path() -> None:
5668 more matches not shown…
Unused Imports753 hits · 627 pts
SeverityFileLineSnippet
LOWtests/cassette_patterns.py100
LOWtests/_lint/test_integration_allow_no_vcr_allowlist.py3
LOWtests/_lint/test_no_session.py3
LOWtests/_lint/test_no_module_shadowing.py31
LOWtests/_lint/test_error_handler_allowlist.py3
LOWtests/_lint/test_no_session_compat_bridges.py39
LOWtests/_lint/test_session_runtime_boundaries.py97
LOWtests/_lint/test_client_composition.py3
LOWtests/_lint/test_login_init_is_reexport_only.py6
LOWtests/_lint/test_login_package_dag.py8
LOWtests/_lint/test_no_forbidden_monkeypatches.py57
LOWtests/_lint/test_no_legacy_rpc_callable_aliases.py3
LOWtests/_lint/test_auth_source_consolidation.py10
LOWtests/_lint/test_no_core_imports.py28
LOW…sts/_lint/test_no_deprecated_public_rpc_call_kwargs.py9
LOWtests/_lint/test_asyncio_loop_affinity_guard.py32
LOWtests/_helpers/client_factory.py3
LOWtests/unit/test_middleware_context_contract.py3
LOWtests/unit/test_artifacts_helpers.py12
LOWtests/unit/test_json_stdout_purity.py19
LOWtests/unit/test_drain_tracker_hooks.py18
LOWtests/unit/test_refresh_lock_registry.py11
LOWtests/unit/test_from_storage_dual_protocol.py18
LOWtests/unit/test_firefox_containers.py12
LOWtests/unit/test_vcr_scrubbing.py30
LOWtests/unit/test_auth_instance_invariant.py3
LOWtests/unit/test_vcr_config.py20
LOWtests/unit/test_source_upload_coverage.py11
LOWtests/unit/test_tier_enforcement_hook.py32
LOWtests/unit/test_auth_refresh_retry.py12
LOWtests/unit/test_streaming_chat_wire.py3
LOWtests/unit/test_streaming_chat_wire.py570
LOWtests/unit/test_concurrency_refresh_race.py58
LOWtests/unit/test_middleware_chain_host.py28
LOWtests/unit/test_cli_boundary.py30
LOWtests/unit/test_with_client_handle_errors.py20
LOWtests/unit/test_logging.py3
LOWtests/unit/test_check_rpc_health.py19
LOWtests/unit/test_refresh_state_machine.py14
LOWtests/unit/test_logging_correlation.py3
LOWtests/unit/test_download_result.py3
LOWtests/unit/test_chat_passage_resolver.py15
LOWtests/unit/test_chat_helpers.py11
LOWtests/unit/test_auth_psidts_recovery.py12
LOWtests/unit/test_mind_maps_api.py3
LOWtests/unit/test_error_injection_middleware.py41
LOWtests/unit/test_public_surface.py26
LOWtests/unit/test_chain_wiring.py27
LOWtests/unit/test_interactive_mind_map.py11
LOWtests/unit/test_playwright_marker_hook.py22
LOWtests/unit/test_e2e_conftest_options.py11
LOWtests/unit/test_auth_account_coverage.py13
LOWtests/unit/test_runtime_auth.py35
LOWtests/unit/test_cookie_domain_split.py21
LOWtests/unit/test_notebook_metadata.py3
LOWtests/unit/test_download_url.py11
LOWtests/unit/test_tier_13_all_exports.py15
LOWtests/unit/test_profile_atomic_write.py38
LOWtests/unit/test_type_boundaries.py3
LOWtests/unit/test_atomic_io.py14
693 more matches not shown…
Docstring Block Structure60 hits · 300 pts
SeverityFileLineSnippet
HIGHtests/cassette_patterns.py122Re-derive ``<count>`` prefixes in a chunked response body. Google's batchexecute responses are framed as alternatin
HIGHtests/cassette_patterns.py962Return a ``(status_code, body, headers)`` triple for a synthetic error. The shape is intentionally minimal; the cli
HIGHsrc/notebooklm/_sharing.py148Share notebook with a user. Args: notebook_id: The notebook ID. email: User's email add
HIGHsrc/notebooklm/_research.py331Start a research session. Args: notebook_id: The notebook ID. query: The research query
HIGHsrc/notebooklm/_research.py470Poll until research reaches a terminal state or times out. When the first poll returns a concrete ``task_id``,
HIGHsrc/notebooklm/_reqid_counter.py142Atomically increment the counter and return the new value. Args: step: Increment applied to the cou
HIGHsrc/notebooklm/paths.py218Get directory for a specific profile. Args: profile: Profile name. If None, resolves via resolve_profile().
HIGHsrc/notebooklm/_chat_notes.py181Build CREATE_NOTE params for the saved-from-chat variant. Produces the 7-element params array used by the web UI's
HIGHsrc/notebooklm/_chat_notes.py283Save a chat answer as a citation-rich note via the saved-from-chat CREATE_NOTE variant (issue #660). Unlike the
HIGHsrc/notebooklm/_deprecation.py157Resolve a renamed keyword, warning if the deprecated name was used. Maps a deprecated keyword (``old``) onto its re
HIGHsrc/notebooklm/_idempotency.py84Probe-then-retry wrapper for mutating create RPCs. Args: create: Coroutine factory that issues the create R
HIGHsrc/notebooklm/_chat.py302Ask the notebook a question. Args: notebook_id: The notebook ID. question: The question
HIGHsrc/notebooklm/_chat.py838Save a chat answer as a citation-rich note (issue #660). Unlike :meth:`NotesAPI.create`, this preserves the ``[
HIGHsrc/notebooklm/_sources.py200Wait for a source to become ready. Polls the source status until it becomes READY or ERROR, or timeout.
HIGHsrc/notebooklm/_sources.py253Wait for a source to be registered server-side (status >= PROCESSING). Polls until the source is visible in the
HIGHsrc/notebooklm/_sources.py303Wait for multiple sources to become ready in parallel. Args: notebook_id: The notebook ID.
HIGHsrc/notebooklm/_sources.py391Add a text source (copied text) to a notebook. Args: notebook_id: The notebook ID. titl
HIGHsrc/notebooklm/_sources.py445Add a file source to a notebook using resumable upload. Uses Google's resumable upload protocol: 1. Reg
HIGHsrc/notebooklm/_sources.py713Get the full content of a source. Args: notebook_id: The notebook ID. source_id: The so
HIGHsrc/notebooklm/_notebooks.py468Get notebook details. Args: notebook_id: The notebook ID. Returns: Notebook ob
HIGHsrc/notebooklm/_artifacts.py866Wait for a generation task to complete. Uses exponential backoff for polling to reduce API load. Concu
HIGHsrc/notebooklm/_artifacts.py1126Select an artifact from candidates by ID or return latest completed. This is the single point where completed-a
HIGHsrc/notebooklm/utils.py37Return the surrounding source-text passage for a chat citation. A :class:`~notebooklm.types.ChatReference` carries
HIGHsrc/notebooklm/_row_adapters_sources.py172Normalize any of the three source wire shapes into a :class:`SourceRow`. Shapes handled (matching the l
HIGHsrc/notebooklm/artifacts.py74Run an artifact-generation callable with rate-limit retry. The callable is always invoked at least once. Retries ha
HIGHsrc/notebooklm/_auth/cookies.py162Extract Google cookies from Playwright storage state for NotebookLM auth. Filters cookies to include those from .go
HIGHsrc/notebooklm/_auth/cookies.py258Load Playwright storage state from file or environment variable. This is a shared helper used by load_auth_from_sto
HIGHsrc/notebooklm/_auth/cookies.py317Load cookies as an httpx.Cookies object for authenticated downloads. Unlike load_auth_from_storage() which returns
HIGHsrc/notebooklm/_auth/cookies.py360Extract Google cookies from storage state preserving original identity. Returns a path-aware ``(name, domain, path)
HIGHsrc/notebooklm/_auth/cookies.py396Build an httpx.Cookies jar with original domains preserved. This function loads cookies from storage and creates a
HIGHsrc/notebooklm/_auth/tokens.py130Create AuthTokens from Playwright storage state file. This is the recommended way to create AuthTokens for prog
HIGHsrc/notebooklm/_auth/tokens.py247Load Google cookies from storage as a flat name→value dict. Loads authentication cookies with the following precede
HIGHsrc/notebooklm/_auth/extraction.py64Extract a ``WIZ_global_data[key]`` value from a NotebookLM HTML response. NotebookLM (and other Google products) em
HIGHsrc/notebooklm/_auth/extraction.py182 Extract CSRF token (SNlM0e) from NotebookLM page HTML. The CSRF token is embedded in the page's WIZ_global_dat
HIGHsrc/notebooklm/_auth/extraction.py222 Extract session ID (FdrFJe) from NotebookLM page HTML. The session ID is embedded in the page's WIZ_global_dat
HIGHsrc/notebooklm/_auth/refresh.py656Internal: fetch CSRF and session tokens using a pre-built cookie jar. This is the single implementation for all tok
HIGHsrc/notebooklm/_auth/refresh.py730Fetch tokens from a cookie mapping. For backward compatibility. Prefer AuthTokens.from_storage() which preserves co
HIGHsrc/notebooklm/_auth/refresh.py779Fetch tokens with domain-preserving cookies from storage. Used by CLI helpers. Loads storage, builds jar, fetches t
HIGHsrc/notebooklm/_auth/account.py144Enumerate Google accounts visible to the given cookie jar. Probes ``https://notebooklm.google.com/?authuser=N`` for
HIGHsrc/notebooklm/cli/resolve.py44Validate and normalize an entity ID. Args: entity_id: The ID to validate. entity_name: Name for err
HIGHsrc/notebooklm/cli/resolve.py124Get notebook ID from argument, env var, or active context. Resolution order (env-var precedence): 1. ``noteboo
HIGHsrc/notebooklm/cli/resolve.py205Resolve a partial ID against a **pre-fetched** item list. Sync core of the partial-ID matching logic. Encapsulates
HIGHsrc/notebooklm/cli/resolve.py337Resolve a case-insensitive partial ID prefix to a full entity ID. Allows users to type partial IDs like ``abc`` ins
HIGHsrc/notebooklm/cli/_firefox_containers.py228Resolve a ``--browser-cookies 'firefox::<spec>'`` to a selector. Args: profile_path: Firefox profile direct
HIGHsrc/notebooklm/cli/_firefox_containers.py409Read ``cookies.sqlite`` filtered to a single container. Args: profile_path: Firefox profile directory conta
HIGHsrc/notebooklm/cli/_chromium_profiles.py316Read and decrypt cookies from a single Chromium user-data profile. Uses ``rookiepy.any_browser(db_path, domains=…)`
HIGHsrc/notebooklm/cli/download_helpers.py21Resolve a partial artifact ID to a full ID. UUID-shaped IDs (canonical 8-4-4-4-12 hex layout, case-insensitive -
HIGHsrc/notebooklm/cli/download_helpers.py94 Select an artifact from a list based on criteria. CRITICAL: Implements Filter -> Count -> Select logic: 1.
HIGHsrc/notebooklm/cli/auth_runtime.py78Get auth components from context. Args: ctx: Click context with optional storage_path in obj Returns:
HIGHsrc/notebooklm/cli/input.py11Read all of stdin as UTF-8 text and strip surrounding whitespace. Centralizes the Unix ``-`` stdin convention used
HIGHsrc/notebooklm/cli/input.py42Resolve prompt text from a positional argument or ``--prompt-file``. Exactly one source may be provided. The file/s
HIGHsrc/notebooklm/cli/services/research.py104Resolve, wait for completion, and optionally import. Args: plan: User inputs validated by the Click handler
HIGHsrc/notebooklm/cli/services/generate.py293Validate Click-layer inputs and return a :class:`GenerationPlan`. Args: kind: One of the literal kind names
HIGHsrc/notebooklm/cli/services/download.py237Validate + assemble a :class:`DownloadPlan` from raw Click args. Synchronous: rejects flag conflicts with a typed v
HIGHsrc/notebooklm/cli/services/login/cookie_jar.py79Probe ``?authuser=N`` against one cookie set and return tagged Accounts. Shared by both the legacy single-jar path
HIGHsrc/notebooklm/cli/services/login/firefox_accounts.py38Load Google cookies from a specific Firefox Multi-Account Container. Bypasses rookiepy because rookiepy 0.5.6 does
HIGHsrc/notebooklm/cli/services/login/profile_targets.py41Derive a valid profile name from an email address. Profile names are restricted to ``[a-zA-Z0-9_-]`` (see :data
HIGHsrc/notebooklm/rpc/decoder.py220 Parse chunked response format (rt=c mode). Format is alternating lines of: - byte_count (integer) - js
HIGHsrc/notebooklm/rpc/decoder.py649 Complete decode pipeline: strip prefix -> parse chunks -> extract result. Args: raw_response: Raw resp
HIGHsrc/notebooklm/rpc/_safe_index.py60Walk ``data`` by ``path`` indices with soft-strict drift handling. Args: data: Nested list/tuple structure
Cross-Language Confusion48 hits · 270 pts
SeverityFileLineSnippet
HIGHtests/vcr_config.py467 1. **Streaming-chat envelope** ``[null, "<inner_json>"]`` where the inner
HIGHtests/vcr_config.py473 2. **Batchexecute envelope** ``[[[rpc_id, args_json, null, "generic"]]]``
HIGHtests/vcr_config.py542 # Streaming-chat envelope: [null, "<inner_json>"].
HIGHtests/unit/test_vcr_config.py87 JSON envelope is ``[null, "<inner_json>"]`` and ``<inner_json>`` is itself a
HIGHtests/unit/test_decoder.py867 """[5, null, 'x'] is not the bare form — no enrichment."""
HIGHtests/unit/test_chat_ask_invariants.py294 '63\n[["wrb.fr","hPTbtc","[[[\\"real-conv-id-from-hptbtc\\"]]]",null,null]]'
HIGHtests/unit/test_cassette_shapes.py448 f"[null, '<inner-json>'], got {type(freq).__name__} {freq!r:.120}"
HIGHtests/unit/test_cassette_shapes.py29the new 9-param outer shape ``[null, "<inner-json-string>"]`` whose inner
HIGHtests/unit/test_cassette_shapes.py440 Real chat-ask `f.req` is ``[null, "<inner-json>"]`` whose inner JSON
HIGHtests/unit/test_api_coverage.py133 # Real API returns 3 levels of nesting: [[[null, [summary], [[keywords]], []]]]
HIGHtests/unit/test_api_coverage.py180 # Response format: [[[title, description, null, null, prompt, audience_level], ...]]
HIGHtests/unit/test_api_coverage.py301 # Verify reference payload: [null, ["source_id"], [2]]
HIGHtests/unit/test_api_coverage.py314 # Verify reference payload: [null, ["source_id"], [2]]
HIGHtests/unit/test_authed_post_pipeline.py1488 decoded_payload = b')]}\'\n\n[["wrb.fr",null,"[1]",null,null,null,"generic"]]'
HIGHtests/unit/test_select_artifact.py276 ever emits ``[null, ...]`` at index 15 the sort must coerce that
HIGHtests/unit/test_auth_cookie_save_race.py1007 f"None-valued cookie must never be persisted as value:null, got: {stored}"
HIGHtests/unit/test_save_chat_as_note_encoder.py105 # passage[3] = [[null, start, end]]; passage[5] = [[[passage_id], source_id]];
HIGHtests/unit/test_save_chat_as_note_encoder.py201 assert "[0,0,0,null,null,null,null,0,0]" in actual_json
HIGHtests/unit/test_rate_limit_retry.py46 resp.text = ")]}'\n[null,[" + str(payload).replace("'", '"') + "]]"
HIGHtests/unit/test_rescrub_cassettes_script.py95 f'[["wrb.fr","JFMDGd","[[null,[\\"{avatar_url}\\"]]]",null,null,null,"generic"]]'
HIGHtests/unit/test_rpc_overrides.py171 '{"LIST_NOTEBOOKS": null, "CREATE_NOTEBOOK": "valid"}',
HIGHtests/unit/test_vcr_body_matcher.py89 """Build a streaming-chat ``f.req`` form body (`[null, "<inner_json>"]`)."""
HIGHtests/unit/test_vcr_body_matcher.py180 fixtures: the cassette has a trailing ``[null, null]`` while the live
HIGHtests/unit/test_vcr_body_matcher.py78 is ``[[[rpc_id, "<args_json>", null, "generic"]]]`` and ``<args_json>``
HIGHtests/unit/test_vcr_body_matcher.py310 The outer ``[[[rpc, "...", null, "generic"]]]`` shape parses cleanly,
HIGHtests/unit/test_source_selection.py1052 # Response format: [[[title, description, null, null, prompt, audience_level], ...]]
HIGHtests/integration/test_vcr_comprehensive.py791 # Drive sources return [[null, true, [source_id]]] when fresh
HIGHtests/integration/test_artifacts_integration.py2321 """An empty (non-null) CREATE_ARTIFACT result drifts and raises.
HIGHtests/integration/test_chat_delete_conversation_vcr.py192 assert params[2] is None, f"slot 2 must be null, got {params[2]!r}"
HIGHtests/integration/test_vcr_example.py90 'f.req=[[["methodId",null,null,[[["notebook_id","data"]]]]]]&at=fake_csrf_token'
HIGHtests/integration/test_notebooks_integration.py301 # First response for rename (returns null)
HIGHtests/integration/test_notebooks_integration.py334 # Rename response (returns null)
HIGHtests/integration/test_notebooks_integration.py374 None, # Share returns null, we build the URL
HIGHtests/integration/test_sources_integration.py610 assert is_fresh is True, "Nested [null, true, ...] should mean source is fresh"
HIGHtests/integration/test_sources_integration.py636 # Real API returns 3 levels of nesting: [[[null, [summary], [[keywords]], []]]]
HIGHtests/integration/test_sources_integration.py600 Drive sources return [[null, true, [source_id]]] when fresh,
HIGHtests/integration/concurrency/test_chat_history_race.py80 ``[null, "<params-json>"]``; the inner params list matches the order
HIGHscripts/check_rpc_health.py453 # Params structure: [[[null,[[null,null,null,null,["language_code"]]]]]]
HIGHsrc/notebooklm/_sources.py667 # - [[null, true, [source_id]]]: source is fresh (Drive sources)
HIGHsrc/notebooklm/_sources.py678 # Check for nested structure [[null, true, ...]] from Drive sources
HIGHsrc/notebooklm/_settings.py176 # Params structure: [[[null,[[null,null,null,null,["language_code"]]]]]]
HIGHsrc/notebooklm/_notebooks.py537 # [notebook_id, [[null, null, null, [null, new_title]]]]
HIGHsrc/notebooklm/cli/services/playwright_login.py122 " 2. Or run: notebooklm auth logout && notebooklm login"
HIGHsrc/notebooklm/rpc/decoder.py639 # we never downgrade a non-null result back to null).
HIGHsrc/notebooklm/rpc/decoder.py716 # null, so raise regardless of ``allow_null``.
HIGHsrc/notebooklm/rpc/overrides.py62 # ``json.loads('{"X": null}')`` would coerce to ``str(None) ==
HIGHsrc/notebooklm/rpc/encoder.py22 [[[rpc_id, json_params, null, "generic"]]]
HIGHsrc/notebooklm/rpc/encoder.py42 # Build inner request: [rpc_id, json_params, null, "generic"]
Over-Commented Block228 hits · 198 pts
SeverityFileLineSnippet
LOWREADME.md121# 1. Authenticate (opens browser)
LOWtests/cassette_patterns.py101
LOWtests/cassette_patterns.py321 "SCRUBBED_DRIVE_FILE_ID",
LOWtests/cassette_patterns.py381# theory contain regex metacharacters (none do today, but future additions
LOWtests/cassette_patterns.py401#
LOWtests/cassette_patterns.py441# storage_state JSON — and ``is_clean`` (whose detector IS registry-derived via
LOWtests/cassette_patterns.py461 # These run FIRST, before any cookie-name-anchored pattern, so a session
LOWtests/cassette_patterns.py481 # -------------------------------------------------------------------------
LOWtests/cassette_patterns.py521 # JSON-quoted form. The replacement embeds ``@example.com`` so a second
LOWtests/cassette_patterns.py541 # here: that would clobber legitimate two-Capitalized-word fixture content
LOWtests/cassette_patterns.py601 # full upload URL above).
LOWtests/cassette_patterns.py621 (
LOWtests/cassette_patterns.py641 # quote inside a JSON string) so it never fires on bare ``"Foo Bar"``
LOWtests/cassette_patterns.py741# Each entry is (label, regex) where the regex's group(1) captures the value
LOWtests/cassette_patterns.py761]
LOWtests/cassette_patterns.py881 # --- 6. Escaped display-name literals ----------------------------------
LOWtests/cassette_patterns.py901 # definition — this is the cookie-name-agnostic backstop that closes the
LOWtests/vcr_config.py641 # Catches the regression class P1-3 targets — different arg counts,
LOWtests/vcr_config.py661# Set NOTEBOOKLM_VCR_RECORD=1 (or =true, =yes) to record new cassettes
LOWtests/_lint/test_no_session_compat_bridges.py61 # so any stray reference raises ``AttributeError`` at access time —
LOWtests/_lint/test_no_session_compat_bridges.py81 "_reqid_counter",
LOWtests/_lint/test_session_runtime_boundaries.py101
LOWtests/_lint/test_session_runtime_boundaries.py521 violations.append(
LOWtests/_lint/test_no_forbidden_monkeypatches.py61from pathlib import Path
LOWtests/_lint/test_no_forbidden_monkeypatches.py101# at a word boundary, so we match the full chain regardless of how deep
LOWtests/_lint/test_no_forbidden_monkeypatches.py141_ALLOWLIST: frozenset[str] = frozenset(
LOWtests/_lint/test_no_forbidden_monkeypatches.py161 # side-effects/idempotency cassettes); these patches sit below the
LOWtests/_lint/test_no_forbidden_monkeypatches.py181 # `_try_claim_rotation`, `_file_lock_try_exclusive`,
LOWtests/_lint/test_no_forbidden_monkeypatches.py201 # database-discovery helpers — CLI-side seam outside `make_fake_core`.
LOWtests/_lint/test_asyncio_loop_affinity_guard.py81# Each entry is a primitive whose construction site is loop-safe by an
LOWtests/unit/test_chat_characterization.py2081 1,
LOWtests/unit/test_vcr_config.py361 assert "real_sid_value" not in out
LOWtests/unit/conftest.py41 """
LOWtests/unit/conftest.py61 # wrapper's ``aiter_bytes`` + rebuild path works on it. Returning a
LOWtests/unit/test_cassette_sanitizer.py481 entries = {
LOWtests/unit/test_cassette_sanitizer.py501 # JSON payload with only sensitive scalars scrubbed inside).
LOWtests/unit/test_cassette_shapes.py81# The "67 cassettes with /ogw/" dynamic set that used to surface here was
LOWtests/unit/test_cassette_shapes.py561# Encoding-header coverage (issue #773 follow-up to #769 / #771)
LOWtests/unit/test_authed_post_pipeline.py481 )
LOWtests/unit/test_auth_cookie_save_race.py1701 # Two jars representing distinct post-rotation states. The save that
LOWtests/unit/test_atomic_update_json.py321# Lock-path derivation contract (#1220)
LOWtests/unit/test_init_order.py321# Artifact-service "reach-in" guard
LOWtests/unit/test_research_api.py701 ):
LOWtests/unit/test_public_shims.py201
LOWtests/unit/test_public_shims.py821 assert frozenset().union(*OPTIONAL_COOKIE_DOMAINS_BY_LABEL.values()) == OPTIONAL_COOKIE_DOMAINS
LOWtests/unit/test_public_shims.py1141 method=RPCMethod.LIST_NOTEBOOKS,
LOWtests/unit/test_public_shims.py1241
LOWtests/unit/test_notes_unit.py681 assert params[1] is None
LOWtests/unit/test_refresh_cmd_redaction.py261 # The full exception (with its cause chain) is what DEBUG-level captures
LOWtests/unit/test_rpc_health_coverage.py61# ---------------------------------------------------------------------------
LOWtests/unit/test_rpc_health_coverage.py81 "CREATE_ARTIFACT",
LOWtests/unit/test_runtime_lifecycle.py121 # needs an async implementation.
LOWtests/unit/test_runtime_lifecycle.py141 # so a client reopened on a different loop rebuilds the semaphore on
LOWtests/unit/test_runtime_lifecycle.py281 host._drain_tracker.reset_after_open.assert_called_once_with()
LOWtests/unit/test_runtime_lifecycle.py701#
LOWtests/unit/test_chat_transport.py341# which exercises a real ``TransportDrainTracker`` end-to-end rather
LOWtests/unit/test_cassette_patterns.py641
LOWtests/unit/test_vcr_body_matcher.py101# is the spec's "widen the volatile-key scrub list" escape hatch applied at
LOWtests/unit/test_source_selection.py121 # SimpleNamespace constructor satisfies the policy by setting every
LOWtests/unit/cli/test_download.py2061# `helpers.handle_error()` shim that always exits 1 with a text-only message
168 more matches not shown…
Cross-File Repetition25 hits · 125 pts
SeverityFileLineSnippet
HIGHtests/unit/test_composition_primitives.py0sentinel callable — identity-checked, never invoked.
HIGHtests/unit/test_composition_primitives.py0sentinel callable — identity-checked, never invoked.
HIGHtests/unit/test_composition_primitives.py0sentinel callable — identity-checked, never invoked.
HIGHtests/unit/test_composition_primitives.py0sentinel callable — identity-checked, never invoked.
HIGHtests/unit/test_row_adapters.py0the adapter is frozen so the wrapped row can't be swapped out.
HIGHtests/unit/test_row_adapters.py0the adapter is frozen so the wrapped row can't be swapped out.
HIGHtests/unit/test_row_adapters.py0the adapter is frozen so the wrapped row can't be swapped out.
HIGHtests/unit/cli/test_artifact.py0path a: uuid-shaped id skips partial-resolve; backend none → exit 1.
HIGHtests/unit/cli/test_source.py0path a: uuid-shaped id skips partial-resolve; backend none → exit 1.
HIGHtests/unit/cli/test_note.py0path a: uuid-shaped id skips partial-resolve; backend none → exit 1.
HIGHtests/unit/cli/test_artifact.py0path a under ``--json``: typed json error doc + exit 1.
HIGHtests/unit/cli/test_source.py0path a under ``--json``: typed json error doc + exit 1.
HIGHtests/unit/cli/test_note.py0path a under ``--json``: typed json error doc + exit 1.
HIGHtests/unit/cli/test_artifact.py0path b: partial-resolve succeeds, backend get() returns none → exit 1.
HIGHtests/unit/cli/test_source.py0path b: partial-resolve succeeds, backend get() returns none → exit 1.
HIGHtests/unit/cli/test_note.py0path b: partial-resolve succeeds, backend get() returns none → exit 1.
HIGH…ts/integration/test_artifact_generation_idempotency.py0extract the ``rpcids=`` query param from a batchexecute request url.
HIGHtests/integration/test_research_idempotency.py0extract the ``rpcids=`` query param from a batchexecute request url.
HIGHtests/integration/test_side_effects_idempotency.py0extract the ``rpcids=`` query param from a batchexecute request url.
HIGHtests/integration/test_notes_idempotency.py0extract the ``rpcids=`` query param from a batchexecute request url.
HIGH…sts/integration/concurrency/test_idempotency_create.py0extract the ``rpcids=`` query param from a batchexecute request url.
HIGH…sts/integration/concurrency/test_note_create_cancel.py0extract the ``rpcids=`` query param from a batchexecute request url.
HIGHsrc/notebooklm/_types/research.py0return the historical compatibility dictionary shape.
HIGHsrc/notebooklm/_types/research.py0return the historical compatibility dictionary shape.
HIGHsrc/notebooklm/_types/research.py0return the historical compatibility dictionary shape.
Excessive Try-Catch Wrapping94 hits · 92 pts
SeverityFileLineSnippet
LOWtests/unit/test_windows_compatibility.py316 except Exception as e:
LOWtests/unit/concurrency/test_close_cancellation_leak.py369 except Exception:
LOWtests/integration/test_chat_delete_conversation_vcr.py144 except Exception as exc: # noqa: BLE001
LOWtests/integration/test_chat_multi_source_vcr.py277 except Exception as exc: # noqa: BLE001 — best-effort cleanup
LOWtests/integration/concurrency/test_add_file_toctou.py235 except Exception: # noqa: BLE001 — defensive
LOWtests/scripts/setup-generation-notebook.py74 except Exception as exc: # noqa: BLE001 — top-level CLI surface
MEDIUMtests/e2e/conftest.py47def _ask_with_skip(*args, **kwargs):
LOWtests/e2e/conftest.py407 except Exception as e:
LOWtests/e2e/conftest.py468 except Exception:
LOWtests/e2e/conftest.py583 except Exception:
LOWtests/e2e/conftest.py592 except Exception:
LOWtests/e2e/conftest.py661 except Exception as e:
LOWtests/e2e/conftest.py687 except Exception:
LOWtests/e2e/conftest.py705 except Exception:
LOWtests/e2e/conftest.py548 except Exception:
LOWtests/e2e/conftest.py550 except Exception:
LOWtests/e2e/conftest.py561 except Exception:
LOWtests/e2e/conftest.py563 except Exception:
LOWtests/e2e/conftest.py795 except Exception:
LOWtests/e2e/conftest.py797 except Exception:
LOWtests/e2e/conftest.py857 except Exception as e:
LOWtests/e2e/test_downloads.py132 except Exception:
LOWdocs/rpc-reference.md117 except Exception:
LOWdocs/examples/notes.py157 except Exception as e:
LOWdocs/examples/bulk-import.py64 except Exception as e:
LOWdocs/examples/bulk-import.py75 except Exception as e:
LOWdocs/examples/bulk-import.py86 except Exception as e:
LOWdocs/examples/chat.py102 except Exception as e:
LOWscripts/diagnose_get_notebook.py130 except Exception as e:
LOWscripts/audit_public_api_compat.py317 except Exception as exc:
LOWscripts/check_rpc_health.py912 except Exception as e:
LOWscripts/check_rpc_health.py928 except Exception as e:
LOWscripts/check_rpc_health.py944 except Exception as e:
LOWscripts/check_rpc_health.py953 except Exception as e:
MEDIUMsrc/notebooklm/_source_upload.py809def _probe() -> str | None:
LOWsrc/notebooklm/_source_upload.py181 except Exception: # noqa: BLE001 - hint lookup must not mask the upload error.
LOWsrc/notebooklm/_source_upload.py801 except Exception:
LOWsrc/notebooklm/_source_upload.py817 except Exception:
LOWsrc/notebooklm/_source_upload.py1138 except Exception as close_exc: # noqa: BLE001
LOWsrc/notebooklm/_source_upload.py1164 except Exception as exc: # noqa: BLE001
LOWsrc/notebooklm/_source_upload.py1174 except Exception as close_exc: # noqa: BLE001
LOWsrc/notebooklm/_source_upload.py1202 except Exception as exc: # noqa: BLE001
LOWsrc/notebooklm/_auth_refresh_retry.py139 except Exception as refresh_error:
LOWsrc/notebooklm/_chat_wire.py441 except Exception:
LOWsrc/notebooklm/client.py663 except Exception as close_exc:
LOWsrc/notebooklm/_runtime_lifecycle.py507 except Exception as e:
LOWsrc/notebooklm/_runtime_lifecycle.py583 except Exception as exc: # noqa: BLE001 - opportunistic best-effort
LOWsrc/notebooklm/_runtime_lifecycle.py595 except Exception as exc: # noqa: BLE001
LOWsrc/notebooklm/_notebooks.py334 except Exception:
LOWsrc/notebooklm/_notebooks.py384 except Exception:
LOWsrc/notebooklm/_notebooks.py424 except Exception:
LOWsrc/notebooklm/_notebooks.py438 except Exception:
MEDIUMsrc/notebooklm/_notebooks.py341def _create() -> Notebook:
LOWsrc/notebooklm/_source_add.py94 except Exception:
LOWsrc/notebooklm/_source_add.py258 except Exception:
MEDIUMsrc/notebooklm/_source_add.py84def _probe() -> Source | None:
MEDIUMsrc/notebooklm/_source_add.py251def _probe() -> Source | None:
LOWsrc/notebooklm/_middleware_metrics.py112 except Exception as exc:
LOWsrc/notebooklm/_middleware_tracing.py115 except Exception as exc:
LOWsrc/notebooklm/_client_metrics.py146 except Exception as exc: # noqa: BLE001 - observability must not alter behavior
34 more matches not shown…
Deep Nesting104 hits · 92 pts
SeverityFileLineSnippet
LOWtests/vcr_config.py460
LOWtests/vcr_config.py512
LOWtests/_lint/test_no_session.py60
LOWtests/_lint/test_no_session_compat_bridges.py165
LOWtests/_lint/test_session_runtime_boundaries.py162
LOWtests/_lint/test_session_runtime_boundaries.py259
LOWtests/_lint/test_session_runtime_boundaries.py329
LOWtests/_lint/test_client_composition.py77
LOWtests/_lint/test_no_legacy_rpc_callable_aliases.py73
LOWtests/_lint/test_no_legacy_rpc_callable_aliases.py95
LOWtests/_lint/test_no_core_imports.py73
LOWtests/_lint/test_asyncio_loop_affinity_guard.py234
LOWtests/unit/test_middleware_context_contract.py92
LOWtests/unit/test_streaming_chat_wire.py543
LOWtests/unit/test_concurrency_refresh_race.py425
LOWtests/unit/test_cli_boundary.py178
LOWtests/unit/test_cli_boundary.py209
LOWtests/unit/test_cli_boundary.py242
LOWtests/unit/test_cli_boundary.py343
LOWtests/unit/test_cli_boundary.py430
LOWtests/unit/test_cli_boundary.py541
LOWtests/unit/test_public_surface.py188
LOWtests/unit/test_type_boundaries.py59
LOWtests/unit/test_type_boundaries.py134
LOWtests/unit/test_type_boundaries.py162
LOWtests/unit/test_type_boundaries.py185
LOWtests/unit/test_init_order.py900
LOWtests/unit/test_rpc_types.py22
LOWtests/unit/test_public_shims.py579
LOWtests/unit/test_install_docs.py88
LOWtests/unit/test_install_docs.py215
LOWtests/unit/test_rpc_overrides.py59
LOWtests/unit/cli/test_quiet_enforcement.py109
LOWtests/integration/test_sources_integration.py1711
LOWtests/integration/concurrency/helpers.py55
LOWtests/scripts/check_cassettes_clean.py136
LOWtests/scripts/compress_polling_cassette.py120
LOWtests/e2e/conftest.py264
LOWtests/e2e/conftest.py537
LOWdocs/examples/notes.py23
LOWscripts/diagnose_get_notebook.py136
LOWscripts/check_deprecation_targets.py166
LOWscripts/audit_test_suite.py99
LOWscripts/audit_test_suite.py114
LOWscripts/audit_test_suite.py171
LOWscripts/audit_public_api_compat.py329
LOWscripts/audit_public_api_compat.py395
LOWscripts/check_workflow_secret_gates.py227
LOWscripts/check_ci_install_parity.py55
LOWscripts/check_rpc_health.py668
LOWsrc/notebooklm/_research.py590
LOWsrc/notebooklm/_research.py710
LOWsrc/notebooklm/_source_upload.py1064
LOWsrc/notebooklm/_source_upload.py1102
LOWsrc/notebooklm/_research_task_parser.py172
LOWsrc/notebooklm/paths.py361
LOWsrc/notebooklm/_chat_wire.py264
LOWsrc/notebooklm/_chat_wire.py427
LOWsrc/notebooklm/_chat_wire.py608
LOWsrc/notebooklm/_chat.py562
44 more matches not shown…
Verbosity Indicators31 hits · 58 pts
SeverityFileLineSnippet
LOWtests/unit/test_cookie_domain_split.py348 # Step 2: storage_state → DomainCookieMap (used by AuthTokens).
LOWtests/unit/test_cookie_domain_split.py354 # Step 3: storage_state → httpx jar (used by downloads + refresh).
LOWtests/unit/test_cookie_domain_split.py362 # Step 4: the runtime gate itself accepts every YouTube variant.
LOWtests/unit/test_cookie_domain_split.py337 # Step 1: rookiepy → storage_state conversion must keep the YouTube
LOWtests/integration/test_sources_integration.py714 # Step 0: register_file_source captures a baseline GET_NOTEBOOK
LOWtests/integration/test_sources_integration.py717 # Step 1: Mock RPC registration response (o4cbdc)
LOWtests/integration/test_sources_integration.py727 # Step 2: Mock upload session start response
LOWtests/integration/test_sources_integration.py737 # Step 3: Mock upload finalize response
LOWtests/integration/test_sources_integration.py931 # Step 0: Baseline GET_NOTEBOOK for the register_file_source probe wrapper.
LOWtests/integration/test_sources_integration.py933 # Step 1: Mock RPC registration
LOWtests/integration/test_sources_integration.py943 # Step 2: Mock upload session start
LOWtests/integration/test_sources_integration.py953 # Step 3: Mock upload finalize
LOWtests/integration/test_sources_integration.py2680 # Step 0: Baseline GET_NOTEBOOK for the register_file_source probe wrapper.
LOWtests/integration/test_sources_integration.py2682 # Step 1: Successful RPC registration
LOWtests/integration/test_sources_integration.py2692 # Step 2: Upload session response WITHOUT the required upload URL header
LOWtests/e2e/test_research_import_verification.py42 # Step 1: Start fast web research
LOWtests/e2e/test_research_import_verification.py56 # Step 2: Poll until complete
LOWtests/e2e/test_research_import_verification.py74 # Step 3: Get sources to import
LOWtests/e2e/test_research_import_verification.py88 # Step 4: Import sources. Use the verification-aware variant so an
LOWtests/e2e/test_research_import_verification.py99 # Step 5: Poll for imported sources to appear
LOWtests/e2e/test_research_import_verification.py111 # Step 6: Verify source count
LOWtests/e2e/test_research.py199 # Step 1: Start research
LOWtests/e2e/test_research.py210 # Step 2: Poll until complete
LOWtests/e2e/test_research.py232 # Step 3: Import sources (if any found)
LOWdocs/examples/video.py26 # Step 1: Create a notebook with content
LOWdocs/examples/video.py45 # Step 2: Generate the video overview
LOWdocs/examples/video.py78 # Step 3: Wait for completion with status updates
LOWdocs/examples/video.py93 # Step 4: Download the video
LOWsrc/notebooklm/cli/download_helpers.py122 # Step 1: Filter
LOWsrc/notebooklm/cli/download_helpers.py140 # Step 2: Count
LOWsrc/notebooklm/cli/download_helpers.py143 # Step 3: Select
AI Slop Vocabulary17 hits · 54 pts
SeverityFileLineSnippet
MEDIUMtests/cassette_patterns.py181 # fixed number of characters) is robust to alternate-length prefixes if
MEDIUMtests/vcr_config.py318# matcher robust across recording sessions while still failing on meaningful
MEDIUMtests/vcr_config.py643 # or extra non-volatile dict keys — while staying robust against leaf
MEDIUMtests/unit/test_json_stdout_purity.py361# so the mock-client harness can't drive them. The parametrized sweep
MEDIUMtests/unit/test_json_stdout_purity.py509 # the mock-client harness. `notebook_create` goes through the standard
MEDIUMtests/unit/test_json_stdout_purity.py534 # harness — they read NOTEBOOKLM_HOME directly. Stage a clean layout
MEDIUMtests/unit/test_auth_cookie_save_race.py1716 # order) to stay robust across schedulers.
MEDIUMtests/unit/test_json_error_exit.py613 # then invoke without the mock-client harness (these commands don't
MEDIUMtests/unit/test_json_error_exit.py588# Filesystem-driven failure cases bypass the mock-client harness — they
MEDIUMtests/unit/test_vcr_body_matcher.py209# Volatile-key stripping — keep matching robust across recording timestamps
MEDIUMtests/integration/concurrency/test_harness_smoke.py50# concurrency-harness smoke tests against a mock transport; no
MEDIUMtests/integration/concurrency/test_harness_smoke.py138 # Peak in-flight was high — the harness is genuinely fanning out.
MEDIUM…ts/integration/concurrency/test_max_concurrent_rpcs.py71# concurrency-harness tests against a mock transport; no HTTP,
MEDIUM…ts/integration/concurrency/test_max_concurrent_rpcs.py155 # Anything <= 8 would mean the gate isn't kicking in (the harness
MEDIUMtests/e2e/test_research_import_verification.py92 # makes this path robust for fast-mode imports too.
LOWsrc/notebooklm/_sharing.py128 # Fetch current status and override view_level with what we just set
MEDIUMsrc/notebooklm/_atomic_io.py229 # and re-introduce the divergent-lock race. ``casefold`` is the robust
Self-Referential Comments16 hits · 44 pts
SeverityFileLineSnippet
MEDIUMtests/unit/test_artifact_downloads.py764 # Create the complex nested structure for data table
MEDIUMtests/unit/test_sources_upload.py922 # Create a temp file
MEDIUMtests/unit/cli/test_resolve.py333 # Create a notebook with a short ID that we'll match exactly
MEDIUMtests/unit/cli/test_source.py306 # Create a temp file
MEDIUMtests/unit/cli/test_skill.py757 # Create a sibling file to make skills/ non-empty after notebooklm/ is gone
MEDIUMtests/unit/cli/test_language.py230 # Create the file so exists() returns True, then mock read_text to raise OSError
MEDIUMtests/integration/test_vcr_comprehensive.py748 # Create a test file
MEDIUMtests/integration/test_vcr_comprehensive.py838 # Create a source to delete
MEDIUMtests/integration/test_vcr_comprehensive.py876 # Create a notebook to delete
MEDIUMtests/integration/test_vcr_comprehensive.py908 # Create a note to delete
MEDIUMtests/e2e/test_artifacts.py248 # Create a quiz artifact for deletion (different type than flashcards)
MEDIUMtests/e2e/test_sources.py123 # Create a source to delete
MEDIUMdocs/examples/notes.py49 # Create a new note with title and content
MEDIUMdocs/examples/notes.py27 # Create a notebook for our examples
MEDIUMdocs/examples/chat.py23 # Create a notebook with some content
MEDIUMsrc/notebooklm/notebooklm_cli.py167 notebooklm create "My Notes" # Create a notebook
Fake / Example Data33 hits · 33 pts
SeverityFileLineSnippet
LOWtests/unit/test_chat_ask_invariants.py86 account_email="user@example.com",
LOWtests/unit/test_chat_ask_invariants.py107 assert _extract_query_param(str(request.url), "authuser") == "user@example.com"
LOWtests/unit/test_token_regex.py47 assert value == "user@example.com"
LOWtests/unit/test_sharing_types.py14 data = ["user@example.com", 3, [], ["Test User", "https://avatar.url"]]
LOWtests/unit/test_sharing_types.py17 assert user.email == "user@example.com"
LOWtests/unit/test_sharing_types.py41 data = ["user@example.com", 2, []]
LOWtests/unit/test_sharing_types.py44 assert user.email == "user@example.com"
LOWtests/unit/test_sharing_types.py51 data = ["user@example.com", 99, []]
LOWtests/unit/test_sharing_types.py58 data = ["user@example.com", {"permission": 3}, []]
LOWtests/unit/test_sharing_types.py73 data = ["user@example.com", 3, [], ["Just Name"]]
LOWtests/unit/cli/test_share.py163 result = runner.invoke(cli, ["share", "add", "user@example.com", "-n", "nb_123"])
LOWtests/unit/cli/test_share.py170 "user@example.com",
LOWtests/unit/cli/test_share.py193 ["share", "add", "user@example.com", "-n", "nb_123", "-p", "editor"],
LOWtests/unit/cli/test_share.py200 "user@example.com",
LOWtests/unit/cli/test_share.py229 cli, ["share", "remove", "user@example.com", "-n", "nb_123", "-y"]
LOWtests/unit/cli/test_share.py234 mock_client.sharing.remove_user.assert_called_once_with("nb_123", "user@example.com")
LOWtests/unit/cli/test_share.py275 cli, ["share", "remove", "user@example.com", "-n", "nb_123", "--json"]
LOWtests/unit/cli/test_share.py279 assert '"removed_user": "user@example.com"' in result.output
LOWtests/unit/cli/test_share.py300 cli, ["share", "remove", "user@example.com", "-n", "nb_123", "--json"]
LOWtests/unit/cli/test_share.py304 assert '"removed_user": "user@example.com"' in result.output
LOWtests/unit/cli/test_share.py306 mock_client.sharing.remove_user.assert_called_once_with("nb_123", "user@example.com")
LOWtests/unit/cli/test_share.py464 "user@example.com",
LOWtests/unit/cli/test_share.py474 assert '"updated_user": "user@example.com"' in result.output
LOWtests/unit/cli/test_share.py546 cli, ["share", "add", "user@example.com", "-n", "nb_123", "--json"]
LOWtests/unit/cli/test_share.py550 assert '"added_user": "user@example.com"' in result.output
LOWtests/unit/cli/test_share.py252 cli, ["share", "remove", "user@example.com", "-n", "nb_123"], input="n\n"
LOWtests/unit/cli/test_share.py434 ["share", "update", "user@example.com", "-n", "nb_123", "-p", "editor"],
LOWtests/unit/cli/test_share.py441 "nb_123", "user@example.com", SharePermission.EDITOR
LOWtests/unit/cli/test_session_characterization.py173 result = char_runner.invoke(cli, ["login", "--account", "user@example.com"])
LOWtests/integration/test_sharing_integration.py343 ["user@example.com", 2, [], ["User", "https://avatar"]], # Now editor
LOWtests/integration/test_sharing_integration.py354 "user@example.com",
LOWdocs/rpc-reference.md1330await client.sharing.add_user(notebook_id, "user@example.com", SharePermission.VIEWER)
LOWsrc/notebooklm/_sharing.py30 "user@example.com",
Hallucination Indicators2 hits · 20 pts
SeverityFileLineSnippet
CRITICALtests/unit/cli/test_generate.py976 assert not mock_client.mind_maps.generate.await_args.kwargs.get("instructions")
CRITICALtests/unit/cli/test_resolver_characterization.py405 passed_conv_id = mock_client.chat.ask.await_args.kwargs.get("conversation_id")
Redundant / Tautological Comments12 hits · 19 pts
SeverityFileLineSnippet
LOWtests/unit/test_windows_compatibility.py265 # Check if UTF-8 mode is active (either via flag or env var)
LOWtests/unit/test_auth_storage.py137 # Set NOTEBOOKLM_HOME to tmp_path and create a file there
LOWtests/e2e/test_chat.py67 # Check if any references have cited_text
LOWscripts/check_rpc_health.py639 # Check if error response still contains our expected ID
LOWscripts/check_rpc_health.py656 # Check if expected ID is in response
LOWscripts/check_rpc_health.py866 # Check if status indicates completion (status code 3 = ready)
LOW.github/workflows/nightly.yml54 # Check if it's main or a release branch
LOWsrc/notebooklm/_auth/refresh.py702 # Check if we were redirected to login
LOWsrc/notebooklm/_auth/cookie_policy.py527 # Check if it's a valid Google domain (base or regional)
LOWsrc/notebooklm/_auth/cookie_policy.py541 # Check if domain is a subdomain of allowed suffixes
LOWsrc/notebooklm/cli/chat_cmd.py47 # Check if user switched notebooks via --notebook flag
LOWsrc/notebooklm/cli/artifact_cmd.py305 # Check if this is a mind map (stored with notes)
Synthetic Comment Markers2 hits · 15 pts
SeverityFileLineSnippet
HIGHdocs/python-api.md922# Get AI-generated description (parsed with suggested topics)
HIGHdocs/python-api.md1014# Get AI-generated summary and keywords (returns a typed SourceGuide)