Cyclomatic Complexity and Maintainability Index Analysis
| File | Function | Type | Complexity | Rating |
|---|---|---|---|---|
| apps/recipes/services/image_cache.py | _fetch_image_safe | method | 14 | C |
| apps/recipes/services/sanitizer.py | sanitize_recipe_data | function | 14 | C |
| apps/core/management/commands/_cookie_admin_app.py | _handle_prompts_set | method | 13 | C |
| apps/ai/api_discover.py | discover_endpoint | function | 13 | C |
| apps/recipes/services/scraper.py | _fetch_image_with_redirects | method | 12 | C |
| apps/core/passkey_api.py | login_verify | function | 12 | C |
| apps/core/management/commands/_cookie_admin_resources.py | _handle_rename | method | 12 | C |
| apps/core/management/commands/_cookie_admin_app.py | _handle_reset | method | 11 | C |
| apps/ai/api_scaling.py | scale_recipe_endpoint | function | 11 | C |
| apps/recipes/management/commands/cleanup_search_images.py | handle | method | 10 | B |
| apps/recipes/services/scraper.py | _fetch_with_redirects | method | 10 | B |
| apps/core/middleware.py | _home_only_patterns | function | 10 | B |
| apps/core/management/commands/_cookie_admin_users.py | _collect_status | method | 10 | B |
| apps/ai/api.py | timer_name_endpoint | function | 10 | B |
| apps/ai/services/remix.py | create_remix | function | 10 | B |
| apps/recipes/services/search_parsers.py | extract_result_from_element | function | 9 | B |
| apps/legacy/views.py | recipe_detail | function | 9 | B |
| apps/core/auth.py | _authenticate_passkey | method | 9 | B |
| apps/core/device_code_api.py | poll_status | function | 9 | B |
| apps/ai/tests.py | test_sources_needing_attention_endpoint | method | 9 | B |
| apps/ai/api.py | tips_endpoint | function | 9 | B |
| apps/ai/services/quota.py | reserve_quota | function | 9 | B |
| apps/ai/services/remix.py | estimate_nutrition | function | 9 | B |
| apps/recipes/api.py | scrape_recipe | function | 8 | B |
| apps/recipes/services/search_classifiers.py | _check_path_heuristics | function | 8 | B |
| apps/recipes/services/search_classifiers.py | looks_like_recipe_title | function | 8 | B |
| apps/recipes/services/scraper.py | _convert_webp_to_jpeg | method | 8 | B |
| apps/recipes/services/search_parsers.py | _collect_srcset_strings | function | 8 | B |
| apps/recipes/services/search.py | _fetch_url | method | 8 | B |
| apps/profiles/api.py | update_preferences | function | 8 | B |
| apps/core/passkey_api.py | register_verify | function | 8 | B |
| apps/core/api.py | reset_database | function | 8 | B |
| apps/core/management/commands/_cookie_admin_users.py | _resolve_user_by_username_or_profile_id | method | 8 | B |
| apps/core/management/commands/_cookie_admin_resources.py | _handle_sources_test | method | 8 | B |
| apps/ai/tests.py | test_ai_status_endpoint | method | 8 | B |
| apps/ai/tests.py | test_repair_selector_success | method | 8 | B |
| apps/ai/api_remix.py | remix_suggestions | function | 8 | B |
| apps/ai/api_remix.py | create_remix_endpoint | function | 8 | B |
| apps/ai/api.py | update_prompt | function | 8 | B |
| apps/ai/services/discover.py | _generate_recommended_suggestions | function | 8 | B |
| apps/ai/services/discover.py | _generate_new_suggestions | function | 8 | B |
| apps/ai/services/openrouter.py | get_available_models | method | 8 | B |
| apps/ai/services/openrouter.py | validate_key_cached | method | 8 | B |
| apps/ai/services/timer.py | generate_timer_name | function | 8 | B |
| apps/recipes/utils.py | tidy_ingredient | function | 7 | B |
| apps/recipes/api.py | _cache_and_map_images | function | 7 | B |
| apps/recipes/api.py | get_recipe | function | 7 | B |
| apps/recipes/services/image_cache.py | SearchImageCache | class | 7 | B |
| apps/recipes/services/image_cache.py | _download_and_save | method | 7 | B |
| apps/recipes/services/image_cache.py | _convert_to_jpeg | method | 7 | B |
| apps/recipes/services/scraper.py | scrape_url | method | 7 | B |
| apps/recipes/services/search.py | _filter_relevant | method | 7 | B |
| apps/core/logging.py | JSONFormatter | class | 7 | B |
| apps/core/management/commands/_cookie_admin_users.py | _handle_list_users | method | 7 | B |
| apps/core/management/commands/_cookie_admin_users.py | _handle_create_session | method | 7 | B |
| apps/core/management/commands/cookie_admin.py | handle | method | 7 | B |
| apps/ai/tests.py | test_ai_status_no_api_key | method | 7 | B |
| apps/ai/tests.py | test_ai_status_valid_api_key | method | 7 | B |
| apps/ai/tests.py | test_validate_key_cached_caches_result | method | 7 | B |
| apps/ai/tests.py | test_cache_decorator_caches_result | method | 7 | B |
| apps/ai/tests.py | test_parse_time_remix | method | 7 | B |
| apps/ai/tests.py | test_parse_servings | method | 7 | B |
| apps/ai/services/tips.py | generate_tips | function | 7 | B |
| apps/ai/services/openrouter.py | complete | method | 7 | B |
| apps/ai/services/openrouter.py | complete_async | method | 7 | B |
| apps/ai/services/scaling.py | calculate_nutrition | function | 7 | B |
| apps/recipes/utils.py | _find_closest_fraction | function | 6 | B |
| apps/recipes/services/search_classifiers.py | _skinnytaste_signal | function | 6 | B |
| apps/recipes/services/scraper.py | _fetch_html | method | 6 | B |
| apps/recipes/services/scraper.py | _download_image | method | 6 | B |
| apps/recipes/services/search_parsers.py | find_link | function | 6 | B |
| apps/recipes/services/search_parsers.py | extract_image | function | 6 | B |
| apps/recipes/services/search_parsers.py | _parse_links | function | 6 | B |
| apps/recipes/services/search.py | _search_source | method | 6 | B |
| apps/recipes/services/search.py | _try_fetch_and_parse | method | 6 | B |
| apps/core/passkey_api.py | add_credential_verify | function | 6 | B |
| apps/core/logging.py | format | method | 6 | B |
| apps/core/auth.py | SessionAuth | class | 6 | B |
| apps/core/device_code_api.py | request_code | function | 6 | B |
| apps/core/management/commands/_cookie_admin_app.py | AppConfigMixin | class | 6 | B |
| apps/core/management/commands/_cookie_admin_users.py | _format_audit_event | method | 6 | B |
| apps/core/management/commands/_cookie_admin_users.py | _handle_usage | method | 6 | B |
| apps/core/management/commands/cleanup_device_codes.py | handle | method | 6 | B |
| apps/ai/tests.py | test_ai_status_invalid_api_key | method | 6 | B |
| apps/ai/tests.py | test_validate_key_cached_caches_invalid_result | method | 6 | B |
| apps/ai/tests.py | test_repair_selector_low_confidence_no_update | method | 6 | B |
| apps/ai/tests.py | test_get_sources_needing_attention | method | 6 | B |
| apps/ai/tests.py | test_repair_selector_endpoint_success | method | 6 | B |
| apps/ai/services/ranking.py | _score_result | function | 6 | B |
| apps/ai/services/openrouter.py | OpenRouterService | class | 6 | B |
| apps/ai/services/openrouter.py | _parse_json_response | method | 6 | B |
| apps/ai/services/scaling.py | _format_time | function | 6 | B |
| apps/recipes/utils.py | decimal_to_fraction | function | 5 | A |
| apps/recipes/api.py | search_recipes | function | 5 | A |
| apps/recipes/sources_api.py | test_all_sources | function | 5 | A |
| apps/recipes/sources_api.py | test_source | function | 5 | A |
| apps/recipes/management/commands/cleanup_search_images.py | Command | class | 5 | A |
| apps/recipes/services/image_cache.py | _fetch_image | method | 5 | A |
| apps/recipes/services/image_cache.py | _looks_like_image | method | 5 | A |
| apps/recipes/services/search_classifiers.py | get_url_signal | function | 5 | A |
| File | Maintainability Index | Rating |
|---|---|---|
| apps/ai/tests.py | 0.0 | C |
| apps/core/management/commands/_cookie_admin_users.py | 32.0 | A |
| apps/ai/services/openrouter.py | 38.1 | A |
| apps/recipes/services/scraper.py | 40.2 | A |
| apps/core/passkey_api.py | 41.4 | A |
| apps/ai/api.py | 41.5 | A |
| apps/recipes/services/search.py | 42.0 | A |
| apps/recipes/api.py | 43.4 | A |
| apps/core/management/commands/_cookie_admin_app.py | 44.6 | A |
| apps/core/management/commands/_cookie_admin_resources.py | 46.0 | A |
| apps/recipes/sources_api.py | 47.9 | A |
| apps/legacy/views.py | 50.7 | A |
| apps/recipes/services/search_parsers.py | 52.3 | A |
| apps/profiles/api.py | 52.8 | A |
| apps/ai/api_remix.py | 53.5 | A |
| apps/core/migrations/0009_lower_ai_quota_defaults_further.py | 54.7 | A |
| apps/core/migrations/0008_lower_ai_quota_defaults.py | 54.7 | A |
| apps/recipes/api_user.py | 55.1 | A |
| apps/ai/services/discover.py | 56.0 | A |
| apps/recipes/services/image_cache.py | 56.0 | A |
| apps/core/device_code_api.py | 56.7 | A |
| apps/ai/services/scaling.py | 58.0 | A |
| apps/core/models.py | 58.1 | A |
| apps/core/middleware.py | 59.7 | A |
| apps/core/tests.py | 59.9 | A |
| apps/core/api.py | 62.4 | A |
| apps/recipes/services/search_classifiers.py | 62.5 | A |
| apps/ai/fixtures.py | 63.1 | A |
| apps/ai/services/remix.py | 63.2 | A |
| apps/ai/services/quota.py | 63.3 | A |
| cookie/settings.py | 63.4 | A |
| apps/core/management/commands/cookie_admin.py | 63.5 | A |
| apps/ai/api_scaling.py | 64.7 | A |
| apps/ai/services/validator.py | 64.8 | A |
| apps/core/management/commands/cleanup_device_codes.py | 65.5 | A |
| apps/ai/api_discover.py | 65.6 | A |
| apps/ai/api_quotas.py | 65.9 | A |
| apps/recipes/utils.py | 65.9 | A |
| apps/core/validators.py | 66.1 | A |
| apps/core/auth_api.py | 67.1 | A |
| apps/recipes/management/commands/cleanup_search_images.py | 70.3 | A |
| apps/recipes/services/fingerprint.py | 71.6 | A |
| apps/core/auth.py | 72.2 | A |
| apps/core/auth_helpers.py | 72.3 | A |
| apps/recipes/services/source_health.py | 75.5 | A |
| apps/ai/services/selector.py | 75.9 | A |
| apps/ai/services/cache.py | 76.9 | A |
| apps/legacy/templatetags/legacy_tags.py | 80.3 | A |
| apps/ai/services/timer.py | 80.3 | A |
| apps/core/encryption.py | 81.9 | A |
| apps/core/cache.py | 83.8 | A |
| apps/ai/services/ranking.py | 83.8 | A |
| apps/ai/services/tips.py | 85.1 | A |
| apps/core/logging.py | 85.3 | A |
| apps/profiles/models.py | 86.0 | A |
| apps/profiles/utils.py | 87.0 | A |
| apps/__init__.py | 100.0 | A |
| apps/recipes/tests.py | 100.0 | A |
| apps/recipes/models.py | 100.0 | A |
| apps/recipes/__init__.py | 100.0 | A |
| apps/recipes/migrations/0013_update_broken_selectors.py | 100.0 | A |
| apps/recipes/migrations/0008_rename_recipes_rec_profile_idx_recipes_rec_profile_7945b8_idx.py | 100.0 | A |
| apps/recipes/migrations/0010_add_remixed_from_field.py | 100.0 | A |
| apps/recipes/migrations/0004_cachedsearchimage.py | 100.0 | A |
| apps/recipes/migrations/0002_populate_search_sources.py | 100.0 | A |
| apps/recipes/migrations/0012_add_title_index.py | 100.0 | A |
| apps/recipes/migrations/0005_serving_adjustment.py | 100.0 | A |
| apps/recipes/migrations/0006_serving_adjustment_instructions_times.py | 100.0 | A |
| apps/recipes/migrations/0009_add_default_selectors.py | 100.0 | A |
| apps/recipes/migrations/0003_recipecollection_recipecollectionitem_recipefavorite_and_more.py | 100.0 | A |
| apps/recipes/migrations/0007_recipe_profile.py | 100.0 | A |
| apps/recipes/migrations/0001_initial.py | 100.0 | A |
| apps/recipes/migrations/__init__.py | 100.0 | A |
| apps/recipes/migrations/0011_update_allrecipes_selector.py | 100.0 | A |
| apps/recipes/management/__init__.py | 100.0 | A |
| apps/recipes/management/commands/__init__.py | 100.0 | A |
| apps/recipes/services/sanitizer.py | 100.0 | A |
| apps/recipes/services/__init__.py | 100.0 | A |
| apps/legacy/apps.py | 100.0 | A |
| apps/legacy/__init__.py | 100.0 | A |
| apps/legacy/urls.py | 100.0 | A |
| apps/legacy/templatetags/__init__.py | 100.0 | A |
| apps/profiles/apps.py | 100.0 | A |
| apps/profiles/deletion.py | 100.0 | A |
| apps/profiles/__init__.py | 100.0 | A |
| apps/profiles/migrations/0003_add_unlimited_ai.py | 100.0 | A |
| apps/profiles/migrations/0002_add_user_field.py | 100.0 | A |
| apps/profiles/migrations/0001_initial.py | 100.0 | A |
| apps/profiles/migrations/__init__.py | 100.0 | A |
| apps/core/apps.py | 100.0 | A |
| apps/core/views.py | 100.0 | A |
| apps/core/context_processors.py | 100.0 | A |
| apps/core/__init__.py | 100.0 | A |
| apps/core/migrations/0007_remove_devicecode_attempts_remaining.py | 100.0 | A |
| apps/core/migrations/0002_alter_appsettings_default_ai_model.py | 100.0 | A |
| apps/core/migrations/0003_passkey_webauthn_devicecode.py | 100.0 | A |
| apps/core/migrations/0006_add_ai_quota_fields.py | 100.0 | A |
| apps/core/migrations/0001_initial.py | 100.0 | A |
| apps/core/migrations/__init__.py | 100.0 | A |
| apps/core/migrations/0004_passkey_model_fixes.py | 100.0 | A |
| apps/core/migrations/0005_passkey_field_fixes.py | 100.0 | A |
| apps/core/management/__init__.py | 100.0 | A |
| apps/core/management/commands/createsuperuser.py | 100.0 | A |
| apps/core/management/commands/cleanup_sessions.py | 100.0 | A |
| apps/core/management/commands/__init__.py | 100.0 | A |
| apps/ai/models.py | 100.0 | A |
| apps/ai/__init__.py | 100.0 | A |
| apps/ai/migrations/0004_update_serving_adjustment_prompt.py | 100.0 | A |
| apps/ai/migrations/0007_update_search_ranking_prompt.py | 100.0 | A |
| apps/ai/migrations/0008_update_serving_adjustment_indivisible.py | 100.0 | A |
| apps/ai/migrations/0002_seed_prompts.py | 100.0 | A |
| apps/ai/migrations/0003_nutrition_estimate_prompt.py | 100.0 | A |
| apps/ai/migrations/0006_add_ai_discovery_suggestion.py | 100.0 | A |
| apps/ai/migrations/0011_remove_search_ranking_prompt.py | 100.0 | A |
| apps/ai/migrations/0010_alter_aiprompt_model.py | 100.0 | A |
| apps/ai/migrations/0005_update_serving_adjustment_v2.py | 100.0 | A |
| apps/ai/migrations/0009_fix_discover_prompts.py | 100.0 | A |
| apps/ai/migrations/0001_initial.py | 100.0 | A |
| apps/ai/migrations/__init__.py | 100.0 | A |
| apps/ai/services/__init__.py | 100.0 | A |
| cookie/wsgi.py | 100.0 | A |
| cookie/__init__.py | 100.0 | A |
| cookie/urls.py | 100.0 | A |