Skip to content

Commit ae3c055

Browse files
authored
Merge pull request #108 from falconstryker/devel
MarsVars Tests
2 parents 17eb6b4 + 3dff278 commit ae3c055

File tree

11 files changed

+2128
-935
lines changed

11 files changed

+2128
-935
lines changed

.github/workflows/marscalendar_test.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
11
name: MarsCalendar Test Workflow
2+
# Cancel any in-progress job or previous runs
3+
concurrency:
4+
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
5+
cancel-in-progress: true
26
on:
37
# Trigger the workflow on push to devel branch
48
push:

.github/workflows/marsfiles_test.yml

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -72,21 +72,9 @@ jobs:
7272
# Fix path handling for Windows
7373
$content = $content -replace "os\.path\.join\(self\.test_dir, file\)", "os.path.normpath(os.path.join(self.test_dir, file))"
7474
Set-Content tests/test_marsfiles.py -Value $content
75-
76-
# Run the help message test - fast and doesn't involve file operations
77-
- name: Run help message test
78-
run: |
79-
cd tests
80-
python -m unittest test_marsfiles.TestMarsFiles.test_help_message
81-
82-
# Run the most reliable tests first to get quick feedback
83-
- name: Run reliable tests
84-
run: |
85-
cd tests
86-
python -m unittest test_marsfiles.TestMarsFiles.test_help_message
87-
88-
# Run all tests with increased timeout
89-
- name: Run all tests
75+
76+
# Run the tests
77+
- name: Run MarsFiles tests
9078
timeout-minutes: 25
9179
run: |
9280
cd tests
Lines changed: 28 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
name: MarsPull Test Workflow
2-
2+
# Cancel any in-progress job or previous runs
3+
concurrency:
4+
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
5+
cancel-in-progress: true
36
on:
47
# Trigger the workflow on push to devel branch
58
push:
@@ -25,31 +28,29 @@ jobs:
2528
matrix:
2629
os: [ubuntu-latest, macos-latest, windows-latest]
2730
python-version: ['3.9', '3.10', '3.11']
28-
2931
runs-on: ${{ matrix.os }}
30-
3132
steps:
32-
# Checkout the repository
33-
- uses: actions/checkout@v3
34-
35-
# Set up the specified Python version
36-
- name: Set up Python ${{ matrix.python-version }}
37-
uses: actions/setup-python@v3
38-
with:
39-
python-version: ${{ matrix.python-version }}
40-
41-
# Install dependencies
42-
- name: Install dependencies
43-
shell: bash
44-
run: |
45-
python -m pip install --upgrade pip
46-
pip install requests numpy
47-
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
48-
49-
# Install the package in editable mode
50-
- name: Install package
51-
run: pip install -e .
52-
53-
# Run the tests
54-
- name: Run MarsPull tests
55-
run: python -m unittest -v tests/test_marspull.py
33+
# Checkout the repository
34+
- uses: actions/checkout@v3
35+
36+
# Set up the specified Python version
37+
- name: Set up Python ${{ matrix.python-version }}
38+
uses: actions/setup-python@v3
39+
with:
40+
python-version: ${{ matrix.python-version }}
41+
42+
# Install dependencies
43+
- name: Install dependencies
44+
shell: bash
45+
run: |
46+
python -m pip install --upgrade pip
47+
pip install requests numpy
48+
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
49+
50+
# Install the package in editable mode
51+
- name: Install package
52+
run: pip install -e .
53+
54+
# Run the tests
55+
- name: Run MarsPull tests
56+
run: python -m unittest -v tests/test_marspull.py
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
name: MarsVars Test Workflow
2+
# Cancel any in-progress job or previous runs
3+
concurrency:
4+
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
5+
cancel-in-progress: true
6+
on:
7+
# Trigger the workflow on push to devel branch
8+
push:
9+
branches: [ devel ]
10+
paths:
11+
- 'bin/MarsVars.py'
12+
- 'tests/test_marsvars.py'
13+
- '.github/workflows/marsvars_test.yml'
14+
- 'amescap/FV3_utils.py'
15+
- 'amescap/Script_utils.py'
16+
- 'amescap/Ncdf_wrapper.py'
17+
# Allow manual triggering of the workflow
18+
workflow_dispatch:
19+
# Trigger on pull requests that modify relevant files
20+
pull_request:
21+
branches: [ devel ]
22+
paths:
23+
- 'bin/MarsVars.py'
24+
- 'tests/test_marsvars.py'
25+
- '.github/workflows/marsvars_test.yml'
26+
- 'amescap/FV3_utils.py'
27+
- 'amescap/Script_utils.py'
28+
- 'amescap/Ncdf_wrapper.py'
29+
jobs:
30+
test:
31+
strategy:
32+
matrix:
33+
os: [ubuntu-latest, macos-latest, windows-latest]
34+
python-version: ['3.9', '3.10', '3.11']
35+
fail-fast: true
36+
runs-on: ${{ matrix.os }}
37+
steps:
38+
- uses: actions/checkout@v3
39+
40+
- name: Set up Python ${{ matrix.python-version }}
41+
uses: actions/setup-python@v3
42+
with:
43+
python-version: ${{ matrix.python-version }}
44+
45+
- name: Cache pip dependencies
46+
uses: actions/cache@v3
47+
with:
48+
path: ~/.cache/pip
49+
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
50+
restore-keys: |
51+
${{ runner.os }}-pip-
52+
53+
# Install dependencies
54+
- name: Install dependencies
55+
shell: bash
56+
run: |
57+
python -m pip install --upgrade pip
58+
pip install numpy netCDF4 xarray scipy matplotlib
59+
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
60+
61+
# Install the package in editable mode
62+
- name: Install package
63+
run: pip install -e .
64+
65+
# Set HOME for Windows since it might be used by the script
66+
- name: Set HOME environment variable for Windows
67+
if: runner.os == 'Windows'
68+
shell: pwsh
69+
run: |
70+
echo "HOME=$env:USERPROFILE" >> $env:GITHUB_ENV
71+
72+
# Set up AmesCAP configuration - handle platform differences
73+
- name: Set up AmesCAP configuration
74+
shell: bash
75+
run: |
76+
mkdir -p $HOME/.amescap
77+
cp mars_templates/amescap_profile $HOME/.amescap_profile
78+
79+
# Create a patch for the test file to fix Windows path issues
80+
- name: Create test_marsvars.py path fix for Windows
81+
if: runner.os == 'Windows'
82+
shell: pwsh
83+
run: |
84+
$content = Get-Content tests/test_marsvars.py -Raw
85+
# Fix path handling for Windows
86+
$content = $content -replace "os\.path\.join\(self\.test_dir, file\)", "os.path.normpath(os.path.join(self.test_dir, file))"
87+
Set-Content tests/test_marsvars.py -Value $content
88+
89+
# Run all tests with increased timeout
90+
- name: Run all tests
91+
timeout-minutes: 25
92+
run: |
93+
cd tests
94+
python -m unittest test_marsvars
95+
96+
# Report file paths if things fail on Windows
97+
- name: Debug Windows paths
98+
if: runner.os == 'Windows' && failure()
99+
shell: pwsh
100+
run: |
101+
Write-Host "Current directory: $(Get-Location)"
102+
Write-Host "Test directory contents: $(Get-ChildItem -Path tests)"

amescap/Ncdf_wrapper.py

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -505,14 +505,15 @@ def write_to_average(self, day_average=5):
505505

506506
# Define dimensions
507507
for ivar in ["lat", "lon", "pfull", "phalf", "zgrid"]:
508-
if ivar =="lon":
509-
cart_ax="X"
510-
if ivar =="lat":
511-
cart_ax="Y"
508+
if ivar == "lon":
509+
cart_ax = "X"
510+
if ivar == "lat":
511+
cart_ax = "Y"
512512
if ivar in ["pfull", "phalf", "zgrid"]:
513-
cart_ax="Z"
513+
cart_ax = "Z"
514514
fort_var = self.variables[ivar]
515-
Log.add_dim_with_content(dimension_name = ivar, DATAin = fort_var,
515+
Log.add_dim_with_content(dimension_name = ivar,
516+
DATAin = fort_var,
516517
longname_txt = fort_var.long_name,
517518
units_txt = fort_var.units,
518519
cart_txt = cart_ax)
@@ -527,15 +528,20 @@ def write_to_average(self, day_average=5):
527528
time_in = self.variables["time"]
528529
time_out = daily_to_average(varIN = fort_var,
529530
dt_in = (time_in[1]-time_in[0]),
530-
nday = day_average, trim = True)
531-
Log.log_axis1D(variable_name = "time", DATAin = time_out,
532-
dim_name = "time", longname_txt = time_in.long_name,
533-
units_txt = time_in.units, cart_txt = "T")
531+
nday = day_average,
532+
trim = True)
533+
Log.log_axis1D(variable_name = "time",
534+
DATAin = time_out,
535+
dim_name = "time",
536+
longname_txt = time_in.long_name,
537+
units_txt = time_in.units,
538+
cart_txt = "T")
534539

535540
# Log static variables
536541
for ivar in ["pk", "bk"]:
537542
fort_var = self.variables[ivar]
538-
Log.log_variable(variable_name = ivar, DATAin = fort_var,
543+
Log.log_variable(variable_name = ivar,
544+
DATAin = fort_var,
539545
dim_array = fort_var.dimensions,
540546
longname_txt = fort_var.long_name,
541547
units_txt = fort_var.units)
@@ -546,8 +552,10 @@ def write_to_average(self, day_average=5):
546552
fort_var = self.variables[ivar]
547553
var_out = daily_to_average(varIN = fort_var,
548554
dt_in = (time_in[1]-time_in[0]),
549-
nday = day_average, trim = True)
550-
Log.log_variable(variable_name = ivar, DATAin = var_out,
555+
nday = day_average,
556+
trim = True)
557+
Log.log_variable(variable_name = ivar,
558+
DATAin = var_out,
551559
dim_array = fort_var.dimensions,
552560
longname_txt = fort_var.long_name,
553561
units_txt = fort_var.units)
@@ -570,7 +578,8 @@ def write_to_diurn(self, day_average=5):
570578
if ivar in ["pfull" , "phalf", "zgrid"]:
571579
cart_ax="Z"
572580
fort_var=self.variables[ivar]
573-
Log.add_dim_with_content(dimension_name = ivar, DATAin = fort_var,
581+
Log.add_dim_with_content(dimension_name = ivar,
582+
DATAin = fort_var,
574583
longname_txt = fort_var.long_name,
575584
units_txt = fort_var.units,
576585
cart_txt = cart_ax)

amescap/Script_utils.py

Lines changed: 53 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -242,21 +242,13 @@ def give_permission(filename):
242242
except subprocess.CalledProcessError:
243243
pass
244244

245-
def check_file_tape(fileNcdf, abort=False):
245+
def check_file_tape(fileNcdf):
246246
"""
247-
For use in the NAS environnment only.
248-
Checks whether a file is exists on the disk by running the command
249-
``dmls -l`` on NAS. This prevents the program from stalling if the
250-
files need to be migrated from the disk to the tape.
251-
247+
Checks whether a file exists on the disk. If on a NAS system,
248+
also checks if the file needs to be migrated from tape.
249+
252250
:param fileNcdf: full path to a netcdf file or a file object with a name attribute
253251
:type fileNcdf: str or file object
254-
255-
:param abort: If True, exit the program. Defaults to False
256-
:type abort: bool, optional
257-
258-
:return: None
259-
260252
"""
261253
# Get the filename, whether passed as string or as file object
262254
filename = fileNcdf if isinstance(fileNcdf, str) else fileNcdf.name
@@ -265,42 +257,58 @@ def check_file_tape(fileNcdf, abort=False):
265257
if not re.search(".nc", filename):
266258
print(f"{Red}{filename} is not a netCDF file{Nclr}")
267259
exit()
268-
269-
try:
270-
# Check if the file exists on the disk, exit otherwise. If it
271-
# exists, copy it over from the disk.
272-
# Check if dmls command is available
273-
subprocess.check_call(["dmls"], shell = True,
274-
stdout = open(os.devnull, "w"),
275-
stderr = open(os.devnull, "w"))
276-
# Get the last columns of the ls command (filename and status)
277-
cmd_txt = f"dmls -l {filename}| awk '{{print $8,$9}}'"
278-
# Get 3-letter identifier from dmls -l command, convert byte to
279-
# string for Python3
280-
dmls_out = subprocess.check_output(cmd_txt,
281-
shell = True).decode("utf-8")
282-
if dmls_out[1:4] not in ["DUL", "REG", "MIG"]:
283-
# If file is OFFLINE, UNMIGRATING etc...
284-
if abort :
285-
print(f"{Red}*** Error ***\n{dmls_out}\n{dmls_out[6:-1]} "
286-
f"is not available on disk, status is: {dmls_out[0:5]}"
287-
f"CHECK file status with ``dmls -l *.nc`` and run "
288-
f"``dmget *.nc`` to migrate the files.\nExiting now..."
260+
261+
# First check if the file exists at all
262+
if not os.path.isfile(filename):
263+
print(f"{Red}File {filename} does not exist{Nclr}")
264+
exit()
265+
266+
# Check if we're on a NAS system by looking for specific environment variables
267+
# or filesystem paths that are unique to NAS
268+
is_nas = False
269+
270+
# Method 1: Check for NAS-specific environment variables
271+
nas_env_vars = ['PBS_JOBID', 'SGE_ROOT', 'NOBACKUP', 'NASA_ROOT']
272+
for var in nas_env_vars:
273+
if var in os.environ:
274+
is_nas = True
275+
break
276+
277+
# Method 2: Check for NAS-specific directories
278+
nas_paths = ['/nobackup', '/nobackupp', '/u/scicon']
279+
for path in nas_paths:
280+
if os.path.exists(path):
281+
is_nas = True
282+
break
283+
284+
# Only perform NAS-specific operations if we're on a NAS system
285+
if is_nas:
286+
try:
287+
# Check if dmls command is available
288+
subprocess.check_call(["dmls"], shell=True,
289+
stdout=open(os.devnull, "w"),
290+
stderr=open(os.devnull, "w"))
291+
292+
# Get the last columns of the ls command (filename and status)
293+
cmd_txt = f"dmls -l {filename}| awk '{{print $8,$9}}'"
294+
295+
# Get identifier from dmls -l command
296+
dmls_out = subprocess.check_output(cmd_txt, shell=True).decode("utf-8")
297+
298+
if dmls_out[1:4] not in ["DUL", "REG", "MIG"]:
299+
# If file is OFFLINE, UNMIGRATING etc...
300+
print(f"{Yellow}*** Warning ***\n{dmls_out[6:-1]} "
301+
f"is not loaded on disk (Status: {dmls_out[0:5]}). "
302+
f"Please migrate it to disk with:\n"
303+
f"``dmget {dmls_out[6:-1]}``\n then try again."
289304
f"\n{Nclr}")
290305
exit()
291-
else:
292-
print(f"{Yellow}*** Warning ***\n{dmls_out[6:-1]} is not "
293-
f"available on the disk. Status: {dmls_out[0:5]}.\n"
294-
f"Consider checking file status with ``dmls -l *.nc`` "
295-
f"and run ``dmget *.nc`` to migrate the files.\n"
296-
f"Waiting for file to be migrated to the disk, this "
297-
f"may take awhile...")
298-
except subprocess.CalledProcessError:
299-
# Return an eror message
300-
if abort:
301-
exit()
302-
else:
306+
except (subprocess.CalledProcessError, FileNotFoundError, IndexError):
307+
# If there's any issue with the dmls command, log it but continue
308+
if "--debug" in sys.argv:
309+
print(f"{Yellow}Warning: Could not check tape status for {filename}{Nclr}")
303310
pass
311+
# Otherwise, we're not on a NAS system, so just continue
304312

305313

306314
def get_Ncdf_path(fNcdf):

0 commit comments

Comments
 (0)