diff --git a/.github/workflows/python_tests.yaml b/.github/workflows/python_tests.yaml index 113ec3f59c..b6124b3093 100644 --- a/.github/workflows/python_tests.yaml +++ b/.github/workflows/python_tests.yaml @@ -24,21 +24,22 @@ jobs: - name: Install Micromamba and srw_app environment uses: mamba-org/setup-micromamba@v1 with: - environment-file: environment.yml - environment-name: srw_app + environment-file: sd_environment.yml + environment-name: srw_sd init-shell: bash cache-downloads: true cache-environment: true - name: Lint the python code run: | - micromamba activate srw_app + micromamba activate srw_sd export PYTHONPATH=$(pwd)/ush pylint --ignore-imports=yes tests/test_python/ pylint ush/create_*.py pylint ush/generate_FV3LAM_wflow.py pylint ush/set_fv3nml*.py pylint ush/update_input_nml.py + pylint ush/smoke_dust - name: Checkout externals run: | @@ -47,15 +48,16 @@ jobs: - name: Run python unittests run: | # exclude test_retrieve_data that is tested in functional test - micromamba activate srw_app + micromamba activate srw_sd export UNIT_TEST=True export PYTHONPATH=$(pwd)/ush python -m unittest tests/test_python/*.py + export PYTHONPATH=${PYTHONPATH}:$(pwd)/tests + python -m pytest tests/test_python/test_smoke_dust - name: Run python functional tests run: | - micromamba activate srw_app + micromamba activate srw_sd export CI=true export PYTHONPATH=${PWD}/ush python3 -m unittest tests/test_python/test_retrieve_data.py - diff --git a/doc/Makefile b/doc/Makefile index 9c57742525..4f7ff0c1b7 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -1,6 +1,6 @@ # Makefile for Sphinx documentation -#tdk: add back in -W +#tdk: add back in -W --keep-going SPHINXOPTS = -a -n SPHINXBUILD = sphinx-build SOURCEDIR = . diff --git a/doc/conf.py b/doc/conf.py index 2075bda1a5..706dd22b1b 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -36,9 +36,22 @@ numfig = True -nitpick_ignore = [('py:class', 'obj'),('py:class', - 'yaml.dumper.Dumper'),('py:class', - 'xml.etree.ElementTree'),('py:class', 'Basemap'),] +nitpick_ignore = [ + ('py:class', 'obj'), + ('py:class', 'yaml.dumper.Dumper'), + ('py:class', 'xml.etree.ElementTree'), + ('py:class', 'Basemap'), + ('py:class', 'numpy.ma.MaskedArray'), + ('py:class', 'esmpy.Field'), + ('py:class', 'pandas.DataFrame'), + ('py:class', 'netCDF4.Variable'), + ('py:class', 'pandas.DatetimeIndex'), + ('py:class', 'netCDF4.Dataset'), + ('py:class', 'numpy.ndarray'), + ('py:class', 'pydantic.BaseModel'), + ('py:class', 'esmpy.Grid'), + ('py:class', 'esmpy.StaggerLoc'), +] # -- General configuration --------------------------------------------------- @@ -52,7 +65,6 @@ 'sphinx.ext.mathjax', 'sphinx.ext.napoleon', 'sphinxcontrib.bibtex', - 'sphinxcontrib.autodoc_pydantic', ] bibtex_bibfiles = ['references.bib'] @@ -322,6 +334,3 @@ def warn_undocumented_members(app, what, name, obj, options, lines): # the purpose of building the documentation, METplus is loaded by including "metplus" in # the autodoc_mock_imports list above, not via use of the METPLUS_ROOT environment variable. os.environ["METPLUS_ROOT"] = "" - -# Configuration related to autodoc_pydantic -autodoc_pydantic_model_show_validator_summary = False \ No newline at end of file diff --git a/sd_environment.yml b/sd_environment.yml index 468a8715a4..7f1ae1c2a1 100644 --- a/sd_environment.yml +++ b/sd_environment.yml @@ -14,4 +14,5 @@ dependencies: - scipy=1.10.* - uwtools=2.3.* - xarray=2022.11.* - - typer=0.15.* \ No newline at end of file + - typer=0.15.* + - sphinx=7.4.* \ No newline at end of file diff --git a/ush/smoke_dust/core/context.py b/ush/smoke_dust/core/context.py index 8b9a52b771..5b8d6cb9e5 100644 --- a/ush/smoke_dust/core/context.py +++ b/ush/smoke_dust/core/context.py @@ -9,7 +9,7 @@ from typing import Union, Annotated, Any from mpi4py import MPI -from pydantic import BaseModel, model_validator, BeforeValidator +from pydantic import BaseModel, model_validator, BeforeValidator, Field from smoke_dust.core.common import open_nc @@ -29,8 +29,8 @@ class PredefinedGrid(StrEnum): class EbbDCycle(StrEnum): """Emission forecast cycle method. - * `1`: Estimate emissions and fire radiative power. - * `2`: In addition to `1`, also create inputs to forecast hourly wildfire potential. + * ``1``: Estimate emissions and fire radiative power. + * ``2``: In addition to `1`, also create inputs to forecast hourly wildfire potential. """ ONE = "1" @@ -43,8 +43,9 @@ class RaveQaFilter(StrEnum): Quality assurance flag filtering to apply to input RAVE data. RAVE QA filter values range from one to three. - * `none`: Do not apply any QA filtering. - * `high`: QA flag values less than `2` are set to zero for derived fire radiative energy fields. + * ``none``: Do not apply any QA filtering. + * ``high``: QA flag values less than `2` are set to zero for derived fire radiative energy + fields. """ NONE = "none" @@ -123,21 +124,43 @@ class SmokeDustContext(BaseModel): """Context object for smoke/dust.""" # Values provided via command-line - staticdir: ReadPathType - ravedir: ReadPathType - intp_dir: WritePathType - predef_grid: PredefinedGrid - ebb_dcycle: EbbDCycle - restart_interval: Annotated[tuple[int, ...], BeforeValidator(_format_restart_interval_)] - persistence: bool - rave_qa_filter: RaveQaFilter - exit_on_error: bool - log_level: LogLevel - regrid_in_memory: bool = False + staticdir: ReadPathType = Field(description="Path to smoke and dust fixed files.") + ravedir: ReadPathType = Field( + description="Path to the directory containing RAVE data files (hourly)." + ) + intp_dir: WritePathType = Field( + description="Path to the directory containing interpolated RAVE data files." + ) + predef_grid: PredefinedGrid = Field( + description="SRW predefined grid to use as the forecast domain." + ) + ebb_dcycle: EbbDCycle = Field(description="The forecast cycle to run.") + restart_interval: Annotated[tuple[int, ...], BeforeValidator(_format_restart_interval_)] = ( + Field( + description="Restart intervals used for restart file search. For example '6 12 18 24'." + ) + ) + persistence: bool = Field( + description="If true, use satellite observations from the previous day. Otherwise, use " + "observations from the same day." + ) + rave_qa_filter: RaveQaFilter = Field( + description="Filter level for RAVE QA flags when regridding fields." + ) + exit_on_error: bool = Field( + description="If false, log errors and write a dummy emissions file but do not raise an " + "exception." + ) + log_level: LogLevel = Field(description="Logging level for the preprocessor") + regrid_in_memory: bool = Field( + description="If true, do esmpy regridding in-memory as opposed to reading from the fixed " + "weight file.", + default=False, + ) # Values provided via environment - current_day: str - nwges_dir: ReadPathType + current_day: str = Field(description="The forecast date for the start of the cycle.") + nwges_dir: ReadPathType = Field(description="Directory containing restart files.") # Fixed parameters should_calc_desc_stats: bool = False diff --git a/ush/smoke_dust/generate_emissions.py b/ush/smoke_dust/generate_emissions.py index 30368ccfbc..4a8db12011 100755 --- a/ush/smoke_dust/generate_emissions.py +++ b/ush/smoke_dust/generate_emissions.py @@ -4,7 +4,7 @@ Python script for fire emissions preprocessing from RAVE FRP and FRE (Li et al.,2022) Author: johana.romero-alvarez@noaa.gov """ - +import os import sys from enum import StrEnum, unique from pathlib import Path @@ -25,7 +25,7 @@ # pylint: enable=wrong-import-position - +os.environ["NO_COLOR"] = "1" app = typer.Typer(pretty_exceptions_enable=False)