Skip to content

Commit 7dc048f

Browse files
authored
Allow restart check to wait for files to write (#12)
* Allowing restartcheck to wait for missing hdf5 files * Adding debugging information to geos_ats docs * Adding a check for lfs pointer objects
1 parent 3c6f5d7 commit 7dc048f

File tree

5 files changed

+142
-52
lines changed

5 files changed

+142
-52
lines changed

docs/geos_ats.rst

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,18 @@ Primary entry point for running integrated tests.
2626
Other machine-specific options for ATS can be viewed by running `run_geos_ats --ats help`
2727

2828

29+
Debugging
30+
------------------
31+
32+
If for any reason you need to debug the geos_ats package, we recommend that you create a local copy of this entry point in the `build/integratedTests` directory: `geosPythonPackages/geos_ats_package/geos_ats/debug_geos_ats.py`.
33+
This script is designed as a debugger entry point, and will read the autogenerated run script that was built during setup.
34+
To use it, you must either have geos_ats installed in your target python environment, or a copy of geosPythonPackages in the expected location (`/usr/workspace/[username]/geosPythonPackages`).
35+
36+
We recommend that you use VSCode with the Python extension to debug geos_ats.
37+
To begin the debugging session, you simply need to load the entry script, set any initial breakpoints you desire, then select the Debug run option.
38+
Note that this approach can only be used to debug the python code associated with tests, and not the underlying GEOS tests.
39+
40+
2941
API
3042
------
3143

docs/index.rst

Lines changed: 45 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,30 +8,65 @@ Python Tools
88
Python Tools Setup
99
---------------------------------
1010

11-
The preferred method to setup the GEOSX python tools is to run the following command in the build directory:
11+
The preferred method to setup the GEOS python tools is to run the following command in the build directory:
1212

1313
.. code-block:: bash
1414
1515
make geosx_python_tools
1616
1717
18-
This will attempt to install the required packages into the python distribution indicated via the `Python3_EXECUTABLE` cmake variable (also used by pygeosx).
18+
The ats setup command also sets up the python tools:
1919

20-
If the user does not have write access for the target python distribution, the installation will attempt to create a new virtual python environment (Note: this requires that the virtualenv package be installed).
20+
.. code-block:: bash
21+
22+
make ats_environment
23+
24+
25+
These will attempt to install the required packages into the python distribution indicated via the `Python3_EXECUTABLE` cmake variable (also used by pygeosx).
2126
If any package dependencies are missing, then the install script will attempt to fetch them from the internet using pip.
22-
After installation, these packages will be available for import within the associated python distribution, and a set of console scripts will be available within the GEOSX build bin directory.
27+
After installation, these packages will be available for import within the associated python distribution, and a set of console scripts will be available within the GEOS build bin directory.
28+
29+
30+
.. note::
31+
To re-install or update an installed version of geosPythonTools, you can run the `make geosx_python_tools_clean` and `make geosx_python_tools` commands.
32+
33+
34+
Manual Installation
35+
---------------------------------
36+
37+
In some cases, you may need to manually install or update geosPythonPackages.
38+
To do this, you can clone a copy of the geosPythonPackages repository and install them using pip:
2339

24-
Alternatively, these packages can be installed manually into a python environment using pip:
2540

2641
.. code-block:: bash
2742
28-
cd GEOSX/src/coreComponents/python/modules/geosx_mesh_tools_package
29-
pip install --upgrade .
43+
cd /path/to/store/python/tools
44+
git clone https://github.com/GEOS-DEV/geosPythonPackages.git
45+
46+
# Install/upgrade geos_ats
47+
cd geosPythonPackages/geos_ats_package
48+
python -m pip install --upgrade .
49+
50+
51+
.. note::
52+
To upgrade an existing installation, the python executable in the above command should correspond to the version you indicated in your host config. If you have previously built the tools, this version will be linked in the build directory: `build_dir/bin/python`.
53+
54+
55+
Development & Debugging
56+
---------------------------
57+
58+
Be default, the python environment setup commands target the "main" branch of geosPythonTools.
59+
To target another version of the tools, you can set the `GEOS_PYTHON_PACKAGES_BRANCH` cmake variable to the name of another valid branch (or git tag) in the host config file.
60+
In this case, the code will pull the most recent commit of the desired branch when building geosPythonTools.
61+
62+
63+
.. note::
64+
If you are working on significant updates to geosPythonTools, you should open a testing branch in the main GEOS repository that defines the `GEOS_PYTHON_PACKAGES_BRANCH` variable. This will ensure that your changes are tested as part of the GEOS CI.
65+
3066

31-
cd ../geosx_xml_tools_package
32-
pip install --upgrade .
67+
If you need to debug one of the packages in geosPythonTools, we recommend using VSCode with the Python extension installed.
68+
Some of the packages contain specific entry point scripts that can be used to assist in this process.
3369

34-
# Etc.
3570

3671

3772
Packages
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
"""
2+
Entry point for debugging geos_ats
3+
4+
To use this script, do the following:
5+
- Setup your ats environment (using the 'make ats_environment' command)
6+
- Create a copy of this script in the build/integratedTests directory
7+
- Debug this script with a tool like vscode
8+
9+
Note: if you have a copy of the geosPythonPackages repository located
10+
in your user workspace, then this script will attempt to use that version
11+
of geos_ats instead of the one installed in your environment.
12+
"""
13+
14+
import os
15+
import sys
16+
17+
18+
def debug_geos_ats():
19+
# Check for a copy of geos_ats in the user's workspace to use
20+
# instead of any currently installed in python
21+
user = os.environ.get( 'USER', '' )
22+
mod_path = f"/usr/workspace/{user}/geosPythonPackages/geos_ats_package"
23+
if os.path.isdir( mod_path ):
24+
sys.path.insert( 0, os.path.join( mod_path ) )
25+
26+
# Collect command line args from autogenerated script
27+
fname = os.path.join( os.path.dirname( __file__ ), 'geos_ats.sh' )
28+
args = open( fname, 'r' ).readlines()[ 1 ].split()[ 1:-1 ]
29+
sys.argv.extend( args )
30+
31+
# Run ats
32+
from geos_ats import main
33+
main.main()
34+
35+
36+
if __name__ == '__main__':
37+
debug_geos_ats()

geos_ats_package/geos_ats/geos_ats_debug.py

Lines changed: 0 additions & 31 deletions
This file was deleted.

geos_ats_package/geos_ats/helpers/restart_check.py

Lines changed: 48 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import re
77
import argparse
88
import logging
9+
import time
910
from pathlib import Path
1011
try:
1112
from geos_ats.helpers.permute_array import permuteArray # type: ignore[import]
@@ -31,6 +32,36 @@ def write( output, msg ):
3132
output.write( msg )
3233

3334

35+
def is_lfs_pointer( fname ):
36+
res = False
37+
try:
38+
header = str( open( fname, 'rb' ).read( 16 ) )
39+
if 'Git LFS pointer' in header:
40+
res = True
41+
except Exception:
42+
pass
43+
44+
return res
45+
46+
47+
def load_hdf5( fname, max_wait_time=10, mode='r' ):
48+
file = None
49+
for ii in range( max_wait_time ):
50+
if os.path.isfile( fname ):
51+
try:
52+
file = h5py.File( fname, mode )
53+
logger.debug( f'Opened file: {fname}' )
54+
break
55+
except IOError:
56+
logger.warning( f'Failed to open file: {fname} (attempt {ii+1}/{max_wait_time})' )
57+
if is_lfs_pointer( fname ):
58+
raise Exception( f'Target LFS object is not initialized: {fname}' )
59+
60+
time.sleep( 1 )
61+
62+
return file
63+
64+
3465
def h5PathJoin( p1, p2 ):
3566
if p1 == "/":
3667
return "/" + p2
@@ -79,17 +110,23 @@ def __init__( self,
79110
assert ( self.atol >= 0.0 )
80111

81112
def filesDiffer( self ):
82-
try:
83-
with h5py.File( self.file_path, "r" ) as file, h5py.File( self.baseline_path, "r" ) as base_file:
84-
self.file_path = file.filename
85-
self.baseline_path = base_file.filename
86-
self.output.write( "\nRank %s is comparing %s with %s \n" %
87-
( MPI.COMM_WORLD.Get_rank(), self.file_path, self.baseline_path ) )
88-
self.compareGroups( file, base_file )
89-
90-
except IOError as e:
91-
self.logger.debug( e )
92-
self.output.write( str( e ) )
113+
# Check to see if the file is on the disk, and wait in case there is any lag in IO
114+
file = load_hdf5( self.file_path )
115+
base_file = load_hdf5( self.baseline_path )
116+
rank = MPI.COMM_WORLD.Get_rank()
117+
self.output.write( f"\nRank {rank} is comparing {self.file_path} with {self.baseline_path} \n" )
118+
119+
# Compare the files
120+
if ( file is not None ) and ( base_file is not None ):
121+
self.file_path = file.filename
122+
self.baseline_path = base_file.filename
123+
self.compareGroups( file, base_file )
124+
125+
else:
126+
if file is None:
127+
self.output.write( f"\nRank {rank} failed to load target file: {self.file_path}\n" )
128+
if base_file is None:
129+
self.output.write( f"\nRank {rank} failed to load baseline file: {self.baseline_path}\n" )
93130
self.different = True
94131

95132
return self.different

0 commit comments

Comments
 (0)