1- #!/usr/bin/env python3
1+ #!/usr/bin/env python
22'''
33*****************************COPYRIGHT******************************
4- (C) Crown copyright 2022-2025 Met Office. All rights reserved.
4+ (C) Crown copyright 2021 Met Office. All rights reserved.
55
66 Use, duplication or disclosure of this code is subject to the restrictions
77 as set forth in the licence. If no licence has been raised with this copy
1818 Common functions and classes required by multiple model drivers
1919'''
2020
21-
22-
23- import datetime
24- import glob
25- import shutil
21+ #The from __future__ imports ensure compatibility between python2.7 and 3.x
22+ from __future__ import absolute_import
23+ import copy
2624import re
2725import os
2826import sys
3230import error
3331import inc_days
3432
35-
3633class ModNamelist (object ):
3734 '''
3835 Modify a fortran namelist. This will not add any new variables, only
@@ -49,7 +46,7 @@ def __init__(self, filename):
4946 def var_val (self , variable , value ):
5047 '''
5148 Create a container of variable name, value pairs to be updated. Note
52- that if a variable doesn't exist in the namelist file, then it
49+ that if a variable doesn't exisit in the namelist file, then it
5350 will be ignored
5451 '''
5552 if isinstance (value , str ):
@@ -83,7 +80,7 @@ def find_previous_workdir(cyclepoint, workdir, taskname, task_param_run=None):
8380 '''
8481 Find the work directory for the previous cycle. Takes as argument
8582 the current cyclepoint, the path to the current work directory, and
86- the current taskname, a value specifying multiple tasks within
83+ the current taskname, a value specifying multiple tasks within
8784 same cycle (e.g. coupled_run1, coupled_run2) as used in coupled NWP
8885 and returns an absolute path.
8986 '''
@@ -100,7 +97,7 @@ def find_previous_workdir(cyclepoint, workdir, taskname, task_param_run=None):
10097
10198 return previous_workdir
10299
103- else :
100+ else :
104101 cyclesdir = os .sep .join (workdir .split (os .sep )[:- 2 ])
105102 #find the work directory for the previous cycle
106103 work_cycles = os .listdir (cyclesdir )
@@ -121,7 +118,7 @@ def find_previous_workdir(cyclepoint, workdir, taskname, task_param_run=None):
121118 sys .stderr .write ('[FAIL] Can not find previous work directory for'
122119 ' task %s\n ' % taskname )
123120 sys .exit (error .MISSING_DRIVER_FILE_ERROR )
124-
121+
125122 return os .path .join (cyclesdir , previous_task_cycle , taskname )
126123
127124
@@ -139,6 +136,7 @@ def get_filepaths(directory):
139136 return file_paths
140137
141138
139+
142140def open_text_file (name , mode ):
143141 '''
144142 Provide a common function to open a file and provide a suitiable error
@@ -152,7 +150,7 @@ def open_text_file(name, mode):
152150 'a+' :'updating (appending)' }
153151 if mode not in list (modes .keys ()):
154152 options = ''
155- for k in modes :
153+ for k in modes . keys () :
156154 options += ' %s: %s\n ' % (k , modes [k ])
157155 sys .stderr .write ('[FAIL] Attempting to open file %s, do not recognise'
158156 ' mode %s. Please use one of the following modes:\n %s'
@@ -188,6 +186,28 @@ def remove_file(filename):
188186 else :
189187 return False
190188
189+ def remove_trailing_slash (path_str ):
190+ '''
191+ Takes a string of a path and removes any trailing slashes and spaces if
192+ there are any present
193+ '''
194+ trailing_slash_regex = r'[\w/]*\w+([\s/]+)$'
195+ match = re .match (trailing_slash_regex , path_str )
196+ if match :
197+ num_trailing_slashes = len (match .group (1 ))
198+ return path_str [:- num_trailing_slashes ]
199+ return path_str
200+
201+
202+ def remove_trailing_slash_orig (path_str ):
203+ '''
204+ Takes a string of a path and removes the trailing slash if there is one
205+ present
206+ '''
207+ if path_str [- 1 ] == '/' :
208+ return path_str [:- 1 ]
209+ return path_str
210+
191211def setup_runtime (common_env ):
192212 '''
193213 Set up model run length in seconds based on the model suite
@@ -324,53 +344,3 @@ def set_aprun_options(nproc, nodes, ompthr, hyperthreads, ss):
324344 rose_launcher_preopts = "-ss " + rose_launcher_preopts
325345
326346 return rose_launcher_preopts
327-
328-
329- def _sort_hist_dirs_by_date (dir_list ):
330- '''
331- Sort a list of history directories by date
332- '''
333- # Pattern that defines the name of the history directories,
334- # which contain a date of the form YYYYmmddHHMM.
335- pattern = r'\.(\d{12})'
336-
337- try :
338- dir_list .sort (key = lambda dname : datetime .datetime .strptime (
339- re .search (pattern , dname ).group (1 ), '%Y%m%d%H%M' ))
340- except AttributeError :
341- msg = '[FAIL] Cannot order directories: %s' % " " .join (dir_list )
342- sys .stderr .write (msg )
343- sys .exit (error .IOERROR )
344-
345- return dir_list
346-
347-
348- def remove_latest_hist_dir (old_hist_dir ):
349- '''
350- If a model task has failed, then removed the last created history
351- directory, before a new one is created, associated with the
352- re-attempt.
353- '''
354- # Replace the regex pattern that defines the history directory
355- # name (that contains a date of the format YYYYmmddHHMM) with a
356- # generic pattern so that we can perform the directory glob.
357- history_pattern = re .sub (
358- r'\.\d{12}' , '.????????????' , old_hist_dir )
359-
360- # Find and sort the history directories, and delete
361- # the latest one, corresponding to the last entry in
362- # the list.
363- history_dirs = glob .glob (history_pattern )
364- history_dirs = _sort_hist_dirs_by_date (history_dirs )
365-
366- msg = '[INFO] Found history directories: %s \n ' % ' ' .join (
367- history_dirs )
368- sys .stdout .write (msg )
369-
370- latest_hist_dir = history_dirs [- 1 ]
371- msg = ("[WARN] Re-attempting failed model step. \n "
372- "[WARN] Clearing out latest history \n "
373- "[WARN] directory %s. \n " % latest_hist_dir )
374- sys .stdout .write (msg )
375-
376- shutil .rmtree (latest_hist_dir )
0 commit comments