diff --git a/.github/workflows/build_conda.yml b/.github/workflows/build_conda.yml
index a5a44c47..d9ba9162 100644
--- a/.github/workflows/build_conda.yml
+++ b/.github/workflows/build_conda.yml
@@ -9,11 +9,11 @@ jobs:
container:
image: continuumio/miniconda3:latest
steps:
- - name: Checkout Files
- uses: actions/checkout@v4
- - name: Run Docker to Build
- run: |
- conda config --append channels conda-forge
- conda config --append channels noaa-gfdl
- conda install conda-build conda-verify
- conda build .
+ - name: Checkout Files
+ uses: actions/checkout@v4
+ - name: Run Conda to Build
+ run: |
+ conda config --append channels conda-forge
+ conda config --append channels noaa-gfdl
+ conda install conda-build conda-verify
+ conda build .
diff --git a/.github/workflows/create_test_conda_env.yml b/.github/workflows/create_test_conda_env.yml
index e2df48e7..7acb2271 100644
--- a/.github/workflows/create_test_conda_env.yml
+++ b/.github/workflows/create_test_conda_env.yml
@@ -7,42 +7,58 @@ jobs:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v4
- - name: Set up Python
- uses: actions/setup-python@v5
- with:
- python-version: '>=3.9'
+ - uses: actions/checkout@v4
+ - name: Set up Python
+ uses: actions/setup-python@v5
+ with:
+ python-version: '>=3.9'
+
+ - name: Add conda to system path
+ run: |
+ # $CONDA is an env var pointing to root of miniconda dir
+ echo $CONDA/bin >> $GITHUB_PATH
+
+ - name: Create fre-cli environment
+ run: |
+ # create environment containing all dependencies
+ # the env cannot be explicitly activated in github CI/CD
+ conda env create -f environment.yml --name fre-cli
- - name: Add conda to system path
- run: |
- # $CONDA is an environment variable pointing to the root of the miniconda directory
- echo $CONDA/bin >> $GITHUB_PATH
+ # add conda env's executables to github's PATH equiv.
+ echo $CONDA/envs/fre-cli/bin >> $GITHUB_PATH
+
+ # use *conda environment's pip* to install fre-cli
+ # called w/ full path to conda's python for explicitness
+ # called as a module (-m pip) for explicitness
+ $CONDA/envs/fre-cli/bin/python -m pip install --prefix $CONDA/envs/fre-cli .
+
+ - name: Run pytest in fre-cli environment
+ run: |
+ # add conda env's executables to github's PATH equiv.
+ # does this need to be done twice?
+ echo $CONDA/envs/fre-cli/bin >> $GITHUB_PATH
- - name: Create fre-cli environment
- run: |
- # create environment fre-cli will be installed into
- conda env create -f environment.yml --name fre-cli
- # try to make sure the right things are in GITHUB_PATH
- echo $CONDA/envs/fre-cli/bin >> $GITHUB_PATH
- # install fre-cli w pip
- $CONDA/envs/fre-cli/bin/python -m pip install --prefix $CONDA/envs/fre-cli .
+ # are we talking to the right python?
+ which python
+ python --version
+ $CONDA/envs/fre-cli/bin/python --version
+
+ # run pytest, not explicitly from the conda env?
+ which pytest
+ pytest --config-file=fre/pytest.ini --cov-config=fre/coveragerc --cov=fre fre/
+
+ - name: Run pylint in fre-cli environment
+ run: |
+ # add conda env's executables to github's PATH equiv.
+ # does this need to be done a third time?
+ echo $CONDA/envs/fre-cli/bin >> $GITHUB_PATH
- - name: Run pytest in fre-cli environment
- run: |
- # try to make sure the right things are in GITHUB_PATH
- echo $CONDA/envs/fre-cli/bin >> $GITHUB_PATH
- which python
- python --version
- $CONDA/envs/fre-cli/bin/python --version
- # run pytest
- pytest --config-file=fre/pytest.ini --cov-config=fre/coveragerc --cov=fre fre/
-
- - name: Run pylint in fre-cli environment
- run: |
- # try to make sure the right things are in GITHUB_PATH
- echo $CONDA/envs/fre-cli/bin >> $GITHUB_PATH
- which python
- python --version
- $CONDA/envs/fre-cli/bin/python --version
- # run pytest
- pylint fre/ || echo "pylint returned non-zero exit code. preventing workflow from dying with this echo."
+ # are we talking to the right python?
+ which python
+ python --version
+ $CONDA/envs/fre-cli/bin/python --version
+
+ # run pylint, not explicitly from the conda env?
+ which pylint
+ # ignore toothless complaint pylint has about netCDF4's stuff
+ pylint --ignored-modules netCDF4 fre/ || echo "pylint returned non-zero exit code. preventing workflow from dying with this echo."
diff --git a/.github/workflows/documentation.yml b/.github/workflows/documentation.yml
index b2cfce1d..ee93e977 100644
--- a/.github/workflows/documentation.yml
+++ b/.github/workflows/documentation.yml
@@ -17,6 +17,13 @@ jobs:
pip install --upgrade sphinx-rtd-theme
- name: Sphinx build
run: |
+ # list content of docs dir before spinx-apidoc
+ ls docs/
+ # generate .rst from doc strings in fre/ modules
+ sphinx-apidoc --output-dir docs fre/ --separate
+ # list content of docs dir after spinx-apidoc
+ ls docs/
+ # build content in docs/ dir, target is build/ dir
sphinx-build docs build
- name: Deploy to GitHub Pages
uses: peaceiris/actions-gh-pages@v3
diff --git a/.github/workflows/publish_conda.yml b/.github/workflows/publish_conda.yml
index b4d00b43..e36a72ea 100644
--- a/.github/workflows/publish_conda.yml
+++ b/.github/workflows/publish_conda.yml
@@ -2,20 +2,20 @@ name: publish_conda
on:
push:
branches:
- - main
+ - main
jobs:
publish:
runs-on: ubuntu-latest
container:
image: continuumio/miniconda3:latest
steps:
- - name: Checkout Files
- uses: actions/checkout@v4
- - name: Run Docker to Build and Upload
- run: |
- conda config --append channels conda-forge
- conda config --append channels noaa-gfdl
- conda install conda-build anaconda-client conda-verify
- export ANACONDA_API_TOKEN=${{ secrets.ANACONDA_TOKEN }}
- conda config --set anaconda_upload yes
- conda build .
+ - name: Checkout Files
+ uses: actions/checkout@v4
+ - name: Run Conda to Build and Publish
+ run: |
+ conda config --append channels conda-forge
+ conda config --append channels noaa-gfdl
+ conda install conda-build anaconda-client conda-verify
+ export ANACONDA_API_TOKEN=${{ secrets.ANACONDA_TOKEN }}
+ conda config --set anaconda_upload yes
+ conda build .
diff --git a/docs/conf.py b/docs/conf.py
index fa898651..32399782 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -14,7 +14,7 @@
# -- General configuration ---------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration
-extensions = []
+extensions = ['sphinx.ext.autodoc']
templates_path = ['_templates']
exclude_patterns = []
diff --git a/fre/README-tool-template.md b/fre/README.md
similarity index 94%
rename from fre/README-tool-template.md
rename to fre/README.md
index 870d3772..4570b317 100644
--- a/fre/README-tool-template.md
+++ b/fre/README.md
@@ -1,3 +1,4 @@
+
+* Refer to fre-cli [README.md](https://github.com/NOAA-GFDL/fre-cli/blob/main/README.md) for usage and tips.
+
+
diff --git a/fre/app/__init__.py b/fre/app/__init__.py
index c71f9893..c8eeb56b 100644
--- a/fre/app/__init__.py
+++ b/fre/app/__init__.py
@@ -1,4 +1,4 @@
-from .maskAtmosPlevel import maskAtmosPlevel_subtool
-from .freapp import appCli
+''' for fre.app imports '''
+from .freapp import app_cli
-__all__ = ["maskAtmosPlevel_subtool", "appCli"]
+__all__ = ["app_cli"]
diff --git a/fre/app/freapp.py b/fre/app/freapp.py
index da3dfb84..cdb0ff9a 100644
--- a/fre/app/freapp.py
+++ b/fre/app/freapp.py
@@ -1,12 +1,19 @@
+#!/usr/bin/env python3
+''' fre app calls '''
+
+import time
+
import click
-from .maskAtmosPlevel import maskAtmosPlevel_subtool
+
+from .mask_atmos_plevel import mask_atmos_plevel_subtool
from .generate_time_averages.generate_time_averages import generate
@click.group(help=click.style(" - access fre app subcommands", fg=(250,154,90)))
-def appCli():
- pass
+def app_cli():
+ ''' entry point to fre app click commands '''
+
-@appCli.command()
+@app_cli.command()
@click.option("-i", "--infile",
type=str,
help="Input NetCDF file containing pressure-level output to be masked",
@@ -20,11 +27,12 @@ def appCli():
required=True)
@click.pass_context
def mask_atmos_plevel(context, infile, outfile, psfile):
+ # pylint: disable=unused-argument
"""Mask out pressure level diagnostic output below land surface"""
- context.forward(maskAtmosPlevel_subtool)
+ context.forward(mask_atmos_plevel_subtool)
-@appCli.command()
+@app_cli.command()
@click.option("-i", "--inf",
type=str,
required=True,
@@ -57,13 +65,15 @@ def mask_atmos_plevel(context, infile, outfile, psfile):
help="Compute standard deviations for time-averages as well")
@click.pass_context
def gen_time_averages(context, inf, outf, pkg, var, unwgt, avg_type, stddev_type):
+ # pylint: disable=unused-argument
"""
- generate time averages for specified set of netCDF files. Example: generate-time-averages.py /path/to/your/files/
+ generate time averages for specified set of netCDF files.
+ Example: generate-time-averages.py /path/to/your/files/
"""
- import time
start_time=time.perf_counter()
context.forward(generate)
- print(f'Finished in total time {round(time.perf_counter() - start_time , 2)} second(s)') # need to change to a click.echo, not sure if echo supports f strings
+ # need to change to a click.echo, not sure if echo supports f strings
+ print(f'Finished in total time {round(time.perf_counter() - start_time , 2)} second(s)')
if __name__ == "__main__":
- appCli()
+ app_cli()
diff --git a/fre/app/generate_time_averages/frepytoolsTimeAverager.py b/fre/app/generate_time_averages/frepytoolsTimeAverager.py
index 7f21e7c9..9a9dd693 100644
--- a/fre/app/generate_time_averages/frepytoolsTimeAverager.py
+++ b/fre/app/generate_time_averages/frepytoolsTimeAverager.py
@@ -1,4 +1,9 @@
''' class for python-native routine usuing netCDF4 and numpy to crunch time-averages '''
+
+import math
+import numpy
+from netCDF4 import Dataset
+
from .timeAverager import timeAverager
class frepytoolsTimeAverager(timeAverager):
@@ -9,8 +14,9 @@ class inheriting from abstract base class timeAverager
'''
def generate_timavg(self, infile=None, outfile=None):
- ''' frepytools approach in a python-native manner. deliberately avoids pre-packaged routines. '''
- assert(self.pkg=="fre-python-tools")
+ ''' frepytools approach in a python-native manner.
+ deliberately avoids pre-packaged routines. '''
+ assert self.pkg=="fre-python-tools"
if __debug__:
print(locals()) #input argument details
@@ -21,10 +27,6 @@ def generate_timavg(self, infile=None, outfile=None):
print(f'ERROR: avg_type={self.avg_type} not supported at this time.')
return 1
- import math
- import numpy
- from netCDF4 import Dataset
-
# (TODO) file I/O should be a sep function, no? make tests, extend
nc_fin = Dataset(infile, 'r')
if nc_fin.file_format != 'NETCDF4':
@@ -36,8 +38,8 @@ def generate_timavg(self, infile=None, outfile=None):
# attempt to determine target var w/ bronx convention
if self.var is not None:
targ_var = self.var
- else:
- targ_var = infile.split('/').pop().split('.')[-2] # this can be replaced w/ a regex search maybe
+ else: # this can be replaced w/ a regex search maybe
+ targ_var = infile.split('/').pop().split('.')[-2]
if __debug__:
print(f'targ_var={targ_var}')
@@ -67,7 +69,9 @@ def generate_timavg(self, infile=None, outfile=None):
fin_dims = nc_fin.dimensions
num_time_bnds = fin_dims['time'].size
if not self.unwgt: #compute sum of weights
- wgts = numpy.moveaxis( time_bnds,0,-1)[1][:].copy() - numpy.moveaxis( time_bnds,0,-1)[0][:].copy()
+# wgts = numpy.moveaxis( time_bnds,0,-1 )[1][:].copy() - numpy.moveaxis( time_bnds,0,-1 )[0][:].copy()
+ wgts = numpy.moveaxis( time_bnds,0,-1 )[1][:].copy() \
+ - numpy.moveaxis( time_bnds,0,-1 )[0][:].copy()
wgts_sum=sum(wgts)
if __debug__:
print(f'wgts_sum={wgts_sum}')
@@ -134,9 +138,11 @@ def generate_timavg(self, infile=None, outfile=None):
- # write output file, (TODO) make this a sep function, make tests, extend, consider compression particular;y for NETCDF file writing
- # with Dataset( outfile, 'w', format='NETCDF4', persist=True ) as nc_fout: # consider this approach instead
- #nc_fout= Dataset( outfile, 'w', format='NETCDF4', persist=True ) # how should we handle file formats (HDF5, Zarr, older NETCDF)?
+ # write output file
+ # (TODO) make this a sep function, make tests, extend,
+ # (TODO) consider compression particular;y for NETCDF file writing
+ # consider this approach instead:
+ # with Dataset( outfile, 'w', format='NETCDF4', persist=True ) as nc_fout:
nc_fout= Dataset( outfile, 'w', format=nc_fin.file_format, persist=True )
# (TODO) make this a sep function, make tests, extend
@@ -156,7 +162,7 @@ def generate_timavg(self, infile=None, outfile=None):
print(f'could not get nc file attribute: {ncattr}. moving on.')
unwritten_ncattr_list.append(ncattr)
if len(unwritten_ncattr_list)>0:
- print(f'WARNING: Some global attributes ({unwritten_ncattr_list}) were not successfully written.')
+ print(f'WARNING: Some global attributes ({unwritten_ncattr_list}) were not written.')
print('------- DONE writing output attributes. --------')
##
@@ -166,11 +172,13 @@ def generate_timavg(self, infile=None, outfile=None):
unwritten_dims_list=[]
for key in fin_dims:
try:
- if key=='time': # this strongly influences the final data structure shape of the averages.
- #nc_fout.createDimension( dimname=key, size=None ) # if set to None, and lets say you try to write
- # # e.g. the original 'time_bnds' (which has 60 time steps)
- # # the array holding the avg. value will suddently have 60 time steps
- # # even though only 1 is needed, 59 time steps will have no data
+ if key=='time':
+ # this strongly influences the final data structure shape of the averages.
+ # if set to None, and lets say you try to write
+ # e.g. the original 'time_bnds' (which has 60 time steps)
+ # the array holding the avg. value will suddently have 60 time steps
+ # even though only 1 is needed, 59 time steps will have no data
+ #nc_fout.createDimension( dimname=key, size=None )
nc_fout.createDimension( dimname=key, size=1)
else:
nc_fout.createDimension( dimname=key, size=fin_dims[key].size )
@@ -178,22 +186,26 @@ def generate_timavg(self, infile=None, outfile=None):
print(f'problem. cannot read/write dimension {key}')
unwritten_dims_list.append(key)
if len(unwritten_dims_list)>0:
- print(f'WARNING: Some dimensions ({unwritten_dims_list}) were not successfully written.')
+ print(f'WARNING: Some dimensions ({unwritten_dims_list}) were not written.')
print('------ DONE writing output dimensions. ------- \n')
##
# (TODO) make this a sep function, make tests, extend
# first write the data we care most about- those we computed
+ # copying metadata, not fully correct
+ # but not far from wrong according to CF
+ # cell_methods must be changed TO DO
print(f'\n------- writing data for data {targ_var} -------- ')
nc_fout.createVariable(targ_var, nc_fin[targ_var].dtype, nc_fin[targ_var].dimensions)
- nc_fout.variables[targ_var].setncatts(nc_fin[targ_var].__dict__) # copying metadata, not fully correct
- # but not far from wrong according to CF
- # cell_methods must be changed TO DO
+ nc_fout.variables[targ_var].setncatts(nc_fin[targ_var].__dict__)
+
+
nc_fout.variables[targ_var][:]=avgvals
if self.stddev_type is not None:
stddev_varname=targ_var+'_'+self.stddev_type+'_stddev'
- nc_fout.createVariable(stddev_varname, nc_fin[targ_var].dtype, nc_fin[targ_var].dimensions)
+ nc_fout.createVariable(
+ stddev_varname, nc_fin[targ_var].dtype, nc_fin[targ_var].dimensions )
nc_fout.variables[stddev_varname].setncatts(nc_fin[targ_var].__dict__)
nc_fout.variables[stddev_varname][:]=stddevs
print('---------- DONE writing output variables. ---------')
@@ -217,15 +229,15 @@ def generate_timavg(self, infile=None, outfile=None):
print(f'nc_fin[var].shape={nc_fin[var].shape}')
#print(f'len(nc_fout.variables[{var}])={len(nc_fout.variables[var])}')
nc_fout.variables[var][:] = [ nc_fin[var][0] ]
- print(f'is it a time variable? {self.var_has_time_units(nc_fin.variables[var])}')
+ print(f'time variable? {self.var_has_time_units(nc_fin.variables[var])}')
else:
continue
if len(unwritten_var_list)>0:
- print(f'WARNING: some variables\' data ({unwritten_var_list}) was not successfully written.')
+ print(f'WARNING: some variables\' data ({unwritten_var_list}) was not written.')
if len(unwritten_var_ncattr_dict)>0:
- print(f'WARNING: some variables\' metadata was not successfully written.')
- print(f'WARNING: relevant variable (key) and attribute (value) pairs: \n{unwritten_var_ncattr_dict}')
+ print('WARNING: some variables\' metadata was not successfully written.')
+ print(f'WARNING: relevant variable/attr pairs: \n{unwritten_var_ncattr_dict}')
print('---------- DONE writing output variables. ---------')
##
diff --git a/fre/app/generate_time_averages/tests/test_generate_time_averages.py b/fre/app/generate_time_averages/tests/test_generate_time_averages.py
index 82400990..b8db14b0 100644
--- a/fre/app/generate_time_averages/tests/test_generate_time_averages.py
+++ b/fre/app/generate_time_averages/tests/test_generate_time_averages.py
@@ -1,18 +1,20 @@
+''' for testing fre app generate-time-averages '''
import pathlib as pl
import pytest
# not a test function, to be called by test functions below.
-def run_avgtype_pkg_calculations(infile=None,outfile=None, pkg=None, avg_type=None, unwgt=None, stddev_type=None):
- assert all( [infile is not None, outfile is not None,
+def run_avgtype_pkg_calculations(infile=None,outfile=None, pkg=None, avg_type=None, unwgt=None,
+ stddev_type=None):
+ assert all( [infile is not None, outfile is not None,
pkg is not None, avg_type is not None,
unwgt is not None] )
if pl.Path(outfile).exists():
- print(f'output test file exists. deleting before remaking.')
+ print('output test file exists. deleting before remaking.')
pl.Path(outfile).unlink() #delete file so we check that it can be recreated
from fre.app.generate_time_averages import generate_time_averages as gtas
- gtas.generate_time_average(infile = infile, outfile = outfile,
- pkg = pkg, unwgt = unwgt,
- avg_type = avg_type, stddev_type = stddev_type)
+ gtas.generate_time_average(infile = infile, outfile = outfile,
+ pkg = pkg, unwgt = unwgt,
+ avg_type = avg_type, stddev_type = stddev_type)
return pl.Path(outfile).exists()
### preamble tests. if these fail, none of the others will succeed. -----------------
@@ -30,23 +32,26 @@ def test_time_avg_input_file_exists():
### cdo avgs, unweighted, all/seasonal/monthly ------------------------
def test_monthly_cdo_time_unwgt_avgs():
''' generates an unweighted monthly time averaged file using cdo '''
- assert run_avgtype_pkg_calculations(infile = (time_avg_file_dir+test_file_name),
- outfile = (time_avg_file_dir+'ymonmean_unwgt_'+test_file_name),
- pkg='cdo',avg_type='month',unwgt=True)
-
+ assert run_avgtype_pkg_calculations(
+ infile = (time_avg_file_dir+test_file_name),
+ outfile = (time_avg_file_dir+'ymonmean_unwgt_'+test_file_name),
+ pkg='cdo',avg_type='month',unwgt=True )
+
def test_seasonal_cdo_time_unwgt_avgs():
''' generates an unweighted seasonal time averaged file using cdo '''
- assert run_avgtype_pkg_calculations(infile = (time_avg_file_dir+test_file_name),
- outfile = (time_avg_file_dir+'yseasmean_unwgt_'+test_file_name),
- pkg='cdo',avg_type='seas',unwgt=True)
+ assert run_avgtype_pkg_calculations(
+ infile = (time_avg_file_dir+test_file_name),
+ outfile = (time_avg_file_dir+'yseasmean_unwgt_'+test_file_name),
+ pkg='cdo',avg_type='seas',unwgt=True )
def test_cdo_time_unwgt_avgs():
''' generates an unweighted time averaged file using cdo '''
- assert run_avgtype_pkg_calculations(infile = (time_avg_file_dir+test_file_name),
- outfile = (time_avg_file_dir+'timmean_unwgt_'+test_file_name),
- pkg='cdo',avg_type='all',unwgt=True)
+ assert run_avgtype_pkg_calculations(
+ infile = (time_avg_file_dir+test_file_name),
+ outfile = (time_avg_file_dir+'timmean_unwgt_'+test_file_name),
+ pkg='cdo',avg_type='all',unwgt=True )
+
-
#### cdo avgs, weighted, all/seasonal/monthly ------------------------
## (TODO) WRITE THESE VERSIONS FOR CDOTIMEAVERAGER CLASS THEN MAKE THESE TESTS
##def test_monthly_cdo_time_avgs():
@@ -54,29 +59,33 @@ def test_cdo_time_unwgt_avgs():
def test_cdo_time_avgs():
''' generates a weighted time averaged file using cdo '''
- assert run_avgtype_pkg_calculations(infile = (time_avg_file_dir+test_file_name),
- outfile = (time_avg_file_dir+'timmean_'+test_file_name),
- pkg='cdo',avg_type='all',unwgt=False)
+ assert run_avgtype_pkg_calculations(
+ infile = (time_avg_file_dir+test_file_name),
+ outfile = (time_avg_file_dir+'timmean_'+test_file_name),
+ pkg='cdo',avg_type='all',unwgt=False )
### cdo stddevs, unweighted, all/seasonal/monthly ------------------------
def test_monthly_cdo_time_unwgt_stddevs():
''' generates a monthly time averaged file using cdo '''
- assert run_avgtype_pkg_calculations(infile = (time_avg_file_dir+test_file_name),
- outfile = (time_avg_file_dir+'ymonstddev1_unwgt_'+test_file_name),
- pkg='cdo',avg_type='month',stddev_type='samp', unwgt=True)
+ assert run_avgtype_pkg_calculations(
+ infile = (time_avg_file_dir+test_file_name),
+ outfile = (time_avg_file_dir+'ymonstddev1_unwgt_'+test_file_name),
+ pkg='cdo',avg_type='month',stddev_type='samp', unwgt=True )
def test_seasonal_cdo_time_unwgt_stddevs():
''' generates a seasonal time averaged file using cdo '''
- assert run_avgtype_pkg_calculations(infile = (time_avg_file_dir+test_file_name),
- outfile = (time_avg_file_dir+'yseasstddev1_unwgt_'+test_file_name),
- pkg='cdo',avg_type='seas',stddev_type='samp',unwgt=True)
+ assert run_avgtype_pkg_calculations(
+ infile = (time_avg_file_dir+test_file_name),
+ outfile = (time_avg_file_dir+'yseasstddev1_unwgt_'+test_file_name),
+ pkg='cdo',avg_type='seas',stddev_type='samp',unwgt=True )
def test_cdo_time_unwgt_stddevs():
''' generates a time averaged file using cdo '''
- assert run_avgtype_pkg_calculations(infile = (time_avg_file_dir+test_file_name),
- outfile = (time_avg_file_dir+'yseasmean_unwgt_'+test_file_name),
- pkg='cdo',avg_type='all',stddev_type='samp', unwgt=True)
+ assert run_avgtype_pkg_calculations(
+ infile = (time_avg_file_dir+test_file_name),
+ outfile = (time_avg_file_dir+'yseasmean_unwgt_'+test_file_name),
+ pkg='cdo',avg_type='all',stddev_type='samp', unwgt=True )
#### cdo stddevs, weighted, all/seasonal/monthly -----------------------
@@ -84,35 +93,39 @@ def test_cdo_time_unwgt_stddevs():
#def test_monthly_cdo_time_stddevs():
#def test_seasonal_cdo_time_stddevs():
#def test_cdo_time_stddevs():
-
+
## frepythontools avgs+stddevs, weighted+unweighted, all ------------------------
def test_fre_python_tools_time_avgs():
''' generates a time averaged file using fre_python_tools's version '''
''' weighted average, no std deviation '''
- assert run_avgtype_pkg_calculations(infile = (time_avg_file_dir+test_file_name),
- outfile = (time_avg_file_dir+'frepytools_timavg_'+test_file_name),
- pkg='fre-python-tools',avg_type='all', unwgt=False)
+ assert run_avgtype_pkg_calculations(
+ infile = (time_avg_file_dir+test_file_name),
+ outfile = (time_avg_file_dir+'frepytools_timavg_'+test_file_name),
+ pkg='fre-python-tools',avg_type='all', unwgt=False )
def test_fre_python_tools_time_unwgt_avgs():
''' generates a time averaged file using fre_python_tools's version '''
''' weighted average, no std deviation '''
- assert run_avgtype_pkg_calculations(infile = (time_avg_file_dir+test_file_name),
- outfile = (time_avg_file_dir+'frepytools_unwgt_timavg_'+test_file_name),
- pkg='fre-python-tools',avg_type='all', unwgt=True)
+ assert run_avgtype_pkg_calculations(
+ infile = (time_avg_file_dir+test_file_name),
+ outfile = (time_avg_file_dir+'frepytools_unwgt_timavg_'+test_file_name),
+ pkg='fre-python-tools',avg_type='all', unwgt=True )
def test_fre_python_tools_time_avgs_stddevs():
''' generates a time averaged file using fre_python_tools's version '''
''' weighted average, no std deviation '''
- assert run_avgtype_pkg_calculations(infile = (time_avg_file_dir+test_file_name),
- outfile = (time_avg_file_dir+'frepytools_stddev_'+test_file_name),
- pkg='fre-python-tools',avg_type='all', stddev_type='samp', unwgt=False)
+ assert run_avgtype_pkg_calculations(
+ infile = (time_avg_file_dir+test_file_name),
+ outfile = (time_avg_file_dir+'frepytools_stddev_'+test_file_name),
+ pkg='fre-python-tools',avg_type='all', stddev_type='samp', unwgt=False )
def test_fre_python_tools_time_unwgt_avgs_stddevs():
''' generates a time averaged file using fre_python_tools's version '''
''' weighted average, no std deviation '''
- assert run_avgtype_pkg_calculations(infile = (time_avg_file_dir+test_file_name),
- outfile = (time_avg_file_dir+'frepytools_unwgt_stddev_'+test_file_name),
- pkg='fre-python-tools',avg_type='all', stddev_type='samp', unwgt=True)
+ assert run_avgtype_pkg_calculations(
+ infile = (time_avg_file_dir+test_file_name),
+ outfile = (time_avg_file_dir+'frepytools_unwgt_stddev_'+test_file_name),
+ pkg='fre-python-tools',avg_type='all', stddev_type='samp', unwgt=True )
## (TODO) WRITE THESE VERSIONS FOR FREPYTOOLSTIMEAVERAGER CLASS THEN MAKE THESE TESTS
#def test_monthly_fre_python_tools_time_avgs():
@@ -128,7 +141,8 @@ def test_fre_python_tools_time_unwgt_avgs_stddevs():
## this will only work at GFDL. dev convenience only.
-#alt_str_fre_nctools_inf='tests/time_avg_test_files/fre_nctools_timavg_CLI_test_r8_b_atmos_LWP_1979_5y.nc'
+#alt_str_fre_nctools_inf= \
+# 'tests/time_avg_test_files/fre_nctools_timavg_CLI_test_r8_b_atmos_LWP_1979_5y.nc'
#def test_fre_nctools_time_avgs():
# ''' generates a time averaged file using fre_python_tools's version '''
# ''' weighted average, no std deviation '''
@@ -136,11 +150,12 @@ def test_fre_python_tools_time_unwgt_avgs_stddevs():
# all_outfile=time_avg_file_dir+'frenctools_timavg_'+test_file_name
#
# if pl.Path(all_outfile).exists():
-# print(f'output test file exists. deleting before remaking.')
+# print('output test file exists. deleting before remaking.')
# pl.Path(all_outfile).unlink() #delete file so we check that it can be recreated
#
# from fre_python_tools.generate_time_averages import generate_time_averages as gtas
-# gtas.generate_time_average(infile = infile, outfile = all_outfile, pkg='fre-nctools', unwgt=False, avg_type='all')
+# gtas.generate_time_average(infile = infile, outfile = all_outfile,
+# pkg='fre-nctools', unwgt=False, avg_type='all')
# assert pl.Path(all_outfile).exists()
@@ -182,13 +197,14 @@ def test_compare_fre_python_tools_to_fre_nctools():
for lat in range(0,len(diff_pytools_nctools_timavg[0])):
for lon in range(0,len(diff_pytools_nctools_timavg[0][0])):
print(f'lat={lat},lon={lon}')
- print(f'diff_pytools_nctools_timavg[0][lat][lon]={diff_pytools_nctools_timavg[0][lat][lon]}')
+ #diff_at_latlon=diff_pytools_nctools_timavg[0][lat][lon]
+ #print(f'diff_pytools_nctools_timavg[0][lat][lon]={diff_at_latlon}')
if lon>10: break
break
-
+
non_zero_count=np.count_nonzero(diff_pytools_nctools_timavg[:])
- #assert (non_zero_count == 0.) # bad way to check for zero.
- assert not( (non_zero_count > 0.) or (non_zero_count < 0.) )
+ #assert (non_zero_count == 0.) # bad way to check for zero.
+ assert not( (non_zero_count > 0.) or (non_zero_count < 0.) )
@pytest.mark.skip(reason='test fails b.c. cdo cannot bitwise-reproduce fre-nctools answer')
def test_compare_fre_python_tools_to_cdo():
@@ -218,7 +234,7 @@ def test_compare_fre_python_tools_to_cdo():
break
non_zero_count=np.count_nonzero(diff_pytools_cdo_timavg[:])
- assert not( (non_zero_count > 0.) or (non_zero_count < 0.) )
+ assert not( (non_zero_count > 0.) or (non_zero_count < 0.) )
def test_compare_unwgt_fre_python_tools_to_unwgt_cdo():
@@ -247,7 +263,7 @@ def test_compare_unwgt_fre_python_tools_to_unwgt_cdo():
break
non_zero_count=np.count_nonzero(diff_pytools_cdo_timavg[:])
- assert not( (non_zero_count > 0.) or (non_zero_count < 0.) )
+ assert not( (non_zero_count > 0.) or (non_zero_count < 0.) )
@pytest.mark.skip(reason='test fails b.c. cdo cannot bitwise-reproduce fre-nctools answer')
def test_compare_cdo_to_fre_nctools():
@@ -262,7 +278,8 @@ def test_compare_cdo_to_fre_nctools():
probably because you are not at GFDL! run the shell script \
example if you would like to see this pass. otherwise, \
i will error right after this message.')
- alt_str_fre_nctools_inf='tests/time_avg_test_files/fre_nctools_timavg_CLI_test_r8_b_atmos_LWP_1979_5y.nc'
+ alt_str_fre_nctools_inf = \
+ 'tests/time_avg_test_files/fre_nctools_timavg_CLI_test_r8_b_atmos_LWP_1979_5y.nc'
try:
fre_nctools_inf=nc.Dataset(alt_str_fre_nctools_inf,'r')
except:
@@ -284,4 +301,4 @@ def test_compare_cdo_to_fre_nctools():
break
non_zero_count=np.count_nonzero(diff_cdo_nctools_timavg[:])
- assert not( (non_zero_count > 0.) or (non_zero_count < 0.) )
+ assert not( (non_zero_count > 0.) or (non_zero_count < 0.) )
diff --git a/fre/app/maskAtmosPlevel.py b/fre/app/mask_atmos_plevel.py
similarity index 74%
rename from fre/app/maskAtmosPlevel.py
rename to fre/app/mask_atmos_plevel.py
index fd6d5896..0e7b2c28 100755
--- a/fre/app/maskAtmosPlevel.py
+++ b/fre/app/mask_atmos_plevel.py
@@ -1,10 +1,11 @@
#!/usr/bin/env python
-
-# This script contains the refineDiags that produce data at the same
-# frequency as the input data (no reduction) such as surface albedo,
-# masking fields,...
-# It can accept any file and will only compute refineDiags in fields
-# are present.
+'''
+This script contains the refineDiags that produce data at the same
+frequency as the input data (no reduction) such as surface albedo,
+masking fields,...
+It can accept any file and will only compute refineDiags in fields
+are present.
+'''
import os
import netCDF4 as nc
@@ -12,24 +13,25 @@
import click
@click.command()
-def maskAtmosPlevel_subtool(infile, outfile, psfile):
+def mask_atmos_plevel_subtool(infile, outfile, psfile):
+ ''' click entry point to fre cmor mask-atmos-plevel'''
+
# Error if outfile exists
if os.path.exists(outfile):
- raise Exception(f"ERROR: Output file '{outfile}' already exists")
+ raise FileExistsError(f"ERROR: Output file {outfile} already exists")
# Open ps dataset
if not os.path.exists(psfile):
- raise Exception(f"ERROR: Input surface pressure file '{psfile}' does not exist")
+ raise FileNotFoundError(f"ERROR: Input surface pressure file {psfile} does not exist")
ds_ps = xr.open_dataset(psfile)
# Exit with message if "ps" not available
if "ps" not in list(ds_ps.variables):
- print(f"WARNING: File '{infile}' does not contain surface pressure, so exiting")
- return None
+ raise ValueError(f"ERROR: File {infile} does not contain surface pressure. exit.")
# Open input dataset
if not os.path.exists(infile):
- raise Exception(f"ERROR: Input file '{infile}' does not exist")
+ raise FileNotFoundError(f"ERROR: Input file {infile} does not exist")
ds_in = xr.open_dataset(infile)
# The trigger for atmos masking is a variable attribute "needs_atmos_masking = True".
@@ -49,61 +51,59 @@ def maskAtmosPlevel_subtool(infile, outfile, psfile):
# Write the output file if anything was done
if ds_out.variables:
- print(f"Modifying variables '{list(ds_out.variables)}', appending into new file '{outfile}'")
+ print(f"Modifying variables: {list(ds_out.variables)}\n appending into new file {outfile}")
write_dataset(ds_out, ds_in, outfile)
else:
- print(f"No variables modified, so not writing output file '{outfile}'")
- return None
+ print(f"No variables modified, so not writing output file {outfile}")
+
def preprocess(ds):
"""add needs_atmos_masking attribute if var ends with _unmsk"""
-
for var in list(ds.variables):
if var.endswith('_unmsk'):
ds[var].attrs['needs_atmos_masking'] = True
-
return ds
def mask_field_above_surface_pressure(ds, var, ds_ps):
"""mask data with pressure larger than surface pressure"""
-
plev = pressure_coordinate(ds, var)
# broadcast pressure coordinate and surface pressure to
# the dimensions of the variable to mask
plev_extended, _ = xr.broadcast(plev, ds[var])
ps_extended, _ = xr.broadcast(ds_ps["ps"], ds[var])
+
# masking do not need looping
masked = xr.where(plev_extended > ps_extended, 1.0e20, ds[var])
+
# copy attributes, but it doesn't include the missing values
attrs = ds[var].attrs.copy()
+
# add the missing values back
attrs['missing_value'] = 1.0e20
attrs['_FillValue'] = 1.0e20
masked.attrs = attrs
+
# transpose dims like the original array
masked = masked.transpose(*ds[var].dims)
-
print(f"Processed {var}")
return masked
-def pressure_coordinate(ds, varname, verbose=False):
+def pressure_coordinate(ds, varname):#, verbose=False):
"""check if dataArray has pressure coordinate fitting requirements
and return it"""
pressure_coord = None
-
for dim in list(ds[varname].dims):
if dim in list(ds.variables): # dim needs to have values in file
if ds[dim].attrs["long_name"] == "pressure":
pressure_coord = ds[dim]
elif ("coordinates" in ds.attrs) and (ds[dim].attrs["units"] == "Pa"):
pressure_coord = ds[dim]
-
return pressure_coord
@@ -118,37 +118,29 @@ def write_dataset(ds, template, outfile):
for var in list(template.variables):
if var in list(ds.variables):
continue
- else:
- ds[var] = template[var]
- ds[var].attrs = template[var].attrs.copy()
-
+ ds[var] = template[var]
+ ds[var].attrs = template[var].attrs.copy()
+ # write to file
ds.to_netcdf(outfile, unlimited_dims="time")
- return None
def set_netcdf_encoding(ds, pressure_vars):
"""set preferred options for netcdf encoding"""
-
all_vars = list(ds.variables)
encoding = {}
-
- for var in do_not_encode_vars + pressure_vars:
+ #for var in do_not_encode_vars + pressure_vars: #what was here in first place
+ for var in pressure_vars: #remove unused variable
if var in all_vars:
- encoding.update({var: dict(_FillValue=None)})
-
+ encoding.update( { var :
+ { '_FillValue':None} } )
return encoding
-def post_write(filename, ds, var_with_bounds, bounds_variables):
+def post_write(filename, var_with_bounds, bounds_variables):
"""fix a posteriori attributes that xarray.to_netcdf
did not do properly using low level netcdf lib"""
-
f = nc.Dataset(filename, "a")
-
for var, bndvar in zip(var_with_bounds, bounds_variables):
f.variables[var].setncattr("bounds", bndvar)
-
f.close()
-
- return None
diff --git a/fre/catalog/__init__.py b/fre/catalog/__init__.py
index 2cb1eeeb..13e87b07 100644
--- a/fre/catalog/__init__.py
+++ b/fre/catalog/__init__.py
@@ -1,4 +1,4 @@
-#from .gen_intake_gfdl import build_script
-from .frecatalog import catalogCli
+''' for fre.catalog imports '''
+from .frecatalog import catalog_cli
-__all__ = ["catalogCli"]
+__all__ = ["catalog_cli"]
diff --git a/fre/catalog/frecatalog.py b/fre/catalog/frecatalog.py
index 36de3679..3223002e 100644
--- a/fre/catalog/frecatalog.py
+++ b/fre/catalog/frecatalog.py
@@ -1,15 +1,20 @@
+'''
+entry point for fre catalog subcommands
+'''
+
import click
-import catalogbuilder
+#import catalogbuilder
from catalogbuilder.scripts import gen_intake_gfdl
from catalogbuilder.scripts import test_catalog
+
@click.group(help=click.style(" - access fre catalog subcommands", fg=(64,94,213)))
-def catalogCli():
+def catalog_cli():
''' entry point for click into fre catalog cli calls '''
- pass
-@catalogCli.command()
+
+@catalog_cli.command()
#TODO arguments dont have help message. So consider changing arguments to options?
@click.argument('input_path', required = False, nargs = 1)
#, help = 'The directory path with the datasets to be cataloged. E.g a GFDL PP path till /pp')
@@ -25,17 +30,20 @@ def catalogCli():
@click.pass_context
def builder(context, input_path = None, output_path = None, config = None, filter_realm = None,
filter_freq = None, filter_chunk = None, overwrite = False, append = False):
+ # pylint: disable=unused-argument
""" - Generate .csv and .json files for catalog """
context.forward(gen_intake_gfdl.create_catalog_cli)
-@catalogCli.command()
+@catalog_cli.command()
@click.argument('json_path', nargs = 1 , required = True)
@click.argument('json_template_path', nargs = 1 , required = False)
-@click.option('-tf', '--test-failure', is_flag=True, default = False, help="Errors are only printed. Program will not exit.")
+@click.option('-tf', '--test-failure', is_flag=True, default = False,
+ help="Errors are only printed. Program will not exit.")
@click.pass_context
def validate(context, json_path, json_template_path, test_failure):
+ # pylint: disable=unused-argument
""" - Validate a catalog against catalog schema """
context.forward(test_catalog.main)
if __name__ == "__main__":
- catalogCli()
+ catalog_cli()
diff --git a/fre/check/__init__.py b/fre/check/__init__.py
index 6216e5dd..ef351297 100644
--- a/fre/check/__init__.py
+++ b/fre/check/__init__.py
@@ -1,4 +1,6 @@
+''' for fre.check imports '''
+
from .frecheckexample import check_test_function
-from .frecheck import checkCli
+from .frecheck import check_cli
-__all__ = ["check_test_function", "checkCli"]
+__all__ = ["check_test_function", "check_cli"]
diff --git a/fre/check/frecheck.py b/fre/check/frecheck.py
index 6c259dbe..9640d138 100644
--- a/fre/check/frecheck.py
+++ b/fre/check/frecheck.py
@@ -1,16 +1,20 @@
+''' fre check '''
+
import click
+
from .frecheckexample import check_test_function
@click.group(help=click.style(" - access fre check subcommands", fg=(162,91,232)))
-def checkCli():
- pass
+def check_cli():
+ ''' entry point to fre check click commands '''
-@checkCli.command()
+@check_cli.command()
@click.option('--uppercase', '-u', is_flag=True, help = 'Print statement in uppercase.')
@click.pass_context
def function(context, uppercase):
+ # pylint: disable=unused-argument
""" - Execute fre check test """
context.forward(check_test_function)
if __name__ == "__main__":
- checkCli()
+ check_cli()
diff --git a/fre/check/frecheckexample.py b/fre/check/frecheckexample.py
index aa9e84b6..daac462a 100644
--- a/fre/check/frecheckexample.py
+++ b/fre/check/frecheckexample.py
@@ -7,7 +7,7 @@
import click
@click.command()
-def check_test_function(uppercase):
+def check_test_function(uppercase=None):
"""Execute fre list testfunction2."""
statement = "testingtestingtestingtesting"
if uppercase:
diff --git a/fre/cmor/CMORmixer.py b/fre/cmor/CMORmixer.py
index 824aeda7..501261cf 100644
--- a/fre/cmor/CMORmixer.py
+++ b/fre/cmor/CMORmixer.py
@@ -2,15 +2,13 @@
'''
see README.md for CMORmixer.py usage
'''
-import os, sys
+import os
import time as tm
-import numpy, json
-import cmor
-import netCDF4 as nc
-import string
+import json
from shutil import copyfile
-#import shutil
+import netCDF4 as nc
import click
+import cmor
global nameOfset, GFDL_vars_file, CMIP_output, GFDL_real_vars_file
diff --git a/fre/cmor/__init__.py b/fre/cmor/__init__.py
index 0e02ef4a..0f8bd3ff 100644
--- a/fre/cmor/__init__.py
+++ b/fre/cmor/__init__.py
@@ -1,4 +1,5 @@
+''' for fre.cmor imports '''
from .CMORmixer import cmor_run_subtool
-from .frecmor import cmorCli
+from .frecmor import cmor_cli
-__all__ = ["cmor_run_subtool", "cmorCli"]
+__all__ = ["cmor_run_subtool", "cmor_cli"]
diff --git a/fre/cmor/frecmor.py b/fre/cmor/frecmor.py
index 06f37d92..c693b1e6 100644
--- a/fre/cmor/frecmor.py
+++ b/fre/cmor/frecmor.py
@@ -1,11 +1,14 @@
+''' fre cmor '''
+
import click
+
from .CMORmixer import cmor_run_subtool
@click.group(help=click.style(" - access fre cmor subcommands", fg=(232,91,204)))
-def cmorCli():
- pass
+def cmor_cli():
+ ''' entry point to fre cmor click commands '''
-@cmorCli.command()
+@cmor_cli.command()
@click.option("-d", "--indir",
type=str,
help="Input directory",
@@ -28,8 +31,9 @@ def cmorCli():
required=True)
@click.pass_context
def run(context, indir, outdir, varlist, table_config, exp_config):
+ # pylint: disable=unused-argument
"""Rewrite climate model output"""
context.forward(cmor_run_subtool)
if __name__ == "__main__":
- cmorCli()
+ cmor_cli()
diff --git a/fre/fre.py b/fre/fre.py
index ea2afa6d..9dd65eb0 100644
--- a/fre/fre.py
+++ b/fre/fre.py
@@ -12,16 +12,16 @@
@click.group(
cls = LazyGroup,
- lazy_subcommands = {"pp": ".pp.frepp.ppCli",
- "catalog": ".catalog.frecatalog.catalogCli",
- "list": ".list.frelist.listCli",
- "check": ".check.frecheck.checkCli",
- "run": ".run.frerun.runCli",
- "test": ".test.fretest.testCli",
- "yamltools": ".yamltools.freyamltools.yamltoolsCli",
- "make": ".make.fremake.makeCli",
- "app": ".app.freapp.appCli",
- "cmor": ".cmor.frecmor.cmorCli" },
+ lazy_subcommands = {"pp": ".pp.frepp.pp_cli",
+ "catalog": ".catalog.frecatalog.catalog_cli",
+ "list": ".list.frelist.list_cli",
+ "check": ".check.frecheck.check_cli",
+ "run": ".run.frerun.run_cli",
+ "test": ".test.fretest.test_cli",
+ "yamltools": ".yamltools.freyamltools.yamltools_cli",
+ "make": ".make.fremake.make_cli",
+ "app": ".app.freapp.app_cli",
+ "cmor": ".cmor.frecmor.cmor_cli" },
help = click.style(
"'fre' is the main CLI click group that houses the other tool groups as lazy subcommands.",
fg='cyan')
@@ -35,7 +35,7 @@
def fre():
''' entry point function to subgroup functions '''
- pass
+
if __name__ == '__main__':
fre()
diff --git a/fre/list/__init__.py b/fre/list/__init__.py
index 9275abc0..555dae55 100644
--- a/fre/list/__init__.py
+++ b/fre/list/__init__.py
@@ -1,4 +1,5 @@
+''' for fre.list imports '''
from .frelistexample import list_test_function
-from .frelist import listCli
+from .frelist import list_cli
-__all__ = ["list_test_function", "listCli"]
+__all__ = ["list_test_function", "list_cli"]
diff --git a/fre/list/frelist.py b/fre/list/frelist.py
index a944385b..fea3b6ea 100644
--- a/fre/list/frelist.py
+++ b/fre/list/frelist.py
@@ -1,16 +1,20 @@
+''' fre list '''
+
import click
+
from .frelistexample import list_test_function
@click.group(help=click.style(" - access fre list subcommands", fg=(232,204,91)))
-def listCli():
- pass
+def list_cli():
+ ''' entry point to fre list click commands '''
-@listCli.command()
+@list_cli.command()
@click.option('--uppercase', '-u', is_flag=True, help = 'Print statement in uppercase.')
@click.pass_context
def function(context, uppercase):
+ # pylint: disable=unused-argument
""" - Execute fre list test """
context.forward(list_test_function)
if __name__ == "__main__":
- listCli()
+ list_cli()
diff --git a/fre/list/frelistexample.py b/fre/list/frelistexample.py
index 1effeb9e..7e40e195 100644
--- a/fre/list/frelistexample.py
+++ b/fre/list/frelistexample.py
@@ -7,7 +7,7 @@
import click
@click.command()
-def list_test_function(uppercase):
+def list_test_function(uppercase=None):
"""Execute fre list testfunction2."""
statement = "testingtestingtestingtesting"
if uppercase:
diff --git a/fre/make/__init__.py b/fre/make/__init__.py
index ff03e974..a35633b9 100644
--- a/fre/make/__init__.py
+++ b/fre/make/__init__.py
@@ -1,17 +1,15 @@
-'''
-for proper import of fre make subcommands
-'''
+''' for fre.make imports '''
from .createCheckout import checkout_create
from .createCompile import compile_create
from .createDocker import dockerfile_create
from .createMakefile import makefile_create
from .runFremake import fremake_run
-from .fremake import makeCli
+from .fremake import make_cli
__all__ = ["checkout_create",
"compile_create",
"dockerfile_create",
"makefile_create",
"fremake_run",
- "makeCli"]
+ "make_cli"]
diff --git a/fre/make/createCheckout.py b/fre/make/createCheckout.py
index e86ac006..97c34cc6 100644
--- a/fre/make/createCheckout.py
+++ b/fre/make/createCheckout.py
@@ -1,10 +1,10 @@
#!/usr/bin/python3
-from .gfdlfremake import varsfre, platformfre, yamlfre, checkout, targetfre
-import click
import os
import logging
import sys
+import click
+from .gfdlfremake import varsfre, platformfre, yamlfre, checkout, targetfre
@click.command()
def checkout_create(yamlfile,platform,target,no_parallel_checkout,jobs,execute,verbose):
diff --git a/fre/make/createCompile.py b/fre/make/createCompile.py
index 94f39b82..24f23255 100644
--- a/fre/make/createCompile.py
+++ b/fre/make/createCompile.py
@@ -1,11 +1,12 @@
#!/usr/bin/python3
-from .gfdlfremake import varsfre, platformfre, yamlfre, targetfre, buildBaremetal
-from multiprocessing.dummy import Pool
-import logging
import os
-import click
import sys
+import logging
+from multiprocessing.dummy import Pool
+
+import click
+from .gfdlfremake import varsfre, platformfre, yamlfre, targetfre, buildBaremetal
@click.command()
def compile_create(yamlfile,platform,target,jobs,parallel,execute,verbose):
diff --git a/fre/make/createDocker.py b/fre/make/createDocker.py
index 577ab42f..fee5775f 100644
--- a/fre/make/createDocker.py
+++ b/fre/make/createDocker.py
@@ -1,9 +1,9 @@
#!/usr/bin/python3
-from .gfdlfremake import varsfre, targetfre, makefilefre, platformfre, yamlfre, buildDocker
-import click
import os
import sys
+import click
+from .gfdlfremake import varsfre, targetfre, makefilefre, platformfre, yamlfre, buildDocker
@click.command()
def dockerfile_create(yamlfile, platform, target, execute):
diff --git a/fre/make/createMakefile.py b/fre/make/createMakefile.py
index 03eaaa01..e520f7c7 100644
--- a/fre/make/createMakefile.py
+++ b/fre/make/createMakefile.py
@@ -1,9 +1,8 @@
#!/usr/bin/python3
-from .gfdlfremake import makefilefre, varsfre, targetfre, yamlfre
-import click
import os
-import logging
+import click
+from .gfdlfremake import makefilefre, varsfre, targetfre, yamlfre
@click.command()
def makefile_create(yamlfile,platform,target):
diff --git a/fre/make/fremake.py b/fre/make/fremake.py
index 10e437b7..27cec2db 100644
--- a/fre/make/fremake.py
+++ b/fre/make/fremake.py
@@ -30,10 +30,10 @@
@click.group(help=click.style(" - access fre make subcommands", fg=(210,73,57)))
-def makeCli():
+def make_cli():
pass
-@makeCli.command()
+@make_cli.command()
@click.option("-y",
"--yamlfile",
type = str,
@@ -75,7 +75,7 @@ def run_fremake(context, yamlfile, platform, target, parallel, jobs, no_parallel
context.forward(fremake_run)
####
-@makeCli.command()
+@make_cli.command()
@click.option("-y",
"--yamlfile",
type = str,
@@ -117,7 +117,7 @@ def create_checkout(context,yamlfile,platform,target,no_parallel_checkout,jobs,e
context.forward(checkout_create)
#####
-@makeCli.command
+@make_cli.command
@click.option("-y",
"--yamlfile",
type = str,
@@ -140,7 +140,7 @@ def create_makefile(context,yamlfile,platform,target):
#####
-@makeCli.command
+@make_cli.command
@click.option("-y",
"--yamlfile",
type = str,
@@ -183,7 +183,7 @@ def create_compile(context,yamlfile,platform,target,jobs,parallel,execute,verbos
-@makeCli.command
+@make_cli.command
@click.option("-y",
"--yamlfile",
type = str,
@@ -210,4 +210,4 @@ def create_dockerfile(context,yamlfile,platform,target,execute):
if __name__ == "__main__":
- makeCli()
+ make_cli()
diff --git a/fre/make/runFremake.py b/fre/make/runFremake.py
index 49072b2f..e45d6837 100644
--- a/fre/make/runFremake.py
+++ b/fre/make/runFremake.py
@@ -5,14 +5,14 @@
## \author Bennett Chang
## \description Script for fremake is used to create and run a code checkout script and compile a model.
-import click
-import subprocess
import os
-import yaml
import logging
-from .gfdlfremake import targetfre, varsfre, yamlfre, checkout, makefilefre, buildDocker, buildBaremetal
from multiprocessing.dummy import Pool
+import click
+
+from .gfdlfremake import targetfre, varsfre, yamlfre, checkout, makefilefre, buildDocker, buildBaremetal
+
@click.command()
def fremake_run(yamlfile, platform, target, parallel, jobs, no_parallel_checkout, verbose):
diff --git a/fre/pp/__init__.py b/fre/pp/__init__.py
index bfe00341..4ac71ea1 100644
--- a/fre/pp/__init__.py
+++ b/fre/pp/__init__.py
@@ -1,3 +1,5 @@
+''' for fre.pp imports '''
+
from .checkoutScript import checkoutTemplate
from .configure_script_yaml import yamlInfo
from .configure_script_xml import convert
@@ -5,7 +7,7 @@
from .install import install_subtool
from .run import pp_run_subtool
from .status import status_subtool
-from .frepp import ppCli
+from .frepp import pp_cli
from .wrapper import runFre2pp
__all__ = ["checkoutTemplate",
@@ -15,6 +17,5 @@
"install_subtool",
"pp_run_subtool",
"status_subtool",
- "ppCli",
+ "pp_cli",
"runFre2pp"]
-
diff --git a/fre/pp/checkoutScript.py b/fre/pp/checkoutScript.py
index ac594888..5095a52c 100644
--- a/fre/pp/checkoutScript.py
+++ b/fre/pp/checkoutScript.py
@@ -5,12 +5,11 @@
import os
import sys
-from pathlib import Path
import subprocess
from subprocess import PIPE
from subprocess import STDOUT
-import click
import re
+import click
#############################################
diff --git a/fre/pp/configure_script_yaml.py b/fre/pp/configure_script_yaml.py
index 11b6aeb9..78f8eb75 100644
--- a/fre/pp/configure_script_yaml.py
+++ b/fre/pp/configure_script_yaml.py
@@ -36,8 +36,8 @@ def validate_yaml(file):
####################
def join_constructor(loader, node):
"""
- Allows FRE properties defined
- in main yaml to be concatenated.
+ Allows FRE properties defined
+ in main yaml to be concatenated.
"""
seq = loader.construct_sequence(node)
return ''.join([str(i) for i in seq])
@@ -109,7 +109,7 @@ def consolidate_yamls(mainyaml,experiment, platform,target):
f1.write(f"\n### {i.upper()} settings ###\n")
#copy expyaml into combined
shutil.copyfileobj(f2,f1)
-
+
return combined
####################
@@ -160,7 +160,7 @@ def set_rose_suite(yamlfile,rose_suite):
# set rose-suite items
if pp is not None:
for i in pp.values():
- if not isinstance(i,list):
+ if not isinstance(i,list):
for key,value in i.items():
# rose-suite.conf is somewhat finicky with quoting
# cylc validate will reveal any complaints
@@ -228,14 +228,14 @@ def _yamlInfo(yamlfile,experiment,platform,target):
# Load the combined yaml
final_yaml = yaml_load(comb_yaml)
-
+
# Clean combined yaml to validate
# If keys exists, delete:
keys_clean=["fre_properties","shared","experiments"]
for kc in keys_clean:
if kc in final_yaml.keys():
del final_yaml[kc]
-
+
with open("combined.yaml",'w') as f:
yaml.safe_dump(final_yaml,f,sort_keys=False)
diff --git a/fre/pp/frepp.py b/fre/pp/frepp.py
index ac48ddc2..b3456e31 100644
--- a/fre/pp/frepp.py
+++ b/fre/pp/frepp.py
@@ -1,3 +1,5 @@
+''' fre pp '''
+
import click
from .checkoutScript import checkoutTemplate
from .configure_script_yaml import yamlInfo
@@ -9,168 +11,130 @@
from .wrapper import runFre2pp
@click.group(help=click.style(" - access fre pp subcommands", fg=(57,139,210)))
-def ppCli():
- pass
+def pp_cli():
+ ''' entry point to fre pp click commands '''
+
# fre pp status
-@ppCli.command()
-@click.option("-e",
- "--experiment",
- type=str,
+@pp_cli.command()
+@click.option("-e", "--experiment", type=str,
help="Experiment name",
required=True)
-@click.option("-p",
- "--platform",
- type=str,
+@click.option("-p", "--platform", type=str,
help="Platform name",
required=True)
-@click.option("-t",
- "--target",
- type=str,
- help="Target name",
- required=True)
+@click.option("-t", "--target", type=str,
+ help="Target name",
+ required=True)
@click.pass_context
def status(context, experiment, platform, target):
+ # pylint: disable=unused-argument
""" - Report status of PP configuration"""
context.forward(status_subtool)
# fre pp run
-@ppCli.command()
-@click.option("-e",
- "--experiment",
- type=str,
+@pp_cli.command()
+@click.option("-e", "--experiment", type=str,
help="Experiment name",
required=True)
-@click.option("-p",
- "--platform",
- type=str,
+@click.option("-p", "--platform", type=str,
help="Platform name",
required=True)
-@click.option("-t",
- "--target",
- type=str,
- help="Target name",
- required=True)
+@click.option("-t", "--target", type=str,
+ help="Target name",
+ required=True)
@click.pass_context
def run(context, experiment, platform, target):
+ # pylint: disable=unused-argument
""" - Run PP configuration"""
context.forward(pp_run_subtool)
# fre pp validate
-@ppCli.command()
-@click.option("-e",
- "--experiment",
- type=str,
+@pp_cli.command()
+@click.option("-e", "--experiment", type=str,
help="Experiment name",
required=True)
-@click.option("-p",
- "--platform",
- type=str,
+@click.option("-p", "--platform", type=str,
help="Platform name",
required=True)
-@click.option("-t",
- "--target",
- type=str,
- help="Target name",
- required=True)
+@click.option("-t", "--target", type=str,
+ help="Target name",
+ required=True)
@click.pass_context
def validate(context, experiment, platform, target):
+ # pylint: disable=unused-argument
""" - Validate PP configuration"""
context.forward(validate_subtool)
# fre pp install
-@ppCli.command()
-@click.option("-e",
- "--experiment",
- type=str,
+@pp_cli.command()
+@click.option("-e", "--experiment", type=str,
help="Experiment name",
required=True)
-@click.option("-p",
- "--platform",
- type=str,
+@click.option("-p", "--platform", type=str,
help="Platform name",
required=True)
-@click.option("-t",
- "--target",
- type=str,
- help="Target name",
- required=True)
+@click.option("-t", "--target", type=str,
+ help="Target name",
+ required=True)
@click.pass_context
def install(context, experiment, platform, target):
+ # pylint: disable=unused-argument
""" - Install PP configuration"""
context.forward(install_subtool)
-@ppCli.command()
-@click.option("-y",
- "--yamlfile",
- type=str,
+@pp_cli.command()
+@click.option("-y", "--yamlfile", type=str,
help="YAML file to be used for parsing",
required=True)
-@click.option("-e",
- "--experiment",
- type=str,
+@click.option("-e", "--experiment", type=str,
help="Experiment name",
required=True)
-@click.option("-p",
- "--platform",
- type=str,
+@click.option("-p", "--platform", type=str,
help="Platform name",
required=True)
-@click.option("-t",
- "--target",
- type=str,
- help="Target name",
- required=True)
+@click.option("-t", "--target", type=str,
+ help="Target name",
+ required=True)
@click.pass_context
def configure_yaml(context,yamlfile,experiment,platform,target):
+ # pylint: disable=unused-argument
""" - Execute fre pp configure """
context.forward(yamlInfo)
-@ppCli.command()
-@click.option("-e",
- "--experiment",
- type=str,
+@pp_cli.command()
+@click.option("-e", "--experiment", type=str,
help="Experiment name",
required=True)
-@click.option("-p",
- "--platform",
- type=str,
+@click.option("-p", "--platform", type=str,
help="Platform name",
required=True)
-@click.option("-t",
- "--target",
- type=str,
- help="Target name",
- required=True)
-@click.option("-b",
- "--branch",
+@click.option("-t", "--target", type=str,
+ help="Target name",
+ required=True)
+@click.option("-b", "--branch",
show_default=True,
- default="main",
- type=str,
- help=" ".join(["Name of fre2/workflows/postproc branch to clone;"
- "defaults to 'main'. Not intended for production use,"
- "but needed for branch testing."])
- )
+ default="main", type=str,
+ help="Name of fre2/workflows/postproc branch to clone; " \
+ "defaults to 'main'. Not intended for production use, " \
+ "but needed for branch testing." )
@click.pass_context
def checkout(context, experiment, platform, target, branch='main'):
+ # pylint: disable=unused-argument
""" - Execute fre pp checkout """
context.forward(checkoutTemplate)
-@ppCli.command()
-@click.option('-x',
- '--xml',
+@pp_cli.command()
+@click.option('-x', '--xml',
required=True,
help="Required. The Bronx XML")
-@click.option('-p',
- '--platform',
+@click.option('-p', '--platform',
required=True,
help="Required. The Bronx XML Platform")
-@click.option('-t',
- '--target',
+@click.option('-t', '--target',
required=True,
help="Required. The Bronx XML Target")
-@click.option('-e',
- '--experiment',
+@click.option('-e', '--experiment',
required=True,
help="Required. The Bronx XML Experiment")
@click.option('--do_analysis',
@@ -178,36 +142,34 @@ def checkout(context, experiment, platform, target, branch='main'):
default=False,
help="Optional. Runs the analysis scripts.")
@click.option('--historydir',
- help="Optional. History directory to reference. " \
- "If not specified, the XML's default will be used.")
+ help="Optional. History directory to reference. " \
+ "If not specified, the XML's default will be used.")
@click.option('--refinedir',
- help="Optional. History refineDiag directory to reference. " \
- "If not specified, the XML's default will be used.")
+ help="Optional. History refineDiag directory to reference. " \
+ "If not specified, the XML's default will be used.")
@click.option('--ppdir',
- help="Optional. Postprocessing directory to reference. " \
- "If not specified, the XML's default will be used.")
+ help="Optional. Postprocessing directory to reference. " \
+ "If not specified, the XML's default will be used.")
@click.option('--do_refinediag',
is_flag=True,
default=False,
help="Optional. Process refineDiag scripts")
@click.option('--pp_start',
- help="Optional. Starting year of postprocessing. " \
- "If not specified, a default value of '0000' " \
- "will be set and must be changed in rose-suite.conf")
+ help="Optional. Starting year of postprocessing. " \
+ "If not specified, a default value of '0000' " \
+ "will be set and must be changed in rose-suite.conf")
@click.option('--pp_stop',
- help="Optional. Ending year of postprocessing. " \
- "If not specified, a default value of '0000' " \
+ help="Optional. Ending year of postprocessing. " \
+ "If not specified, a default value of '0000' " \
"will be set and must be changed in rose-suite.conf")
@click.option('--validate',
is_flag=True,
- help="Optional. Run the Cylc validator " \
+ help="Optional. Run the Cylc validator " \
"immediately after conversion")
-@click.option('-v',
- '--verbose',
+@click.option('-v', '--verbose',
is_flag=True,
help="Optional. Display detailed output")
-@click.option('-q',
- '--quiet',
+@click.option('-q', '--quiet',
is_flag=True,
help="Optional. Display only serious messages and/or errors")
@click.option('--dual',
@@ -216,44 +178,36 @@ def checkout(context, experiment, platform, target, branch='main'):
@click.pass_context
def configure_xml(context, xml, platform, target, experiment, do_analysis, historydir, refinedir,
ppdir, do_refinediag, pp_start, pp_stop, validate, verbose, quiet, dual):
+ # pylint: disable=unused-argument
""" - Converts a Bronx XML to a Canopy rose-suite.conf """
context.forward(convert)
#fre pp wrapper
-@ppCli.command()
-@click.option("-e",
- "--experiment",
- type=str,
+@pp_cli.command()
+@click.option("-e", "--experiment", type=str,
help="Experiment name",
required=True)
-@click.option("-p",
- "--platform",
- type=str,
+@click.option("-p", "--platform", type=str,
help="Platform name",
required=True)
-@click.option("-t",
- "--target",
- type=str,
- help="Target name",
- required=True)
-@click.option("-c",
- "--config-file",
- type=str,
- help="Path to a configuration file in either XML or YAML",
- required=True)
-@click.option("-b",
- "--branch",
+@click.option("-t", "--target", type=str,
+ help="Target name",
+ required=True)
+@click.option("-c", "--config-file", type=str,
+ help="Path to a configuration file in either XML or YAML",
+ required=True)
+@click.option("-b", "--branch",
show_default=True,
- default="main",
- type=str,
- help=" ".join(["Name of fre2/workflows/postproc branch to clone;"
- "defaults to 'main'. Not intended for production use,"
- "but needed for branch testing."])
- )
+ default="main", type=str,
+ help="Name of fre2/workflows/postproc branch to clone; " \
+ "defaults to 'main'. Not intended for production use, " \
+ "but needed for branch testing." )
@click.pass_context
def wrapper(context, experiment, platform, target, config_file, branch='main'):
+ # pylint: disable=unused-argument
""" - Execute fre pp steps in order """
context.forward(runFre2pp)
if __name__ == "__main__":
- ppCli()
+ ''' entry point for click to fre pp commands '''
+ pp_cli()
diff --git a/fre/pp/install.py b/fre/pp/install.py
index d344c5fa..9ffc00ee 100644
--- a/fre/pp/install.py
+++ b/fre/pp/install.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python
+''' fre pp install '''
-import os
import subprocess
import click
@@ -18,4 +18,5 @@ def _install_subtool(experiment, platform, target):
@click.command()
def install_subtool(experiment, platform, target):
+ ''' entry point to install for click '''
return _install_subtool(experiment, platform, target)
diff --git a/fre/pp/run.py b/fre/pp/run.py
index 444d6d5b..57f2c427 100644
--- a/fre/pp/run.py
+++ b/fre/pp/run.py
@@ -1,10 +1,9 @@
#!/usr/bin/env python
+''' fre pp run '''
-import os
import subprocess
import click
-
def _pp_run_subtool(experiment, platform, target):
"""
Start or restart the Cylc workflow identified by:
@@ -17,4 +16,5 @@ def _pp_run_subtool(experiment, platform, target):
@click.command()
def pp_run_subtool(experiment, platform, target):
+ ''' entry point to run for click '''
return _pp_run_subtool(experiment, platform, target)
diff --git a/fre/pp/status.py b/fre/pp/status.py
index 0eaa9079..6e2c07e1 100644
--- a/fre/pp/status.py
+++ b/fre/pp/status.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python
+''' fre pp status '''
-import os
import subprocess
import click
@@ -17,4 +17,5 @@ def _status_subtool(experiment, platform, target):
@click.command()
def status_subtool(experiment, platform, target):
+ ''' entry point to status for click '''
return _status_subtool(experiment, platform, target)
diff --git a/fre/pp/validate.py b/fre/pp/validate.py
index 350c3cb3..9c07340f 100644
--- a/fre/pp/validate.py
+++ b/fre/pp/validate.py
@@ -1,4 +1,5 @@
#!/usr/bin/env python
+''' fre pp validate '''
import os
import subprocess
@@ -16,13 +17,14 @@ def _validate_subtool(experiment, platform, target):
os.chdir(directory)
# Run the Rose validation macros
- cmd = f"rose macro --validate"
+ cmd = "rose macro --validate"
subprocess.run(cmd, shell=True, check=True)
# Validate the Cylc configuration
- cmd = f"cylc validate ."
+ cmd = "cylc validate ."
subprocess.run(cmd, shell=True, check=True)
@click.command()
def validate_subtool(experiment, platform, target):
+ ''' entry point to validate for click '''
return _validate_subtool(experiment, platform, target)
diff --git a/fre/pp/wrapper.py b/fre/pp/wrapper.py
index d3ca3802..965b9b2b 100644
--- a/fre/pp/wrapper.py
+++ b/fre/pp/wrapper.py
@@ -14,25 +14,24 @@
import sys
import os
-import subprocess
-from subprocess import PIPE, STDOUT
-from subprocess import STDOUT
-import click
-import re
import time
-
-#Add path to this file to the pythonpath for local imports
-import_dir = os.path.dirname(os.path.abspath(__file__))
-sys.path.append(import_dir)
+#import subprocess
+#from subprocess import PIPE, STDOUT
+#from subprocess import STDOUT
+import click
# Import from the local packages
-from checkoutScript import _checkoutTemplate
-from configure_script_xml import _convert
-from configure_script_yaml import _yamlInfo
-from validate import _validate_subtool
-from install import _install_subtool
-from run import _pp_run_subtool
-from status import _status_subtool
+from .checkoutScript import _checkoutTemplate
+from .configure_script_xml import _convert
+from .configure_script_yaml import _yamlInfo
+from .validate import _validate_subtool
+from .install import _install_subtool
+from .run import _pp_run_subtool
+from .status import _status_subtool
+
+##Add path to this file to the pythonpath for local imports
+#import_dir = os.path.dirname(os.path.abspath(__file__))
+#sys.path.append(import_dir)
@click.command()
def runFre2pp(experiment, platform, target, config_file, branch):
diff --git a/fre/pytest.ini b/fre/pytest.ini
index 20575029..0bcbff6a 100644
--- a/fre/pytest.ini
+++ b/fre/pytest.ini
@@ -1,11 +1,11 @@
[pytest]
testpaths =
fre/tests
-# fre/catalog/tests
+ fre/catalog/tests
# fre/check/tests
# fre/cmor/tests
# fre/list/tests
-# fre/make/tests
+ fre/make/tests
fre/pp/tests
# fre/run/tests
# fre/test/tests
diff --git a/fre/run/__init__.py b/fre/run/__init__.py
index e707693d..cdd61f12 100644
--- a/fre/run/__init__.py
+++ b/fre/run/__init__.py
@@ -1,8 +1,6 @@
-'''
-for proper import of fre run subcommands
-'''
+''' for fre.run imports '''
from .frerunexample import run_test_function
-from .frerun import runCli
+from .frerun import run_cli
-__all__ = ["run_test_function", "runCli"]
+__all__ = ["run_test_function", "run_cli"]
diff --git a/fre/run/frerun.py b/fre/run/frerun.py
index 3c0a5459..c2c611c3 100644
--- a/fre/run/frerun.py
+++ b/fre/run/frerun.py
@@ -6,15 +6,16 @@
from .frerunexample import run_test_function
@click.group(help=click.style(" - access fre run subcommands", fg=(164,29,132)))
-def runCli():
- pass
+def run_cli():
+ ''' entry point to fre run click commands '''
-@runCli.command()
+@run_cli.command()
@click.option('--uppercase', '-u', is_flag=True, help = 'Print statement in uppercase.')
@click.pass_context
def function(context, uppercase):
+ # pylint: disable=unused-argument
""" - Execute fre run test """
context.forward(run_test_function)
if __name__ == "__main__":
- runCli()
+ run_cli()
diff --git a/fre/run/frerunexample.py b/fre/run/frerunexample.py
index 55cb1feb..a4335144 100644
--- a/fre/run/frerunexample.py
+++ b/fre/run/frerunexample.py
@@ -7,8 +7,8 @@
import click
@click.command()
-def run_test_function(uppercase):
- """Execute fre list testfunction2."""
+def run_test_function(uppercase=None):
+ """Execute fre run run_test_function"""
statement = "testingtestingtestingtesting"
if uppercase:
statement = statement.upper()
diff --git a/fre/test/__init__.py b/fre/test/__init__.py
index a29104d6..0dedd8fe 100644
--- a/fre/test/__init__.py
+++ b/fre/test/__init__.py
@@ -1,4 +1,5 @@
+''' for fre.test imports '''
from .fretestexample import test_test_function
-from .fretest import testCli
+from .fretest import test_cli
-__all__ = ["test_test_function", "testCli"]
+__all__ = ["test_test_function", "test_cli"]
diff --git a/fre/test/fretest.py b/fre/test/fretest.py
index 69236d4c..172ac855 100644
--- a/fre/test/fretest.py
+++ b/fre/test/fretest.py
@@ -1,16 +1,21 @@
+'''
+entry point for fre test subcommands
+'''
+
import click
from .fretestexample import test_test_function
@click.group(help=click.style(" - access fre test subcommands", fg=(92,164,29)))
-def testCli():
- pass
+def test_cli():
+ ''' entry point to fre test click commands '''
-@testCli.command()
+@test_cli.command()
@click.option('--uppercase', '-u', is_flag=True, help = 'Print statement in uppercase.')
@click.pass_context
def function(context, uppercase):
+ # pylint: disable=unused-argument
""" - Execute fre test test """
context.forward(test_test_function)
if __name__ == "__main__":
- testCli()
+ test_cli()
diff --git a/fre/test/fretestexample.py b/fre/test/fretestexample.py
index ad465774..86d0f6ce 100644
--- a/fre/test/fretestexample.py
+++ b/fre/test/fretestexample.py
@@ -7,8 +7,8 @@
import click
@click.command()
-def test_test_function(uppercase):
- """Execute fre list testfunction2."""
+def test_test_function(uppercase=None):
+ """Execute fre list test_test_function"""
statement = "testingtestingtestingtesting"
if uppercase:
statement = statement.upper()
diff --git a/fre/tests/test_fre_app_cli.py b/fre/tests/test_fre_app_cli.py
new file mode 100644
index 00000000..87bc496a
--- /dev/null
+++ b/fre/tests/test_fre_app_cli.py
@@ -0,0 +1,23 @@
+#!/usr/bin/env python3
+''' test "fre app" calls '''
+
+from click.testing import CliRunner
+
+from fre import fre
+
+runner = CliRunner()
+
+def test_cli_fre_app():
+ ''' fre app '''
+ result = runner.invoke(fre.fre, args=["app"])
+ assert result.exit_code == 0
+
+def test_cli_fre_app_help():
+ ''' fre app --help '''
+ result = runner.invoke(fre.fre, args=["app", "--help"])
+ assert result.exit_code == 0
+
+def test_cli_fre_app_opt_dne():
+ ''' fre app optionDNE '''
+ result = runner.invoke(fre.fre, args=["app", "optionDNE"])
+ assert result.exit_code == 2
diff --git a/fre/tests/test_fre_catalog_cli.py b/fre/tests/test_fre_catalog_cli.py
new file mode 100644
index 00000000..fee3e0a3
--- /dev/null
+++ b/fre/tests/test_fre_catalog_cli.py
@@ -0,0 +1,38 @@
+#!/usr/bin/env python3
+''' test "fre catalog" calls '''
+
+from click.testing import CliRunner
+
+from fre import fre
+
+runner = CliRunner()
+
+def test_cli_fre_catalog():
+ ''' fre catalog '''
+ result = runner.invoke(fre.fre, args=["catalog"])
+ assert result.exit_code == 0
+
+def test_cli_fre_catalog_help():
+ ''' fre catalog --help '''
+ result = runner.invoke(fre.fre, args=["catalog", "--help"])
+ assert result.exit_code == 0
+
+def test_cli_fre_catalog_opt_dne():
+ ''' fre catalog optionDNE '''
+ result = runner.invoke(fre.fre, args=["catalog", "optionDNE"])
+ assert result.exit_code == 2
+
+def test_cli_fre_catalog_builder():
+ ''' fre catalog builder '''
+ result = runner.invoke(fre.fre, args=["catalog", "builder"])
+ assert all( [
+ result.exit_code == 1,
+ 'No paths given, using yaml configuration'
+ in result.stdout.split('\n')
+ ]
+ )
+
+def test_cli_fre_catalog_builder_help():
+ ''' fre catalog builder --help '''
+ result = runner.invoke(fre.fre, args=["catalog", "builder", "--help"])
+ assert result.exit_code == 0
diff --git a/fre/tests/test_fre_check_cli.py b/fre/tests/test_fre_check_cli.py
new file mode 100644
index 00000000..b00dc834
--- /dev/null
+++ b/fre/tests/test_fre_check_cli.py
@@ -0,0 +1,23 @@
+#!/usr/bin/env python3
+''' test "fre check" calls '''
+
+from click.testing import CliRunner
+
+from fre import fre
+
+runner = CliRunner()
+
+def test_cli_fre_check():
+ ''' fre check '''
+ result = runner.invoke(fre.fre, args=["check"])
+ assert result.exit_code == 0
+
+def test_cli_fre_check_help():
+ ''' fre check --help '''
+ result = runner.invoke(fre.fre, args=["check", "--help"])
+ assert result.exit_code == 0
+
+def test_cli_fre_check_opt_dne():
+ ''' fre check optionDNE '''
+ result = runner.invoke(fre.fre, args=["check", "optionDNE"])
+ assert result.exit_code == 2
diff --git a/fre/tests/test_fre_cli.py b/fre/tests/test_fre_cli.py
index 9a3e3141..daff4fbd 100644
--- a/fre/tests/test_fre_cli.py
+++ b/fre/tests/test_fre_cli.py
@@ -1,151 +1,23 @@
#!/usr/bin/env python3
-
-from fre import fre
+''' test "fre" calls '''
from click.testing import CliRunner
-runner = CliRunner()
-#tests are structured in the manner of:
-#https://click.palletsprojects.com/en/8.1.x/testing/
-#general intent for these tests is that each fre tool has 3 commandline tests:
-#command, help, command does not exist
+from fre import fre
-#Test list:
-#fre
-#-- fre app
-#-- fre catalog
-#-- fre check
-#-- fre cmor
-#-- fre list
-#-- fre make
-#-- fre pp
-#-- fre run
+runner = CliRunner()
def test_cli_fre():
+ ''' fre '''
result = runner.invoke(fre.fre)
- #print(f'exit code of runner result is {result.exit_code}')
- #print(f'output of runner result is {result.output}')
assert result.exit_code == 0
def test_cli_fre_help():
- result = runner.invoke(fre.fre,args='--help')
- #print(f'exit code of runner result is {result.exit_code}')
- #print(f'output of runner result is {result.output}')
+ ''' fre --help '''
+ result = runner.invoke(fre.fre, args='--help')
assert result.exit_code == 0
def test_cli_fre_option_dne():
- result = runner.invoke(fre.fre,args='optionDNE')
- #print(f'exit code of runner result is {result.exit_code}')
- #print(f'output of runner result is {result.output}')
- assert result.exit_code == 2
-
-#-- fre app
-
-def test_cli_fre_app():
- result = runner.invoke(fre.fre, args=["app"])
- assert result.exit_code == 0
-
-def test_cli_fre_app_help():
- result = runner.invoke(fre.fre, args=['--help', "app"])
- assert result.exit_code == 0
-
-def test_cli_fre_app_opt_dne():
- result = runner.invoke(fre.fre, args=['optionDNE', "app"])
- assert result.exit_code == 2
-
-#-- fre catalog
-def test_cli_fre_catalog():
- result = runner.invoke(fre.fre, args=["catalog"])
- assert result.exit_code == 0
-
-def test_cli_fre_catalog_builder_help():
- result = runner.invoke(fre.fre, args=["catalog", "builder", "--help"])
- assert result.exit_code == 0
-
-def test_cli_fre_catalog_help():
- result = runner.invoke(fre.fre, args=['--help', "catalog"])
- assert result.exit_code == 0
-
-def test_cli_fre_catalog_opt_dne():
- result = runner.invoke(fre.fre, args=['optionDNE', "catalog"])
- assert result.exit_code == 2
-
-#-- fre check
-
-def test_cli_fre_check():
- result = runner.invoke(fre.fre, args=["check"])
- assert result.exit_code == 0
-
-def test_cli_fre_check_help():
- result = runner.invoke(fre.fre, args=['--help', "check"])
- assert result.exit_code == 0
-
-def test_cli_fre_check_opt_dne():
- result = runner.invoke(fre.fre, args=['optionDNE', "check"])
- assert result.exit_code == 2
-
-#-- fre cmor
-
-def test_cli_fre_cmor():
- result = runner.invoke(fre.fre, args=["cmor"])
- assert result.exit_code == 0
-
-def test_cli_fre_cmor_help():
- result = runner.invoke(fre.fre, args=['--help', "cmor"])
- assert result.exit_code == 0
-
-def test_cli_fre_cmor_opt_dne():
- result = runner.invoke(fre.fre, args=['optionDNE', "cmor"])
- assert result.exit_code == 2
-
-#-- fre list
-def test_cli_fre_list():
- result = runner.invoke(fre.fre, args=["list"])
- assert result.exit_code == 0
-
-def test_cli_fre_list_help():
- result = runner.invoke(fre.fre, args=['--help', "list"])
- assert result.exit_code == 0
-
-def test_cli_fre_list_opt_dne():
- result = runner.invoke(fre.fre, args=['optionDNE', "list"])
- assert result.exit_code == 2
-
-#-- fre make
-def test_cli_fre_make():
- result = runner.invoke(fre.fre, args=["make"])
- assert result.exit_code == 0
-
-def test_cli_fre_make_help():
- result = runner.invoke(fre.fre, args=['--help', "make"])
- assert result.exit_code == 0
-
-def test_cli_fre_make_opt_dne():
- result = runner.invoke(fre.fre, args=['optionDNE', "make"])
- assert result.exit_code == 2
-
-#-- fre pp
-def test_cli_fre_pp():
- result = runner.invoke(fre.fre, args=["pp"])
- assert result.exit_code == 0
-
-def test_cli_fre_pp_help():
- result = runner.invoke(fre.fre, args=['--help', "pp"])
- assert result.exit_code == 0
-
-def test_cli_fre_pp_opt_dne():
- result = runner.invoke(fre.fre, args=['optionDNE', "pp"])
- assert result.exit_code == 2
-
-#-- fre run
-def test_cli_fre_run():
- result = runner.invoke(fre.fre, args=["run"])
- assert result.exit_code == 0
-
-def test_cli_fre_run_help():
- result = runner.invoke(fre.fre, args=['--help', "run"])
- assert result.exit_code == 0
-
-def test_cli_fre_run_opt_dne():
- result = runner.invoke(fre.fre, args=['optionDNE', "run"])
+ ''' fre optionDNE '''
+ result = runner.invoke(fre.fre, args='optionDNE')
assert result.exit_code == 2
diff --git a/fre/tests/test_fre_cmor_cli.py b/fre/tests/test_fre_cmor_cli.py
new file mode 100644
index 00000000..51ce52b2
--- /dev/null
+++ b/fre/tests/test_fre_cmor_cli.py
@@ -0,0 +1,23 @@
+#!/usr/bin/env python3
+''' test "fre cmor" calls '''
+
+from click.testing import CliRunner
+
+from fre import fre
+
+runner = CliRunner()
+
+def test_cli_fre_cmor():
+ ''' fre cmor '''
+ result = runner.invoke(fre.fre, args=["cmor"])
+ assert result.exit_code == 0
+
+def test_cli_fre_cmor_help():
+ ''' fre cmor --help '''
+ result = runner.invoke(fre.fre, args=["cmor", "--help"])
+ assert result.exit_code == 0
+
+def test_cli_fre_cmor_opt_dne():
+ ''' fre cmor optionDNE '''
+ result = runner.invoke(fre.fre, args=["cmor", "optionDNE"])
+ assert result.exit_code == 2
diff --git a/fre/tests/test_fre_list_cli.py b/fre/tests/test_fre_list_cli.py
new file mode 100644
index 00000000..effbb261
--- /dev/null
+++ b/fre/tests/test_fre_list_cli.py
@@ -0,0 +1,23 @@
+#!/usr/bin/env python3
+''' test "fre list" calls '''
+
+from click.testing import CliRunner
+
+from fre import fre
+
+runner = CliRunner()
+
+def test_cli_fre_list():
+ ''' fre list '''
+ result = runner.invoke(fre.fre, args=["list"])
+ assert result.exit_code == 0
+
+def test_cli_fre_list_help():
+ ''' fre list --help '''
+ result = runner.invoke(fre.fre, args=["list", "--help"])
+ assert result.exit_code == 0
+
+def test_cli_fre_list_opt_dne():
+ ''' fre list optionDNE '''
+ result = runner.invoke(fre.fre, args=["list", "optionDNE"])
+ assert result.exit_code == 2
diff --git a/fre/tests/test_fre_make_cli.py b/fre/tests/test_fre_make_cli.py
new file mode 100644
index 00000000..6d6ba41a
--- /dev/null
+++ b/fre/tests/test_fre_make_cli.py
@@ -0,0 +1,23 @@
+#!/usr/bin/env python3
+''' test "fre make" calls '''
+
+from click.testing import CliRunner
+
+from fre import fre
+
+runner = CliRunner()
+
+def test_cli_fre_make():
+ ''' fre make '''
+ result = runner.invoke(fre.fre, args=["make"])
+ assert result.exit_code == 0
+
+def test_cli_fre_make_help():
+ ''' fre make --help '''
+ result = runner.invoke(fre.fre, args=["make", "--help"])
+ assert result.exit_code == 0
+
+def test_cli_fre_make_opt_dne():
+ ''' fre make optionDNE '''
+ result = runner.invoke(fre.fre, args=["make", "optionDNE"])
+ assert result.exit_code == 2
diff --git a/fre/tests/test_fre_pp_cli.py b/fre/tests/test_fre_pp_cli.py
new file mode 100644
index 00000000..4fef6afa
--- /dev/null
+++ b/fre/tests/test_fre_pp_cli.py
@@ -0,0 +1,23 @@
+#!/usr/bin/env python3
+''' test "fre pp" calls '''
+
+from click.testing import CliRunner
+
+from fre import fre
+
+runner = CliRunner()
+
+def test_cli_fre_pp():
+ ''' fre pp '''
+ result = runner.invoke(fre.fre, args=["pp"])
+ assert result.exit_code == 0
+
+def test_cli_fre_pp_help():
+ ''' fre pp --help '''
+ result = runner.invoke(fre.fre, args=["pp", "--help"])
+ assert result.exit_code == 0
+
+def test_cli_fre_pp_opt_dne():
+ ''' fre pp optionDNE '''
+ result = runner.invoke(fre.fre, args=["pp", "optionDNE"])
+ assert result.exit_code == 2
diff --git a/fre/tests/test_fre_run_cli.py b/fre/tests/test_fre_run_cli.py
new file mode 100644
index 00000000..42215490
--- /dev/null
+++ b/fre/tests/test_fre_run_cli.py
@@ -0,0 +1,23 @@
+#!/usr/bin/env python3
+''' test "fre run" calls '''
+
+from click.testing import CliRunner
+
+from fre import fre
+
+runner = CliRunner()
+
+def test_cli_fre_run():
+ ''' fre run '''
+ result = runner.invoke(fre.fre, args=["run"])
+ assert result.exit_code == 0
+
+def test_cli_fre_run_help():
+ ''' fre run --help '''
+ result = runner.invoke(fre.fre, args=["run", "--help"])
+ assert result.exit_code == 0
+
+def test_cli_fre_run_opt_dne():
+ ''' fre run optionDNE '''
+ result = runner.invoke(fre.fre, args=["run", "optionDNE"])
+ assert result.exit_code == 2
diff --git a/fre/tests/test_fre_test_cli.py b/fre/tests/test_fre_test_cli.py
new file mode 100644
index 00000000..a82da835
--- /dev/null
+++ b/fre/tests/test_fre_test_cli.py
@@ -0,0 +1,23 @@
+#!/usr/bin/env python3
+''' test "fre test" calls '''
+
+from click.testing import CliRunner
+
+from fre import fre
+
+runner = CliRunner()
+
+def test_cli_fre_test():
+ ''' fre test '''
+ result = runner.invoke(fre.fre, args=["test"])
+ assert result.exit_code == 0
+
+def test_cli_fre_test_help():
+ ''' fre test --help '''
+ result = runner.invoke(fre.fre, args=["test", "--help"])
+ assert result.exit_code == 0
+
+def test_cli_fre_test_opt_dne():
+ ''' fre test optionDNE '''
+ result = runner.invoke(fre.fre, args=["test", "optionDNE"])
+ assert result.exit_code == 2
diff --git a/fre/tests/test_fre_yamltools_cli.py b/fre/tests/test_fre_yamltools_cli.py
new file mode 100644
index 00000000..fd6bd1c2
--- /dev/null
+++ b/fre/tests/test_fre_yamltools_cli.py
@@ -0,0 +1,23 @@
+#!/usr/bin/env python3
+''' test "fre yamltools" calls '''
+
+from click.testing import CliRunner
+
+from fre import fre
+
+runner = CliRunner()
+
+def test_cli_fre_yamltools():
+ ''' fre yamltools '''
+ result = runner.invoke(fre.fre, args=["yamltools"])
+ assert result.exit_code == 0
+
+def test_cli_fre_yamltools_help():
+ ''' fre yamltools --help '''
+ result = runner.invoke(fre.fre, args=["yamltools", "--help"])
+ assert result.exit_code == 0
+
+def test_cli_fre_yamltools_opt_dne():
+ ''' fre yamltools optionDNE '''
+ result = runner.invoke(fre.fre, args=["yamltools", "optionDNE"])
+ assert result.exit_code == 2
diff --git a/fre/yamltools/__init__.py b/fre/yamltools/__init__.py
index 9c94eeb6..369b1a42 100644
--- a/fre/yamltools/__init__.py
+++ b/fre/yamltools/__init__.py
@@ -1,7 +1,5 @@
-'''
-for proper import of fre yamltools subcommands
-'''
+''' for fre.yamltools imports '''
from .freyamltoolsexample import yamltools_test_function
-from .freyamltools import yamltoolsCli
+from .freyamltools import yamltools_cli
-__all__ = ["yamltools_test_function", "yamltoolsCli"]
+__all__ = ["yamltools_test_function", "yamltools_cli"]
diff --git a/fre/yamltools/data_table/is_valid_data_table_yaml.py b/fre/yamltools/data_table/is_valid_data_table_yaml.py
index e3169435..17d08fbd 100644
--- a/fre/yamltools/data_table/is_valid_data_table_yaml.py
+++ b/fre/yamltools/data_table/is_valid_data_table_yaml.py
@@ -18,15 +18,12 @@
* You should have received a copy of the GNU Lesser General Public
* License along with FMS. If not, see .
***********************************************************************
-"""
-
-""" Determine if a yaml data_table is valid.
+ Determine if a yaml data_table is valid.
Run `python3 is_valid_data_table_yaml.py -h` for more details
Author: Uriel Ramirez 05/27/2022
"""
import yaml
-import sys
import click
def check_gridname(grid_name):
diff --git a/fre/yamltools/diag_table/diag_table_to_yaml.py b/fre/yamltools/diag_table/diag_table_to_yaml.py
index 4eb52333..5fe7f9b3 100755
--- a/fre/yamltools/diag_table/diag_table_to_yaml.py
+++ b/fre/yamltools/diag_table/diag_table_to_yaml.py
@@ -24,10 +24,10 @@
"""
import copy as cp
-import click
from os import path
+import click
import yaml
-from .. import __version__, TableParseError
+from .. import __version__#, TableParseError
def main():
#: parse user input
diff --git a/fre/yamltools/diag_table/is_valid_diag_table_yaml.py b/fre/yamltools/diag_table/is_valid_diag_table_yaml.py
index 8b5fe22f..e9ce12a5 100644
--- a/fre/yamltools/diag_table/is_valid_diag_table_yaml.py
+++ b/fre/yamltools/diag_table/is_valid_diag_table_yaml.py
@@ -19,16 +19,14 @@
* You should have received a copy of the GNU Lesser General Public
* License along with FMS. If not, see .
***********************************************************************
-"""
-
-""" Determine if a yaml diag_table is valid.
+ Determine if a yaml diag_table is valid.
Run `python3 is_valid_diag_table_yaml.py -h` for more details
Author: Uriel Ramirez 05/27/2022
"""
-import yaml
import sys
import argparse
+import yaml
parser = argparse.ArgumentParser(prog='is_valid_diag_table_yaml', \
description="Determine if a yaml diag_table is valid. \
diff --git a/fre/yamltools/field_table/field_table_to_yaml.py b/fre/yamltools/field_table/field_table_to_yaml.py
index 2c0cff90..1067da74 100755
--- a/fre/yamltools/field_table/field_table_to_yaml.py
+++ b/fre/yamltools/field_table/field_table_to_yaml.py
@@ -18,14 +18,13 @@
* You should have received a copy of the GNU Lesser General Public
* License along with FMS. If not, see .
***********************************************************************
-"""
-""" Converts a legacy ascii field_table to a yaml field_table.
+Converts a legacy ascii field_table to a yaml field_table.
Author: Eric Stofferahn 07/14/2022
+
"""
import re
-import sys
from collections import OrderedDict
import click
import yaml
diff --git a/fre/yamltools/freyamltools.py b/fre/yamltools/freyamltools.py
index 125d0005..f603f803 100644
--- a/fre/yamltools/freyamltools.py
+++ b/fre/yamltools/freyamltools.py
@@ -1,16 +1,19 @@
+''' fre yamltools '''
+
import click
from .freyamltoolsexample import yamltools_test_function
@click.group(help=click.style(" - access fre yamltools subcommands", fg=(202,177,95)))
-def yamltoolsCli():
- pass
+def yamltools_cli():
+ ''' entry point to fre yamltools click commands '''
-@yamltoolsCli.command()
+@yamltools_cli.command()
@click.option('--uppercase', '-u', is_flag=True, help = 'Print statement in uppercase.')
@click.pass_context
def function(context, uppercase):
+ # pylint: disable=unused-argument
""" - Execute fre yamltools test """
context.forward(yamltools_test_function)
if __name__ == "__main__":
- yamltoolsCli()
+ yamltools_cli()
diff --git a/fre/yamltools/freyamltoolsexample.py b/fre/yamltools/freyamltoolsexample.py
index 22fa6bef..e86fb206 100644
--- a/fre/yamltools/freyamltoolsexample.py
+++ b/fre/yamltools/freyamltoolsexample.py
@@ -7,7 +7,7 @@
import click
@click.command()
-def yamltools_test_function(uppercase):
+def yamltools_test_function(uppercase=None):
"""Execute fre list testfunction2."""
statement = "testingtestingtestingtesting"
if uppercase: