1 """!parses UNIX conf files and makes the result readily available
3 The hwrf.config module reads configuration information for the HWRF
4 system from one or more *.conf files, via the Python ConfigParser
5 module. This module also automatically fills in certain information,
6 such as fields calculated from the tcvitals or date. The result is
7 accessible via the HWRFConfig class, which provides many ways of
8 automatically accessing configuration options."""
12 __all__=[
'from_file',
'from-string',
'confwalker',
'HWRFConfig',
'fordriver',
'ENVIRONMENT']
14 import ConfigParser,collections,re,string,os,logging,threading
15 import os.path,sys,StringIO
28 from string
import Formatter
29 from ConfigParser
import SafeConfigParser,NoOptionError,NoSectionError
34 """!returns environment variables, allowing substitutions
36 This class is used to read (but not write) environment variables
37 and provide default values if an environment variable is unset or
38 blank. It is only meant to be used in string formats, by passing
39 ENV=ENVIRONMENT. There is a global constant in this module,
40 ENVIRONMENT, which is an instance of this class. You should never
41 need to instantiate another one."""
43 """!Determines if __getitem__ will return something (True) or
44 raise KeyError (False). Same as "s in os.environ" unless s
45 contains "|-", in which case, the result is True."""
46 return s.find(
'|-')>=0
or s
in os.environ
48 """!Same as os.environ[s] unless s contains "|-".
49 ENVIRONMENT["VARNAME|-substitute"]
50 will return os.environ[VARNAME] if VARNAME is defined and
51 non-empty in os.environ. Otherwise, it will return
55 if i<0:
return os.environ[s]
58 val=os.environ.get(var,
'')
59 if val!=
'':
return val
67 """!Internal class that implements HWRFConfig.strinterp()
69 This class is part of the implementation of HWRFConfig: it is
70 used to interpolate strings using a syntax similar to
71 string.format(), but it allows recursion in the config sections,
72 and it also is able to use the [config] and [dir] sections as
73 defaults for variables not found in the current section."""
75 """!Constructor for ConfFormatter"""
78 """!Return the value of variable, or a substitution.
80 Never call this function. It is called automatically by
81 str.format. It provides the value of an variable,
82 or a string substitution.
83 @param key the string key being analyzed by str.format()
84 @param args the indexed arguments to str.format()
85 @param kwargs the keyword arguments to str.format()"""
87 if kwargs[
'__depth']>=ConfigParser.MAX_INTERPOLATION_DEPTH:
88 raise ConfigParser.InterpolationDepthError(kwargs[
'__key'],
89 kwargs[
'__section'],key)
91 if isinstance(key,int):
93 conf=kwargs.get(
'__conf',
None)
96 elif '__taskvars' in kwargs \
97 and kwargs[
'__taskvars'] \
98 and key
in kwargs[
'__taskvars']:
99 v=kwargs[
'__taskvars'][key]
106 section=kwargs.get(
'__section',
None)
110 section=kwargs.get(
'__section',
None)
111 conf=kwargs.get(
'__conf',
None)
113 if section
is not None and conf
is not None:
114 if conf.has_option(section,key):
115 v=conf.get(section,key)
116 elif conf.has_option(section,
'@inc'):
117 for osec
in conf.get(section,
'@inc').split(
','):
118 if conf.has_option(osec,key):
121 if conf.has_option(
'config',key):
122 v=conf.get(
'config',key)
123 elif conf.has_option(
'dir',key):
124 v=conf.get(
'dir',key)
128 if isinstance(v,basestring):
129 if v.find(
'{')>=0
or v.find(
'%')>=0:
130 vnew=self.vformat(v,args,kwargs)
131 assert(vnew
is not None)
141 FCST_KEYS={
'fYMDHM':
'%Y%m%d%H%M',
'fYMDH':
'%Y%m%d%H',
'fYMD':
'%Y%m%d',
142 'fyear':
'%Y',
'fYYYY':
'%Y',
'fYY':
'%y',
'fCC':
'%C',
'fcen':
'%C',
143 'fmonth':
'%m',
'fMM':
'%m',
'fday':
'%d',
'fDD':
'%d',
'fhour':
'%H',
144 'fcyc':
'%H',
'fHH':
'%H',
'fminute':
'%M',
'fmin':
'%M' }
145 """A list of keys recognized by ConfTimeFormatter if the key is
146 requested during string interpolation, and the key is not in the
147 relevant section. This list of keys represents the forecast time. It
148 is a dict mapping from the key name to the format sent to
149 datetime.datetime.strftime to generate the string value."""
153 ANL_KEYS={
'aYMDHM':
'%Y%m%d%H%M',
'aYMDH':
'%Y%m%d%H',
'aYMD':
'%Y%m%d',
154 'ayear':
'%Y',
'aYYYY':
'%Y',
'aYY':
'%y',
'aCC':
'%C',
'acen':
'%C',
155 'amonth':
'%m',
'aMM':
'%m',
'aday':
'%d',
'aDD':
'%d',
'ahour':
'%H',
156 'acyc':
'%H',
'aHH':
'%H',
'aminute':
'%M',
'amin':
'%M' }
157 """A list of keys recognized by ConfTimeFormatter if the key is
158 requested during string interpolation, and the key is not in the
159 relevant section. This list of keys represents the analysis time. It
160 is a dict mapping from the key name to the format sent to
161 datetime.datetime.strftime to generate the string value."""
165 ANL_M6_KEYS={
'am6YMDHM':
'%Y%m%d%H%M',
'am6YMDH':
'%Y%m%d%H',
'am6YMD':
'%Y%m%d',
166 'am6year':
'%Y',
'am6YYYY':
'%Y',
'am6YY':
'%y',
'am6CC':
'%C',
'am6cen':
'%C',
167 'am6month':
'%m',
'am6MM':
'%m',
'am6day':
'%d',
'am6DD':
'%d',
'am6hour':
'%H',
168 'am6cyc':
'%H',
'am6HH':
'%H',
'am6minute':
'%M',
'am6min':
'%M' }
169 """A list of keys recognized by ConfTimeFormatter if the key is
170 requested during string interpolation, and the key is not in the
171 relevant section. This list of keys represents the analysis time. It
172 is a dict mapping from the key name to the format sent to
173 datetime.datetime.strftime to generate the string value."""
177 ANL_P6_KEYS={
'ap6YMDHM':
'%Y%m%d%H%M',
'ap6YMDH':
'%Y%m%d%H',
'ap6YMD':
'%Y%m%d',
178 'ap6year':
'%Y',
'ap6YYYY':
'%Y',
'ap6YY':
'%y',
'ap6CC':
'%C',
'ap6cen':
'%C',
179 'ap6month':
'%m',
'ap6MM':
'%m',
'ap6day':
'%d',
'ap6DD':
'%d',
'ap6hour':
'%H',
180 'ap6cyc':
'%H',
'ap6HH':
'%H',
'ap6minute':
'%M',
'ap6min':
'%M' }
181 """A list of keys recognized by ConfTimeFormatter if the key is
182 requested during string interpolation, and the key is not in the
183 relevant section. This list of keys represents the analysis time. It
184 is a dict mapping from the key name to the format sent to
185 datetime.datetime.strftime to generate the string value."""
190 TIME_DIFF_KEYS=set([
'fahr',
'famin',
'fahrmin'])
191 """A list of keys recognized by ConfTimeFormatter if the key is
192 requested during string interpolation, and the key is not in the
193 relevant section. This list of keys represents the time difference
194 between the forecast and analysis time. Unlike FCST_KEYS and
195 ANL_KEYS, this is not a mapping: it is a set."""
202 """!internal function that implements time formatting
204 Like its superclass, ConfFormatter, this class is part of the
205 implementation of HWRFConfig, and is used to interpolate strings
206 in a way similar to string.format(). It works the same way as
207 ConfFormatter, but accepts additional keys generated based on the
208 forecast and analysis times:
210 fYMDHM - 201409171200 = forecast time September 17, 2014 at 12:00 UTC
215 fYY - 14 (year % 100)
228 Replace the initial "f" with "a" for analysis times. In addition,
229 the following are available for the time difference between
230 forecast and analysis time. Suppose the forecast is twenty-three
231 hours and nineteen minutes (23:19) after the analysis time:
234 famin - 1399 ( = 23*60+19)
237 """!constructor for ConfTimeFormatter"""
238 super(ConfTimeFormatter,self).
__init__()
240 """!return the value of a variable, or a substitution
242 Never call this function. It is called automatically by
243 str.format. It provides the value of an variable,
244 or a string substitution.
245 @param key the string key being analyzed by str.format()
246 @param args the indexed arguments to str.format()
247 @param kwargs the keyword arguments to str.format()"""
250 if kwargs[
'__depth']>=ConfigParser.MAX_INTERPOLATION_DEPTH:
251 raise ConfigParser.InterpolationDepthError(
252 kwargs[
'__key'],kwargs[
'__section'],v)
254 if isinstance(key,int):
258 elif '__taskvars' in kwargs \
259 and kwargs[
'__taskvars'] \
260 and key
in kwargs[
'__taskvars']:
261 v=kwargs[
'__taskvars'][key]
262 elif '__ftime' in kwargs
and key
in FCST_KEYS:
263 v=kwargs[
'__ftime'].strftime(FCST_KEYS[key])
264 elif '__atime' in kwargs
and key
in ANL_KEYS:
265 v=kwargs[
'__atime'].strftime(ANL_KEYS[key])
266 elif '__atime' in kwargs
and key
in ANL_M6_KEYS:
267 am6=kwargs[
'__atime']-datetime.timedelta(0,3600*6)
268 v=am6.strftime(ANL_M6_KEYS[key])
269 elif '__atime' in kwargs
and key
in ANL_P6_KEYS:
270 ap6=kwargs[
'__atime']+datetime.timedelta(0,3600*6)
271 v=ap6.strftime(ANL_P6_KEYS[key])
272 elif '__ftime' in kwargs
and '__atime' in kwargs
and \
273 key
in TIME_DIFF_KEYS:
275 kwargs[
'__ftime'],kwargs[
'__atime'])
279 v=int(ihours*60+iminutes)
283 v=int(ihours*60+iminutes)
290 section=kwargs.get(
'__section',
None)
294 section=kwargs.get(
'__section',
None)
295 conf=kwargs.get(
'__conf',
None)
297 if conf.has_option(section,key):
298 v=conf.get(section,key)
299 elif conf.has_option(section,
'@inc'):
300 for osec
in conf.get(section,
'@inc').split(
','):
301 if conf.has_option(osec,key):
304 if conf.has_option(
'config',key):
305 v=conf.get(
'config',key)
306 elif conf.has_option(
'dir',key):
307 v=conf.get(
'dir',key)
309 raise KeyError(
'Cannot find key %s in section %s'
310 %(repr(key),repr(section)))
312 if isinstance(v,basestring)
and ( v.find(
'{')!=-1
or
315 vnew=self.vformat(v,args,kwargs)
316 assert(vnew
is not None)
318 except KeyError
as e:
321 raise ConfigParser.InterpolationMissingOptionError(
322 kwargs[
'__key'],kwargs[
'__section'],v,str(e))
330 """!walks through a ConfigParser-like object performing some action
332 Recurses through a ConfigParser-like object "conf" starting at
333 section "start", performing a specified action. The special
334 variable whose name is in recursevar specifies a list of
335 additional sections to recurse into. No section will be processed
336 more than once, and sections are processed in breadth-first order.
337 For each variable seen in each section (including recursevar),
338 this will call selector(sectionname, varname) to see if the
339 variable should be processed. If selector returns True, then
340 acceptor(section, varname, value) will be called.
342 @param conf the ConfigParser-like object
343 @param start the starting section
344 @param selector a function selector(section,option) that decides
345 if an option needs processing (True) or not (False)
346 @param acceptor a function acceptor(section,option,value)
347 run on all options for which the selector returns True
348 @param recursevar an option in each section that lists more
349 sections the confwalker should touch. If the selector returns
350 True for the recursevar, then the recursevar will be sent to
351 the acceptor. However, it will be scanned for sections to
352 recurse into even if the selector rejects it."""
354 requested=[str(start)]
355 while len(requested)>0:
360 for (key,val)
in conf.items(sec):
361 if selector(sec,key):
362 acceptor(sec,key,val)
364 for sec2
in reversed(val.split(
',')):
366 if len(trim)>0
and not trim
in touched:
367 requested.append(trim)
372 """!Reads the specified conf file into an HWRFConfig object.
374 Creates a new HWRFConfig object and instructs it to read the specified file.
375 @param filename the path to the file that is to be read
376 @return a new HWRFConfig object"""
377 if not isinstance(filename,basestring):
378 raise TypeError(
'First input to hwrf.config.from_file must be a string.')
384 """!Reads the given string as if it was a conf file into an HWRFConfig object
386 Creates a new HWRFConfig object and reads the string data into it
387 as if it was a config file
388 @param confstr the config data
389 @return a new HWRFConfig object"""
390 if not isinstance(confstr,basestring):
391 raise TypeError(
'First input to hwrf.config.from_string must be a string.')
393 conf.readstr(confstr)
397 """!a class that contains configuration information
399 This class keeps track of configuration information for all tasks
400 in a running HWRF model. It can be used in a read-only manner as
401 if it was a ConfigParser object. All HWRFTask objects require an
402 HWRFConfig object to keep track of registered task names via the
403 register_task_name method, the current forecast cycle (cycle
404 property) and the Datastore object (datastore property).
406 This class should never be instantiated directly. Instead, you
407 should use the hwrf.config.from_string or hwrf.config.from_file to
408 read configuration information from an in-memory string or a file.
410 Also note that this class should not be used to create a new
411 config file for the first HWRF job in a workflow. The
412 hwrf.launcher module does that for you."""
415 """!HWRFConfig constructor
417 Creates a new HWRFConfig object.
418 @param conf the underlying ConfigParser.SafeConfigParser object
419 that stores the actual config data"""
420 self.
_logger=logging.getLogger(
'hwrf')
422 self.
_lock=threading.RLock()
427 self.
_conf=SafeConfigParser()
if (conf
is None)
else conf
428 self._conf.optionxform=str
430 self._conf.add_section(
'config')
431 self._conf.add_section(
'dir')
434 """!read config data and add it to this object
436 Given a string with conf data in it, parses the data.
437 @param source the data to parse
439 fp=StringIO.StringIO(str(source))
440 self._conf.readfp(fp)
445 """!reads and parses a config file
447 Opens the specified config file and reads it, adding its
448 contents to the configuration. This is used to implement the
449 from_file module-scope function. You can use it again on an
450 HWRFConfig object to read additional files.
451 @param source the file to read
453 self._conf.read(source)
457 """!read config data from an open file
459 Reads a config file from the specified file-like object.
460 This is used to implement the readstr.
461 @param source the opened file to read
463 self._conf.readfp(source)
467 """!reads config data from an in-memory string
469 Reads the given string as a config file. This is used to
470 implement the from_string module-scope function. You can use
471 it again to read more config data into an existing HWRFConfig.
472 @param string the string to parse
474 sio=StringIO.StringIO(string)
475 self._conf.readfp(sio)
479 """!set values of several options in a section
481 Sets the value of several options in one section. The
482 keywords arguments are the names of the options to set and the
483 keyword values are the option values.
484 @param section the section being modified
485 @param kwargs additional keyword arguments are the option names
487 for k,v
in kwargs.iteritems():
489 self._conf.set(section,k,value)
494 WARNING: This is presently unused and may be removed. It does
495 not belong in HWRFConfig.
497 Reads tcvitals from the specified file if specified, or from
498 the current cycle's vitals storage area if not. Does not
499 parse, clean or otherwise modify the vitals: they are assumed
500 to contain output for only one storm, with no duplicate
501 cycles. Ideally, the file should have been created by the
502 hwrf.launcher module. Returns an hwrf.revital.Revital object."""
504 logger.info(
'read vitals from: '+vitfile)
506 with open(vitfile,
'rt')
as f:
507 revital.readfiles([vitfile])
512 """!is this a real-time simulation?
514 Is this configuration for a real-time simulation? Defaults to
515 True if unknown. This is the same as doing
516 getbool('config','realtime',True)."""
517 return self.
getbool(
'config',
'realtime',
True)
518 def set(self,section,key,value):
519 """!set a config option
521 Sets the specified config option (key) in the specified
522 section, to the specified value. All three are converted to
523 strings via str() before setting the value."""
524 self._conf.set(str(section),str(key),str(value))
526 """!grab the thread lock
528 Grabs this HWRFConfig's thread lock. This is only for future
529 compatibility and is never used."""
532 """!release the thread lock
534 Releases this HWRFConfig's thread lock. This is only for
535 future compatibility and is never used.
536 @param a,b,c unused"""
539 """!add an hwrf.hwrftask.HWRFTask to the database
541 Checks to ensure that there is no other task by this name, and
542 records the fact that there is now a task. This is used by
543 the hwrf.hwrftask.HWRFTask to ensure only one task is made by
548 '%s: attempted to use this task name twice'%(name,))
549 self._tasknames.add(name)
550 def log(self,sublog=None):
551 """!returns a logging.Logger object
553 Returns a logging.Logger object. If the sublog argument is
554 provided, then the logger will be under that subdomain of the
555 "hwrf" logging domain. Otherwise, this HWRFConfig's logger
556 (usually the "hwrf" domain) is returned.
557 @param sublog the logging subdomain, or None
558 @return a logging.Logger object"""
559 if sublog
is not None:
561 return logging.getLogger(
'hwrf.'+sublog)
564 """!returns the Datastore
566 Returns the produtil.datastore.Datastore object for this
573 dsfile=self.
getstr(
'config',
'datastore')
575 logger=self.
log(
'datastore'))
580 datastore=property(getdatastore,
None,
None, \
581 """Returns the Datastore object for this HWRF simulation,
582 creating it if necessary. If the underlying datastore file
583 did not already exist, it will be opened in create=True mode.""")
586 """!get the analysis time
588 Returns the analysis time of this HWRF workflow as a
589 datetime.datetime."""
591 self.
_cycle=to_datetime(self._conf.get(
'config',
'cycle'))
594 """!set the analysis time
596 Sets the analysis time of this HWRF workflow. Also sets the
597 [config] section's "cycle" option. Accepts anything that
598 hwrf.numerics.to_datetime recognizes."""
599 cycle=to_datetime(cycle)
600 strcycle=cycle.strftime(
'%Y%m%d%H')
601 self._conf.set(
'config',
'cycle',strcycle)
607 cycle=property(getcycle,setcycle,
None,
608 """The cycle this HWRF simulation should run, as a datetime.datetime.""")
611 """!internal function that sets time-related variables
613 Sets many config options in the [config] section based on this
614 HWRF workflow's analysis time. This is called automatically
615 when the cycle property is assigned. You never need to call
616 this function directly.
618 YMDHM - 201409171200 = forecast time September 17, 2014 at 12:00 UTC
636 for var,fmt
in [ (
'YMDHM',
'%Y%m%d%H%M'), (
'YMDH',
'%Y%m%d%H'),
637 (
'YMD',
'%Y%m%d'), (
'year',
'%Y'), (
'YYYY',
'%Y'),
638 (
'YY',
'%y'), (
'CC',
'%C'), (
'cen',
'%C'),
639 (
'month',
'%m'), (
'MM',
'%m'), (
'day',
'%d'),
640 (
'DD',
'%d'), (
'hour',
'%H'), (
'cyc',
'%H'),
641 (
'HH',
'%H'), (
'minute',
'%M'), (
'min',
'%M') ]:
642 self._conf.set(
'config',var,self._cycle.strftime(fmt))
644 """!add a new config section
646 Adds a section to this HWRFConfig. If the section did not
647 already exist, it will be initialized empty. Otherwise, this
648 function has no effect.
649 @param sec the new section's name"""
651 self._conf.add_section(sec)
654 """!does this section exist?
656 Determines if a config section exists (even if it is empty)
657 @return True if this HWRFConfig has the given section and
659 @param sec the section to check for"""
661 return self._conf.has_section(sec)
663 """! is this option set?
665 Determines if an option is set in the specified section
666 @return True if this HWRFConfig has the given option in the
667 specified section, and False otherwise.
668 @param sec the section
669 @param opt the name of the option in that section"""
671 return self._conf.has_option(sec,opt)
672 def getdir(self,name,default=None,morevars=None,taskvars=None):
673 """! query the "dir" section
675 Search the "dir" section.
676 @return the specified key (name) from the "dir" section.
677 Other options are passed to self.getstr.
679 @param default the default value if the option is unset
680 @param morevars more variables for string substitution
681 @param taskvars even more variables for string substitution
682 @param name the option name to search for"""
684 return self.
getstr(
'dir',name,default=default,
685 morevars=morevars,taskvars=taskvars)
686 def getloc(self,name,default=None,morevars=None,taskvars=None):
687 """!search the config, exe and dir sections in that order
689 Find the location of a file in the named option. Searches
690 the [config], [exe] and [dir] sections in order for an option
691 by that name, returning the first one found.
692 @param default the default value if the option is unset
693 @param morevars more variables for string substitution
694 @param taskvars even more variables for string substitution
695 @param name the option name to search for
696 @returns the resulting value"""
699 return self.
getstr(
'config',name,default=default,
700 morevars=morevars,taskvars=taskvars)
702 return self.
getstr(
'exe',name,default=default,
703 morevars=morevars,taskvars=taskvars)
705 return self.
getstr(
'dir',name,default=default,
706 morevars=morevars,taskvars=taskvars)
707 def getexe(self,name,default=None,morevars=None,taskvars=None):
708 """! query the "exe" section
710 Search the "exe" section.
711 @return the specified key (name) from the "exe" section.
712 Other options are passed to self.getstr.
714 @param default the default value if the option is unset
715 @param morevars more variables for string substitution
716 @param taskvars even more variables for string substitution
717 @param name the option name to search for"""
719 return self.
getstr(
'exe',name,default=default,morevars=morevars,
722 """!convenience function; replaces self.items and self.get
724 This is a convenience function that provides access to the
725 self.items or self.get functions.
727 * conf["section"] -- returns a dict containing the results of
729 * conf[a,b,c] -- returns self.get(a,b,c)
730 (b and c are optional)
731 @param arg the arguments: a list or string"""
733 if isinstance(arg,str):
734 return dict(self.
items(arg))
735 elif ( isinstance(arg,list)
or isinstance(arg,tuple) ):
736 if len(arg)==1:
return dict(self.
items(arg))
737 if len(arg)==2:
return self.
get(str(arg[0]),str(arg[1]))
738 if len(arg)==3:
return self.
get(str(arg[0]),str(arg[1]),
740 return NotImplemented
742 """!calls produtil.fileop.makedirs() on directories in the [dir] section
744 This is a simple utility function that calls
745 produtil.fileop.makedirs() on some of the directories in the
747 @param args the keys in the [dir] section for the directories
750 dirs=[self.
getstr(
'dir',arg)
for arg
in args]
754 """!get options in a section
756 Returns a list containing the config options in the given
758 @param sec the string name of the section"""
760 return [ opt
for opt
in self._conf.options(sec) ]
761 def items(self,sec,morevars=None,taskvars=None):
762 """!get the list of (option,value) tuples for a section
764 Returns a section's options as a list of two-element
765 tuples. Each tuple contains a config option, and the value of
766 the config option after string interpolation. Note that the
767 special config section inclusion option "@inc" is also
769 @param sec the section
770 @param morevars variables for string substitution
771 @param taskvars yet more variables
772 @return a list of (option,value) tuples, where the value is
773 after string expansion"""
776 for opt
in self._conf.options(sec):
777 out.append((opt,self.
_interp(sec,opt,morevars,
781 """!write the contents of this HWRFConfig to a file
783 Writes the contents of an HWRFConfig to the specified file,
784 without interpolating (expanding) any strings. The file will
785 be suitable for reading in to a new HWRFConfig object in a
786 later job. This is used by the hwrf.launcher module to create
787 the initial config file.
788 @param fileobject an opened file to write to"""
790 self._conf.write(fileobject)
792 """!return the raw value of an option
794 Returns the raw value for the specified section and option,
795 without string interpolation. That is, any {...} will be
796 returned unmodified. Raises an exception if no value is set.
797 Will not search other sections, unlike other accessors.
798 @param sec the section
799 @param opt the option name
800 @param default the value to return if the option is unset.
801 If unspecified or None, NoOptionError is raised"""
803 return self._conf.get(sec,opt,raw=
True)
804 except NoOptionError:
805 if default
is not None:
return default
808 """!perform string expansion
810 Performs this HWRFConfig's string interpolation on the
811 specified string, as if it was a value from the specified
813 @param sec the section name
814 @param string the string to expand
815 @param kwargs more variables for string substitution"""
816 assert(isinstance(sec,basestring))
817 assert(isinstance(string,basestring))
819 if 'vit' not in kwargs
and 'syndat' in self.__dict__:
820 kwargs[
'vit']=self.syndat.__dict__
821 if 'oldvit' not in kwargs
and 'oldsyndat' in self.__dict__:
822 kwargs[
'oldvit']=self.oldsyndat.__dict__
823 return self._formatter.format(string,__section=sec,
824 __key=
'__string__',__depth=0,__conf=self.
_conf,
825 ENV=ENVIRONMENT,**kwargs)
827 """!performs string expansion, including time variables
829 Performs this HWRFConfig's string interpolation on the
830 specified string, as self.strinterp would, but adds in
831 additional keys based on the given analysis and forecast
832 times. The keys are the same as the keys added to [config]
833 for the cycle, except with "a" prepended for the analysis
834 time, or "f" for the forecast time. There are three more keys
835 for the difference between the forecast an analysis time. The
836 famin is the forecast time in minutes, rounded down. The fahr
837 and fahrmin are the forecast hour, rounded down, and the
838 remainder in minutes, rounded down to the next nearest minute.
840 If the analysis time is None or unspecified, then self.cycle
841 is used. The atime can be anything understood by
842 hwrf.numerics.to_datetime and the ftime can be anything
843 understood by hwrf.numerics.to_datetime_rel, given the atime
844 (or, absent atime, self.cycle) as the second argument.
846 This is implemented as a wrapper around the
847 self._time_formatter object, which knows how to expand the a*
848 and f* variables without having to generate all of them.
850 @param sec the section name
851 @param string the string to expand
852 @param ftime the forecast time or None
853 @param atime the analysis time or None
854 @param kwargs more variables for string expansion"""
855 if atime
is not None:
860 if 'vit' not in kwargs
and 'syndat' in self.__dict__:
861 kwargs[
'vit']=self.syndat.__dict__
862 if 'oldvit' not in kwargs
and 'oldsyndat' in self.__dict__:
863 kwargs[
'oldvit']=self.oldsyndat.__dict__
865 return self._time_formatter.format(string,__section=sec,
866 __key=
'__string__',__depth=0,__conf=self.
_conf,ENV=ENVIRONMENT,
867 __atime=atime, __ftime=ftime,**kwargs)
869 def _interp(self,sec,opt,morevars=None,taskvars=None):
870 """!implementation of data-getting routines
872 This is the underlying implementation of the various self.get*
873 routines, and lies below the self._get. It reads a config
874 option opt from the config section sec.
876 If the string contains a {...} expansion, the _interp will
877 perform string interpolation, expanding {...} strings
878 according to ConfigParser rules. If the section contains an
879 @inc, and any variables requested are not found, then the
880 sections listed in @inc are searched. Failing that, the
881 config and dir sections are searched.
883 @param sec the section name
884 @param opt the option name
885 @param morevars a dict containing variables whose values will
886 override anything in this HWRFConfig when performing string
888 @param taskvars serves the same purpose as morevars, but
889 provides a second scope.
890 @return the result of the string expansion"""
893 if 'syndat' in self.__dict__: vitdict=self.syndat.__dict__
894 if 'oldsyndat' in self.__dict__: olddict=self.oldsyndat.__dict__
896 sections=( sec,
'config',
'dir',
'@inc' )
898 for section
in sections:
901 inc=self._conf.get(sec,
'@inc')
902 except NoOptionError:
905 touched=
set(( sec,
'config',
'dir' ))
906 for incsection
in inc.split(
","):
907 trim=incsection.strip()
908 if len(trim)>0
and trim
not in touched:
911 got=self._conf.get(trim,opt,raw=
True)
914 except (KeyError,NoSectionError,NoOptionError)
as e:
919 got=self._conf.get(section,opt,raw=
True)
922 except (KeyError,NoSectionError,NoOptionError)
as e:
926 raise NoOptionError(opt,sec)
929 return self._formatter.format(got,
930 __section=sec,__key=opt,__depth=0,__conf=self.
_conf, vit=vitdict,
931 ENV=ENVIRONMENT, oldvit=olddict,__taskvars=taskvars)
933 return self._formatter.format(got,
934 __section=sec,__key=opt,__depth=0,__conf=self.
_conf, vit=vitdict,
935 ENV=ENVIRONMENT, oldvit=olddict,__taskvars=taskvars,
938 def _get(self,sec,opt,typeobj,default,badtypeok,morevars=None,taskvars=None):
939 """! high-level implemention of get routines
941 This is the implementation of all of the self.get* routines.
942 It obtains option opt from section sec via the self._interp,
943 providing the optional list of additional variables for string
944 interpolation in the morevars. It then converts to the given
945 type via typeobj (for example, typeobj=int for int
946 conversion). If default is not None, and the variable cannot
947 be found, then the default is returned.
949 @param sec the section name
950 @param opt the option name in that section
951 @param default the default value to return if the variable
952 cannot be found, or None if no default is provided.
953 @param badtypeok if True and default is not None, and the type
954 conversion failed, then default is returned. Otherwise, the
955 TypeError resulting from the failed type conversion is passed
957 @param morevars a dict containing variables whose values will
958 override anything in this HWRFConfig when performing string
960 @param taskvars serves the same purpose as morevars, but
961 provides a second scope. """
963 s=self.
_interp(sec,opt,morevars=morevars,taskvars=taskvars)
964 assert(s
is not None)
966 except NoOptionError:
967 if default
is not None:
972 if default
is not None:
return default
975 def getint(self,sec,opt,default=None,badtypeok=False,morevars=None,taskvars=None):
976 """!get an integer value
978 Gets option opt from section sec and expands it; see "get" for
979 details. Attempts to convert it to an int.
981 @param sec,opt the section and option
982 @param default if specified and not None, then the default is
983 returned if an option has no value or the section does not exist
984 @param badtypeok is True, and the conversion fails, and a
985 default is specified, the default will be returned.
986 @param morevars,taskvars dicts of more variables for string expansion"""
988 return self.
_get(sec,opt,int,default,badtypeok,morevars,taskvars=taskvars)
990 def getfloat(self,sec,opt,default=None,badtypeok=False,morevars=None,taskvars=None):
991 """!get a float value
993 Gets option opt from section sec and expands it; see "get" for
994 details. Attempts to convert it to a float
996 @param sec,opt the section and option
997 @param default if specified and not None, then the default is
998 returned if an option has no value or the section does not exist
999 @param badtypeok is True, and the conversion fails, and a
1000 default is specified, the default will be returned.
1001 @param morevars,taskvars dicts of more variables for string expansion"""
1003 return self.
_get(sec,opt,float,default,badtypeok,morevars,taskvars=taskvars)
1005 def getstr(self,sec,opt,default=None,badtypeok=False,morevars=None,taskvars=None):
1006 """!get a string value
1008 Gets option opt from section sec and expands it; see "get" for
1009 details. Attempts to convert it to a str
1011 @param sec,opt the section and option
1012 @param default if specified and not None, then the default is
1013 returned if an option has no value or the section does not exist
1014 @param badtypeok is True, and the conversion fails, and a
1015 default is specified, the default will be returned.
1016 @param morevars,taskvars dicts of more variables for string expansion"""
1018 return self.
_get(sec,opt,str,default,badtypeok,morevars,taskvars=taskvars)
1020 def get(self,sec,opt,default=None,badtypeok=False,morevars=None,taskvars=None):
1021 """!get the value of an option from a section
1023 Gets option opt from section sec, expands it and converts
1024 to a string. If the option is not found and default is
1025 specified, returns default. If badtypeok, returns default if
1026 the option is found, but cannot be converted. The morevars is
1027 used during string expansion: if {abc} is in the value of the
1028 given option, and morevars contains a key abc, then {abc} will
1029 be expanded using that value. The morevars is a dict that
1030 allows the caller to override the list of variables for string
1032 @param sec,opt the section and option
1033 @param default if specified and not None, then the default is
1034 returned if an option has no value or the section does not exist
1035 @param badtypeok is True, and the conversion fails, and a
1036 default is specified, the default will be returned.
1037 @param morevars,taskvars dicts of more variables for string expansion"""
1040 return self.
_interp(sec,opt,morevars,taskvars=taskvars)
1041 except NoOptionError:
1042 if default
is not None:
1047 """!what options are in this section?
1049 Returns a list of options in the given section
1050 @param sec the section"""
1052 return self._conf.options(sec)
1054 def getboolean(self,sec,opt,default=None,badtypeok=False,morevars=None,taskvars=None):
1055 """!alias for getbool: get a bool value
1057 This is an alias for getbool for code expecting a
1058 ConfigParser. Gets option opt from section sec and expands
1059 it; see "get" for details. Attempts to convert it to a bool
1061 @param sec,opt the section and option
1062 @param default if specified and not None, then the default is
1063 returned if an option has no value or the section does not exist
1064 @param badtypeok is True, and the conversion fails, and a
1065 default is specified, the default will be returned.
1066 @param morevars,taskvars dicts of more variables for string expansion"""
1067 return self.
getbool(sec,opt,default=default,badtypeok=badtypeok,
1068 morevars=morevars,taskvars=taskvars)
1070 def getbool(self,sec,opt,default=None,badtypeok=False,morevars=None,taskvars=None):
1071 """!get a bool value
1073 Gets option opt from section sec and expands it; see "get" for
1074 details. Attempts to convert it to a bool
1076 @param sec,opt the section and option
1077 @param default if specified and not None, then the default is
1078 returned if an option has no value or the section does not exist
1079 @param badtypeok is True, and the conversion fails, and a
1080 default is specified, the default will be returned.
1081 @param morevars,taskvars dicts of more variables for string expansion"""
1084 s=self.
_interp(sec,opt,morevars=morevars,taskvars=taskvars)
1085 except NoOptionError:
1086 if default
is not None:
1087 return bool(default)
1089 if re.match(
'(?i)\A(?:T|\.true\.|true|yes|on|1)\Z',s):
return True
1090 if re.match(
'(?i)\A(?:F|\.false\.|false|no|off|0)\Z',s):
return False
1093 except ValueError
as e:
pass
1094 if badtypeok
and default
is not None:
1095 return bool(default)
1096 raise ValueError(
'%s.%s: invalid value for HWRF conf file boolean: %s'
This module provides a set of utility functions to do filesystem operations.
def getexe
query the "exe" section
def fcst_hr_min(time, start)
Return forecast time in hours and minutes.
def _interp
implementation of data-getting routines
def to_datetime_rel(d, rel)
Converts objects to a datetime relative to another datetime.
def getboolean
alias for getbool: get a bool value
def _get
high-level implemention of get routines
def __getitem__(self, s)
Same as os.environ[s] unless s contains "|-".
def makedirs(self, args)
calls produtil.fileop.makedirs() on directories in the [dir] section
def read_precleaned_vitfile(self, vitfile)
reads tcvitals
def strinterp(self, sec, string, kwargs)
perform string expansion
def getfloat
get a float value
Defines the Revital class which manipulates tcvitals files.
def register_hwrf_task(self, name)
add an hwrf.hwrftask.HWRFTask to the database
def from_string(confstr)
Reads the given string as if it was a conf file into an HWRFConfig object.
def set_time_vars(self)
internal function that sets time-related variables
Defines StormInfo and related functions for interacting with vitals ATCF data.
Raised when more than one task is registered with the same name in an HWRFConfig object.
def log
returns a logging.Logger object
def get
get the value of an option from a section
def getloc
search the config, exe and dir sections in that order
def getstr
get a string value
def readstr(self, source)
read config data and add it to this object
Stores products and tasks in an sqlite3 database file.
def to_datetime(d)
Converts the argument to a datetime.
def add_section(self, sec)
add a new config section
a class that contains configuration information
def makedirs
Make a directory tree, working around filesystem bugs.
Time manipulation and other numerical routines.
def readfp(self, source)
read config data from an open file
def getraw
return the raw value of an option
def __exit__(self, a, b, c)
release the thread lock
def set(self, section, key, value)
set a config option
returns environment variables, allowing substitutions
def setcycle(self, cycle)
set the analysis time
def getdatastore(self)
returns the Datastore
def __contains__(self, s)
Determines if getitem will return something (True) or raise KeyError (False).
def getint
get an integer value
def getcycle(self)
get the analysis time
Stores information about Datum objects in a database.
def from_file(filename)
Reads the specified conf file into an HWRFConfig object.
def confwalker(conf, start, selector, acceptor, recursevar)
walks through a ConfigParser-like object performing some action
def realtime(self)
is this a real-time simulation?
def __enter__(self)
grab the thread lock
def getbool
get a bool value
def keys(self, sec)
get options in a section
def __init__
HWRFConfig constructor.
Exceptions raised by the hwrf package.
def read(self, source)
reads and parses a config file
def write(self, fileobject)
write the contents of this HWRFConfig to a file
def has_section(self, sec)
does this section exist?
def getdir
query the "dir" section
def has_option(self, sec, opt)
is this option set?
def items
get the list of (option,value) tuples for a section
def set_options(self, section, kwargs)
set values of several options in a section
def options(self, sec)
what options are in this section?
cycle
the analysis cycle, a datetime.datetime object
def __getitem__(self, arg)
convenience function; replaces self.items and self.get
This class reads one or more tcvitals files and rewrites them as requested.
def timestrinterp(self, sec, string, ftime, atime=None, kwargs)
performs string expansion, including time variables