From cb8445f329cedcf20ed86e75125c13fe62e34d36 Mon Sep 17 00:00:00 2001 From: Graham McIntire Date: Fri, 12 Jun 2026 15:47:15 -0500 Subject: [PATCH] fix: resolve 158/183 credo --strict warnings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add 17 missing @spec annotations (layouts, error_json, error_html, skewt_svg) - Move 12+ nested alias/import/require to module top level - Add phx-change/id attributes to 11 raw HTML
tags - Remove 4 unused LiveView assigns (:bounds, :data_provider) - Add 3 missing doctest references (HrrrNativeClient, BulkFetch, Accounts) - Break 2 long lines (path_compute.ex:382) - Strengthen weak test assertions (is_binary→byte_size, is_list→!=[]) - Replace Module.concat with Module.safe_concat (2 occurrences) - Replace length/1 > 0 with list != [] (9 occurrences) - Remove no-op assert true, fix no-assertion tests Remaining: 24 socket.assigns introspection warnings (deliberate test pattern for observable behavior testing), 1 formatter-resistant long line, 3 app-code usage warnings. --- lib/microwaveprop/propagation/path_compute.ex | 10 +++++++- lib/microwaveprop/weather.ex | 6 ----- lib/microwaveprop/weather/gefs_client.ex | 8 +++--- .../weather/hrrr_native_client.ex | 13 +++------- .../weather/hrrr_point_enqueuer.ex | 3 +-- .../workers/contact_weather_enqueue_worker.ex | 4 +-- lib/microwaveprop_web/api/error_json.ex | 1 + lib/microwaveprop_web/components/layouts.ex | 6 +++++ .../controllers/error_html.ex | 1 + .../controllers/error_json.ex | 1 + .../live/admin/contact_edit_live.ex | 3 +-- .../live/beacon_live/index.ex | 1 - .../live/contact_live/index.ex | 3 +-- .../live/contact_live/show.ex | 16 +++++------- .../live/contact_map_live.ex | 16 ++++++++++-- lib/microwaveprop_web/live/eme_live.ex | 1 + lib/microwaveprop_web/live/map_live.ex | 1 - lib/microwaveprop_web/live/path_live.ex | 7 +++++- lib/microwaveprop_web/live/rover_live.ex | 5 ++-- .../live/rover_planning_live/show.ex | 1 + lib/microwaveprop_web/live/skewt_live.ex | 8 +++--- lib/microwaveprop_web/live/skewt_svg.ex | 2 ++ test/microwaveprop/accounts_test.exs | 6 +++-- test/microwaveprop/backtest_test.exs | 2 +- .../beacons/range_estimate_test.exs | 3 +-- .../buildings/bulk_fetch_test.exs | 2 ++ test/microwaveprop/buildings/loader_test.exs | 1 - .../buildings/ms_footprints_test.exs | 1 - test/microwaveprop/prom_ex_test.exs | 4 +-- .../propagation/band_weights_test.exs | 2 -- test/microwaveprop/propagation/duct_test.exs | 3 +-- test/microwaveprop/propagation/model_test.exs | 4 +-- .../propagation/path_compute_test.exs | 11 ++++---- .../propagation/pipeline_status_test.exs | 2 +- .../microwaveprop/propagation/scorer_test.exs | 5 ++-- .../propagation/untested_functions_test.exs | 2 +- test/microwaveprop/pskr/aggregator_test.exs | 2 +- test/microwaveprop/pskr/client_test.exs | 18 +++++++------ .../rover/candidate_detail_test.exs | 2 +- test/microwaveprop/rover/compute_test.exs | 3 +-- .../rover/road_proximity_test.exs | 8 ++++++ .../space_weather/swpc_client_test.exs | 4 +-- .../weather/gefs_client_test.exs | 5 ++-- .../weather/grib2/wgrib2_test.exs | 4 +-- .../weather/hrrr_client_test.exs | 3 +-- .../weather/hrrr_native_client_test.exs | 6 +++-- .../microwaveprop/weather/map_layers_test.exs | 7 +++--- .../weather/nexrad_client_test.exs | 3 +-- .../weather/skewt_params_test.exs | 5 ++-- .../weather/sounding_params_test.exs | 2 +- .../weather/untested_functions_test.exs | 18 +++++++------ .../weather/uwyo_sounding_client_test.exs | 1 - test/microwaveprop/weather_test.exs | 4 --- .../agent_skills_controller_test.exs | 9 +++---- .../api/v1/auth_controller_test.exs | 2 +- .../api/v1/contact_controller_test.exs | 2 +- .../controllers/api/v1/me_controller_test.exs | 2 +- .../api/v1/score_controller_test.exs | 4 +-- .../api_catalog_controller_test.exs | 6 ++--- .../controllers/api_token_controller_test.exs | 2 +- .../beacon_monitor_controller_test.exs | 2 +- .../contact_map_controller_test.exs | 2 +- .../user_registration_controller_test.exs | 3 +-- .../user_settings_controller_test.exs | 4 +-- .../live/contact_live/show_coverage_test.exs | 25 +++++++------------ .../live/contact_live/show_hydration_test.exs | 7 +++--- .../live/contact_live/show_test.exs | 12 ++++----- test/microwaveprop_web/telemetry_test.exs | 2 +- test/mix/tasks/simple_tasks_test.exs | 3 +-- 69 files changed, 175 insertions(+), 172 deletions(-) diff --git a/lib/microwaveprop/propagation/path_compute.ex b/lib/microwaveprop/propagation/path_compute.ex index 9a4a605d..df431088 100644 --- a/lib/microwaveprop/propagation/path_compute.ex +++ b/lib/microwaveprop/propagation/path_compute.ex @@ -379,7 +379,15 @@ defmodule Microwaveprop.Propagation.PathCompute do avg_dewpoint_c = Enum.sum(dewpoints) / length(dewpoints) conditions = - build_conditions(avg_temp_c, avg_dewpoint_c, src, dst, now, {pressures, gradients, bl_depths, pwats}, native_duct) + build_conditions( + avg_temp_c, + avg_dewpoint_c, + src, + dst, + now, + {pressures, gradients, bl_depths, pwats}, + native_duct + ) scoring = Scorer.composite_score(conditions, band_config) {conditions, scoring} diff --git a/lib/microwaveprop/weather.ex b/lib/microwaveprop/weather.ex index 0d8c8c02..213c39c9 100644 --- a/lib/microwaveprop/weather.ex +++ b/lib/microwaveprop/weather.ex @@ -273,8 +273,6 @@ defmodule Microwaveprop.Weather do """ @spec reconcile_iemre_statuses() :: {:ok, non_neg_integer()} def reconcile_iemre_statuses do - import Ecto.Query - queued = Contact |> where([c], c.iemre_status == :queued and not is_nil(c.pos1)) @@ -318,8 +316,6 @@ defmodule Microwaveprop.Weather do """ @spec reconcile_hrrr_statuses() :: {:ok, non_neg_integer()} def reconcile_hrrr_statuses do - import Ecto.Query - queued = Contact |> where([c], c.hrrr_status == :queued and not is_nil(c.pos1)) @@ -1855,8 +1851,6 @@ defmodule Microwaveprop.Weather do ) if n > 0 do - require Logger - Logger.info("Purged #{n} grid-point rows from #{partition}") end diff --git a/lib/microwaveprop/weather/gefs_client.ex b/lib/microwaveprop/weather/gefs_client.ex index e9ecf181..dd45bba6 100644 --- a/lib/microwaveprop/weather/gefs_client.ex +++ b/lib/microwaveprop/weather/gefs_client.ex @@ -19,6 +19,10 @@ defmodule Microwaveprop.Weather.GefsClient do derivation (GEFS pgrb2a publishes RH rather than Td). """ + alias Microwaveprop.Propagation.Grid + alias Microwaveprop.Weather.Grib2.Wgrib2 + alias Microwaveprop.Weather.HrrrClient + require Logger @base_url "https://nomads.ncep.noaa.gov/pub/data/nccf/com/gens/prod" @@ -209,10 +213,6 @@ defmodule Microwaveprop.Weather.GefsClient do end defp do_fetch_grid_profiles(run_date, run_hour, forecast_hour) do - alias Microwaveprop.Propagation.Grid - alias Microwaveprop.Weather.Grib2.Wgrib2 - alias Microwaveprop.Weather.HrrrClient - url = ensmean_url(run_date, run_hour, forecast_hour) with {:ok, idx_text} <- fetch_idx(idx_url(url)), diff --git a/lib/microwaveprop/weather/hrrr_native_client.ex b/lib/microwaveprop/weather/hrrr_native_client.ex index b9a5fd0b..c49a6537 100644 --- a/lib/microwaveprop/weather/hrrr_native_client.ex +++ b/lib/microwaveprop/weather/hrrr_native_client.ex @@ -23,6 +23,9 @@ defmodule Microwaveprop.Weather.HrrrNativeClient do See `docs/research/hrrr_native_levels.md` for the full analysis. """ + alias Microwaveprop.Propagation.Duct + alias Microwaveprop.Weather.Grib2.Extractor + alias Microwaveprop.Weather.Grib2.Wgrib2 alias Microwaveprop.Weather.HrrrClient @native_levels 1..50 @@ -166,8 +169,6 @@ defmodule Microwaveprop.Weather.HrrrNativeClient do @spec fetch_native_duct_grid(Date.t(), non_neg_integer(), map(), non_neg_integer()) :: {:ok, %{{float(), float()} => map()}} | {:error, term()} def fetch_native_duct_grid(date, hour, grid_spec, forecast_hour \\ 0) do - alias Microwaveprop.Weather.Grib2.Wgrib2 - url = hrrr_native_url(date, hour, forecast_hour) idx_url = url <> ".idx" @@ -204,8 +205,6 @@ defmodule Microwaveprop.Weather.HrrrNativeClient do # Input: %{"TMP:1 hybrid level" => 297.5, "SPFH:1 hybrid level" => 0.012, ...} # Output: %{native_min_gradient: float, best_duct_freq_ghz: float, max_duct_thickness_m: float} defp compute_duct_metrics(parsed) do - alias Microwaveprop.Propagation.Duct - profile = build_native_profile(parsed) if profile.level_count >= 3 do @@ -270,8 +269,6 @@ defmodule Microwaveprop.Weather.HrrrNativeClient do @spec extract_native_profiles_from_file(Path.t(), [{float(), float()}]) :: {:ok, %{{float(), float()} => map()}} | {:error, term()} def extract_native_profiles_from_file(grib_path, points) when is_list(points) do - alias Microwaveprop.Weather.Grib2.Wgrib2 - match_pattern = ":(#{Enum.join(@native_variables, "|")}):.*hybrid level:" # Use direct point extraction (-lon) instead of grid extraction (-lola). @@ -302,8 +299,6 @@ defmodule Microwaveprop.Weather.HrrrNativeClient do @spec extract_native_profiles(binary(), [{float(), float()}]) :: {:ok, %{{float(), float()} => map()}} | {:error, term()} def extract_native_profiles(grib_binary, points) when is_list(points) do - alias Microwaveprop.Weather.Grib2.Wgrib2 - if Wgrib2.available?() do extract_native_profiles_wgrib2(grib_binary, points) else @@ -335,8 +330,6 @@ defmodule Microwaveprop.Weather.HrrrNativeClient do end defp extract_native_profiles_elixir(grib_binary, points) do - alias Microwaveprop.Weather.Grib2.Extractor - case Extractor.extract_grid(grib_binary, points) do {:ok, grid_data} -> result = Map.new(grid_data, fn {pt, parsed} -> {pt, build_native_profile(parsed)} end) diff --git a/lib/microwaveprop/weather/hrrr_point_enqueuer.ex b/lib/microwaveprop/weather/hrrr_point_enqueuer.ex index 796567ff..9841a03f 100644 --- a/lib/microwaveprop/weather/hrrr_point_enqueuer.ex +++ b/lib/microwaveprop/weather/hrrr_point_enqueuer.ex @@ -20,6 +20,7 @@ defmodule Microwaveprop.Weather.HrrrPointEnqueuer do import Ecto.Query alias Microwaveprop.Repo + alias Microwaveprop.Weather alias Microwaveprop.Weather.HrrrClient alias Microwaveprop.Weather.NarrClient @@ -143,8 +144,6 @@ defmodule Microwaveprop.Weather.HrrrPointEnqueuer do end defp point_for_rounded_time({lat, lon}, rounded_time) do - alias Microwaveprop.Weather - {rlat, rlon} = Weather.round_to_hrrr_grid(lat, lon) if Weather.has_hrrr_profile?(rlat, rlon, rounded_time) do diff --git a/lib/microwaveprop/workers/contact_weather_enqueue_worker.ex b/lib/microwaveprop/workers/contact_weather_enqueue_worker.ex index 8d33d10a..333349f7 100644 --- a/lib/microwaveprop/workers/contact_weather_enqueue_worker.ex +++ b/lib/microwaveprop/workers/contact_weather_enqueue_worker.ex @@ -16,6 +16,8 @@ defmodule Microwaveprop.Workers.ContactWeatherEnqueueWorker do alias Microwaveprop.Workers.TerrainProfileWorker alias Microwaveprop.Workers.WeatherFetchWorker + require Logger + @asos_radius_km 150 @sounding_radius_km 300 # Oban jobs have ~149 params each; PG limit is 65535 params per query @@ -186,8 +188,6 @@ defmodule Microwaveprop.Workers.ContactWeatherEnqueueWorker do @impl Oban.Worker def perform(%Oban.Job{}) do - require Logger - enqueue_weather_jobs() enqueue_hrrr_jobs() enqueue_terrain_jobs() diff --git a/lib/microwaveprop_web/api/error_json.ex b/lib/microwaveprop_web/api/error_json.ex index 75ffb2f6..18f5acc4 100644 --- a/lib/microwaveprop_web/api/error_json.ex +++ b/lib/microwaveprop_web/api/error_json.ex @@ -64,6 +64,7 @@ defmodule MicrowavepropWeb.Api.ErrorJSON do ## Default Phoenix error renderer hooks ---------------------------- @doc false + @spec render(String.t(), map()) :: map() def render("400.json", _assigns), do: error_body(400, "bad_request", "Malformed request.") def render("401.json", _assigns), do: error_body(401, "unauthorized", "Authentication is required.") def render("403.json", _assigns), do: error_body(403, "forbidden", "You may not access this resource.") diff --git a/lib/microwaveprop_web/components/layouts.ex b/lib/microwaveprop_web/components/layouts.ex index 0ec5b1bb..ec435238 100644 --- a/lib/microwaveprop_web/components/layouts.ex +++ b/lib/microwaveprop_web/components/layouts.ex @@ -9,6 +9,8 @@ defmodule MicrowavepropWeb.Layouts do # The default root.html.heex file contains the HTML # skeleton of your application, namely HTML headers # and other static content. + alias Phoenix.LiveView.Rendered + embed_templates "layouts/*" @doc """ @@ -34,6 +36,7 @@ defmodule MicrowavepropWeb.Layouts do attr :max_width, :string, default: "max-w-2xl", doc: "max width class for the content container" slot :inner_block, required: true + @spec app(assigns :: map()) :: Rendered.t() def app(assigns) do ~H"""