How to use optional_in method in pandera

Best Python code snippet using pandera_python

metavar.py

Source:metavar.py Github

copy

Full Screen

1#!/usr/bin/env python2#3# Class to hold all information on a CCPP metadata variable4#5# Python library imports6from __future__ import print_function7import re8import xml.etree.ElementTree as ET9from collections import OrderedDict10# CCPP framework imports11from parse_tools import check_fortran_ref, check_fortran_type, context_string12from parse_tools import FORTRAN_DP_RE, FORTRAN_ID13from parse_tools import registered_fortran_ddt_name14from parse_tools import check_dimensions, check_cf_standard_name15from parse_tools import ParseContext, ParseSource16from parse_tools import ParseInternalError, ParseSyntaxError, CCPPError17###############################################################################18real_subst_re = re.compile(r"(.*\d)p(\d.*)")19list_re = re.compile(r"[(]([^)]*)[)]\s*$")20########################################################################21def standard_name_to_long_name(prop_dict, context=None):22########################################################################23 """Translate a standard_name to its default long_name24 >>> standard_name_to_long_name({'standard_name':'cloud_optical_depth_layers_from_0p55mu_to_0p99mu'})25 'Cloud optical depth layers from 0.55mu to 0.99mu'26 >>> standard_name_to_long_name({'local_name':'foo'}) #doctest: +IGNORE_EXCEPTION_DETAIL27 Traceback (most recent call last):28 CCPPError: No standard name to convert foo to long name29 >>> standard_name_to_long_name({}) #doctest: +IGNORE_EXCEPTION_DETAIL30 Traceback (most recent call last):31 CCPPError: No standard name to convert to long name32 >>> standard_name_to_long_name({'local_name':'foo'}, context=ParseContext(linenum=3, filename='foo.F90')) #doctest: +IGNORE_EXCEPTION_DETAIL33 Traceback (most recent call last):34 CCPPError: No standard name to convert foo to long name at foo.F90:335 >>> standard_name_to_long_name({}, context=ParseContext(linenum=3, filename='foo.F90')) #doctest: +IGNORE_EXCEPTION_DETAIL36 Traceback (most recent call last):37 CCPPError: No standard name to convert to long name at foo.F90:338 """39 # We assume that standar_name has been checked for validity40 # Make the first char uppercase and replace each underscore with a space41 if 'standard_name' in prop_dict:42 standard_name = prop_dict['standard_name']43 if len(standard_name) > 0:44 long_name = standard_name[0].upper() + re.sub("_", " ", standard_name[1:])45 else:46 long_name = ''47 # End if48 # Next, substitute a decimal point for the p in [:digit]p[:digit]49 match = real_subst_re.match(long_name)50 while match is not None:51 long_name = match.group(1) + '.' + match.group(2)52 match = real_subst_re.match(long_name)53 # End while54 else:55 long_name = ''56 if 'local_name' in prop_dict:57 lname = ' {}'.format(prop_dict['local_name'])58 else:59 lname = ''60 # End if61 ctxt = context_string(context)62 raise CCPPError('No standard name to convert{} to long name{}'.format(lname, ctxt))63 # End if64 return long_name65########################################################################66def default_kind_val(prop_dict, context=None):67########################################################################68 """Choose a default kind based on a variable's type69 >>> default_kind_val({'type':'REAL'})70 'kind_phys'71 >>> default_kind_val({'type':'complex'})72 'kind_phys'73 >>> default_kind_val({'type':'double precision'})74 'kind_phys'75 >>> default_kind_val({'type':'integer'})76 ''77 >>> default_kind_val({'type':'character'})78 ''79 >>> default_kind_val({'type':'logical'})80 ''81 >>> default_kind_val({'local_name':'foo'}) #doctest: +IGNORE_EXCEPTION_DETAIL82 Traceback (most recent call last):83 CCPPError: No type to find default kind for foo84 >>> default_kind_val({}) #doctest: +IGNORE_EXCEPTION_DETAIL85 Traceback (most recent call last):86 CCPPError: No type to find default kind87 >>> default_kind_val({'local_name':'foo'}, context=ParseContext(linenum=3, filename='foo.F90')) #doctest: +IGNORE_EXCEPTION_DETAIL88 Traceback (most recent call last):89 CCPPError: No type to find default kind for foo at foo.F90:390 >>> default_kind_val({}, context=ParseContext(linenum=3, filename='foo.F90')) #doctest: +IGNORE_EXCEPTION_DETAIL91 Traceback (most recent call last):92 CCPPError: No type to find default kind at foo.F90:393 """94 if 'type' in prop_dict:95 vtype = prop_dict['type'].lower()96 if vtype == 'real':97 kind = 'kind_phys'98 elif vtype == 'complex':99 kind = 'kind_phys'100 elif FORTRAN_DP_RE.match(vtype) is not None:101 kind = 'kind_phys'102 else:103 kind = ''104 # End if105 else:106 kind = ''107 if 'local_name' in prop_dict:108 lname = ' {}'.format(prop_dict['local_name'])109 else:110 lname = ''111 # End if112 ctxt = context_string(context)113 raise CCPPError('No type to find default kind for {}{}'.format(lname, ctxt))114 # End if115 return kind116########################################################################117def ddt_modules(variable_list):118########################################################################119 ddt_mods = set()120 for var in variable_list:121 if var.is_ddt():122 module = var.get_prop_value('module')123 if len(module) > 0:124 ddt_mods.add((module, var.get_prop_value('type')))125 # End if126 # End if127 # End for128 return ddt_mods129########################################################################130class VariableProperty(object):131 """Class to represent a single property of a metadata header entry132 >>> VariableProperty('local_name', str) #doctest: +ELLIPSIS133 <__main__.VariableProperty object at ...>134 >>> VariableProperty('standard_name', str) #doctest: +ELLIPSIS135 <__main__.VariableProperty object at ...>136 >>> VariableProperty('long_name', str) #doctest: +ELLIPSIS137 <__main__.VariableProperty object at ...>138 >>> VariableProperty('units', str) #doctest: +ELLIPSIS139 <__main__.VariableProperty object at ...>140 >>> VariableProperty('dimensions', list) #doctest: +ELLIPSIS141 <__main__.VariableProperty object at ...>142 >>> VariableProperty('type', str) #doctest: +ELLIPSIS143 <__main__.VariableProperty object at ...>144 >>> VariableProperty('kind', str) #doctest: +ELLIPSIS145 <__main__.VariableProperty object at ...>146 >>> VariableProperty('state_variable', str, valid_values_in=['True', 'False', '.true.', '.false.' ], optional_in=True, default_in=False) #doctest: +ELLIPSIS147 <__main__.VariableProperty object at ...>148 >>> VariableProperty('intent', str, valid_values_in=['in', 'out', 'inout']) #doctest: +ELLIPSIS149 <__main__.VariableProperty object at ...>150 >>> VariableProperty('optional', str, valid_values_in=['True', 'False', '.true.', '.false.' ], optional_in=True, default_in=False) #doctest: +ELLIPSIS151 <__main__.VariableProperty object at ...>152 >>> VariableProperty('local_name', str).name153 'local_name'154 >>> VariableProperty('standard_name', str).type155 <type 'str'>156 >>> VariableProperty('units', str).is_match('units')157 True158 >>> VariableProperty('units', str).is_match('UNITS')159 True160 >>> VariableProperty('units', str).is_match('type')161 False162 >>> VariableProperty('value', int, valid_values_in=[1, 2 ]).valid_value('2')163 2164 >>> VariableProperty('value', int, valid_values_in=[1, 2 ]).valid_value('3')165 >>> VariableProperty('value', int, valid_values_in=[1, 2 ]).valid_value('3', error=True) #doctest: +IGNORE_EXCEPTION_DETAIL166 Traceback (most recent call last):167 CCPPError: Invalid value variable property, '3'168 >>> VariableProperty('dimensions', list, check_fn_in=check_dimensions).valid_value('()')169 []170 >>> VariableProperty('dimensions', list, check_fn_in=check_dimensions).valid_value('(x)')171 ['x']172 >>> VariableProperty('dimensions', list, check_fn_in=check_dimensions).valid_value('x')173 >>> VariableProperty('dimensions', list, check_fn_in=check_dimensions).valid_value('(x:y)')174 ['x:y']175 >>> VariableProperty('dimensions', list, check_fn_in=check_dimensions).valid_value('(w:x,y:z)')176 ['w:x', 'y:z']177 >>> VariableProperty('dimensions', list, check_fn_in=check_dimensions).valid_value('(w:x,x:y:z:q)', error=True) #doctest: +IGNORE_EXCEPTION_DETAIL178 Traceback (most recent call last):179 CCPPError: 'x:y:z:q' is an invalid dimension range180 >>> VariableProperty('dimensions', list, check_fn_in=check_dimensions).valid_value('(x:3y)', error=True) #doctest: +IGNORE_EXCEPTION_DETAIL181 Traceback (most recent call last):182 CCPPError: '3y' is not a valid Fortran identifier183 """184 __true_vals = ['t', 'true', '.true.']185 __false_vals = ['f', 'false', '.false.']186 def __init__(self, name_in, type_in, valid_values_in=None, optional_in=False, default_in=None, default_fn_in=None, check_fn_in=None):187 self._name = name_in188 self._type = type_in189 if self._type not in [ bool, int, list, str ]:190 raise CCPPError("{} has invalid VariableProperty type, '{}'".format(name_in, type_in))191 # End if192 self._valid_values = valid_values_in193 self._optional = optional_in194 if self.optional:195 if (default_in is None) and (default_fn_in is None):196 raise CCPPError('default_in or default_fn_in is a required property for {} because it is optional'.format(name_in))197 if (default_in is not None) and (default_fn_in is not None):198 raise CCPPError('default_in and default_fn_in cannot both be provided')199 self._default = default_in200 self._default_fn = default_fn_in201 elif default_in is not None:202 raise CCPPError('default_in is not a valid property for {} because it is not optional'.format(name_in))203 elif default_in is not None:204 raise CCPPError('default_fn_in is not a valid property for {} because it is not optional'.format(name_in))205 self._check_fn = check_fn_in206 @property207 def name(self):208 'Return the name of the property'209 return self._name210 @property211 def type(self):212 'Return the type of the property'213 return self._type214 def get_default_val(self, prop_dict, context=None):215 if self._default_fn is not None:216 return self._default_fn(prop_dict, context)217 elif self._default is not None:218 return self._default219 else:220 ctxt = context_string(context)221 raise CCPPError('No default for variable property {}{}'.format(self.name, ctxt))222 # End if223 @property224 def optional(self):225 return self._optional226 def is_match(self, test_name):227 "Return True iff <test_name> is the name of this property"228 return self.name.lower() == test_name.lower()229 def valid_value(self, test_value, error=False):230 'Return a sanitized version of test_value if valid, otherwise return None or abort'231 valid_val = None232 if self.type is int:233 try:234 tv = int(test_value)235 if self._valid_values is not None:236 if tv in self._valid_values:237 valid_val = tv238 else:239 valid_val = None # i.e. pass240 else:241 valid_val = tv242 except CCPPError:243 valid_val = None # Redundant but more expressive than pass244 elif self.type is list:245 if isinstance(test_value, str):246 match = list_re.match(test_value)247 if match is None:248 tv = None249 else:250 tv = [x.strip() for x in match.group(1).split(',')]251 if (len(tv) == 1) and (len(tv[0]) == 0):252 # Scalar253 tv = list()254 # End if255 # End if256 else:257 tv = test_value258 # End if259 if isinstance(tv, list):260 valid_val = tv261 elif isinstance(tv, tuple):262 valid_val = list(tv)263 else:264 valid_val = None265 # End if266 if (valid_val is not None) and (self._valid_values is not None):267 # Special case for lists, _valid_values applies to elements268 for item in valid_val:269 if item not in self._valid_values:270 valid_val = None271 break272 # End if273 # End for274 else:275 pass276 elif self.type is bool:277 if isinstance(test_value, str):278 if test_value.lower() in VariableProperty.__true_vals + VariableProperty.__false_vals:279 valid_val = test_value.lower() in VariableProperty.__true_vals280 else:281 valid_val = None # i.e., pass282 else:283 valid_val = not not test_value284 elif self.type is str:285 if isinstance(test_value, str):286 if self._valid_values is not None:287 if test_value in self._valid_values:288 valid_val = test_value289 else:290 valid_val = None # i.e., pass291 else:292 valid_val = test_value293 # End if294 # End if295 # End if296 # Call a check function?297 if valid_val and (self._check_fn is not None):298 valid_val = self._check_fn(valid_val, error=error)299 elif (valid_val is None) and error:300 raise CCPPError("Invalid {} variable property, '{}'".format(self.name, test_value))301 # End if302 return valid_val303###############################################################################304class Var(object):305 """ A class to hold a metadata variable306 >>> Var.get_prop('standard_name') #doctest: +ELLIPSIS307 <__main__.VariableProperty object at 0x...>308 >>> Var.get_prop('standard')309 >>> Var.get_prop('type').is_match('type')310 True311 >>> Var.get_prop('type').is_match('long_name')312 False313 >>> Var.get_prop('type').valid_value('character')314 'character'315 >>> Var.get_prop('type').valid_value('char')316 >>> Var.get_prop('long_name').valid_value('hi mom')317 'hi mom'318 >>> Var.get_prop('dimensions').valid_value('hi mom')319 >>> Var.get_prop('dimensions').valid_value(['Bob', 'Ray'])320 ['Bob', 'Ray']321 >>> Var.get_prop('active')322 '.true.'323 >>> Var.get_prop('active').valid_value('flag_for_aerosol_physics')324 'flag_for_aerosol_physics'325 >>> Var({'local_name' : 'foo', 'standard_name' : 'hi_mom', 'units' : 'm/s', 'dimensions' : '()', 'type' : 'real', 'intent' : 'in'}, ParseSource('vname', 'SCHEME', ParseContext())).get_prop_value('long_name')326 'Hi mom'327 >>> Var({'local_name' : 'foo', 'standard_name' : 'hi_mom', 'units' : 'm/s', 'dimensions' : '()', 'type' : 'real', 'intent' : 'in'}, ParseSource('vname', 'SCHEME', ParseContext())).get_prop_value('intent')328 'in'329 >>> Var({'local_name' : 'foo', 'standard_name' : 'hi_mom', 'units' : 'm/s', 'dimensions' : '()', 'ttype' : 'real', 'intent' : 'in'}, ParseSource('vname', 'SCHEME', ParseContext()))330 Traceback (most recent call last):331 ParseSyntaxError: Invalid metadata variable property, 'ttype', in <standard input>332 >>> Var({'local_name' : 'foo', 'standard_name' : 'hi_mom', 'dimensions' : '()', 'type' : 'real', 'intent' : 'in'}, ParseSource('vname', 'SCHEME', ParseContext()))333 Traceback (most recent call last):334 ParseSyntaxError: Required property, 'units', missing, in <standard input>335 >>> Var({'local_name' : 'foo', 'standard_name' : 'hi_mom', 'units' : 'm/s', 'dimensions' : '()', 'type' : 'real', 'intent' : 'inout', 'constant' : '.true.'}, ParseSource('vname', 'SCHEME', ParseContext())) #doctest: +IGNORE_EXCEPTION_DETAIL336 Traceback (most recent call last):337 ParseSyntaxError: foo is marked constant but is intent inout, at <standard input>:1338 >>> Var({'local_name' : 'foo', 'standard_name' : 'hi_mom', 'units' : 'm/s', 'dimensions' : '()', 'type' : 'real', 'intent' : 'ino'}, ParseSource('vname', 'SCHEME', ParseContext())) #doctest: +IGNORE_EXCEPTION_DETAIL339 Traceback (most recent call last):340 ParseSyntaxError: Invalid intent variable property, 'ino', at <standard input>:1341 """342 # __spec_props are for variables defined in a specification343 __spec_props = [VariableProperty('local_name', str,344 check_fn_in=check_fortran_ref),345 VariableProperty('standard_name', str,346 check_fn_in=check_cf_standard_name),347 VariableProperty('long_name', str, optional_in=True,348 default_fn_in=standard_name_to_long_name),349 VariableProperty('units', str),350 VariableProperty('dimensions', list,351 check_fn_in=check_dimensions),352 VariableProperty('type', str,353 check_fn_in=check_fortran_type),354 VariableProperty('kind', str,355 optional_in=True,356 default_fn_in=default_kind_val),357 VariableProperty('state_variable', bool,358 optional_in=True, default_in=False),359 VariableProperty('constant', bool,360 optional_in=True, default_in=False),361 VariableProperty('allocatable', bool,362 optional_in=True, default_in=False),363 VariableProperty('persistence', str, optional_in=True,364 valid_values_in=['timestep', 'run'],365 default_in='timestep'),366 VariableProperty('active', str, optional_in=True,367 default_in='.true.')]368 # __var_props contains properties which are not in __spec_props369 __var_props = [VariableProperty('optional', bool,370 optional_in=True, default_in=False),371 VariableProperty('intent', str,372 valid_values_in=['in', 'out', 'inout'])]373 __spec_propdict = {}374 __var_propdict = {}375 __required_spec_props = list()376 __required_var_props = list()377 for p in __spec_props:378 __spec_propdict[p.name] = p379 __var_propdict[p.name] = p380 if not p.optional:381 __required_spec_props.append(p.name)382 __required_var_props.append(p.name)383 # End if384 # End for385 for p in __var_props:386 __var_propdict[p.name] = p387 if not p.optional:388 __required_var_props.append(p.name)389 # End if390 # End for391 def __init__(self, prop_dict, source, invalid_ok=False, logger=None):392 """NB: invalid_ok=True is dangerous because it allows creation393 of a Var object with invalid properties.394 In order to prevent silent failures, invalid_ok requires a logger395 in order to take effect."""396 if source.type == 'SCHEME':397 required_props = Var.__required_var_props398 master_propdict = Var.__var_propdict399 else:400 required_props = Var.__required_spec_props401 master_propdict = Var.__spec_propdict402 # End if403 self._source = source404 # Grab a frozen copy of the context405 self._context = ParseContext(context=source.context)406 # First, check the input407 if 'ddt_type' in prop_dict:408 # Special case to bypass normal type rules409 if 'type' not in prop_dict:410 prop_dict['type'] = prop_dict['ddt_type']411 # End if412 if 'units' not in prop_dict:413 prop_dict['units'] = ""414 # End if415 prop_dict['kind'] = prop_dict['ddt_type']416 del prop_dict['ddt_type']417 # End if418 for key in prop_dict:419 if Var.get_prop(key) is None:420 raise ParseSyntaxError("Invalid metadata variable property, '{}'".format(key), context=self.context)421 # End if422 # End for423 # Make sure required properties are present424 for propname in required_props:425 if propname not in prop_dict:426 if invalid_ok and (logger is not None):427 ctx = context_string(self.context)428 logger.warning("Required property, '{}', missing{}".format(propname, ctx))429 else:430 raise ParseSyntaxError("Required property, '{}', missing".format(propname), context=self.context)431 # End if432 # End if433 # End for434 # Check for any mismatch435 if ('constant' in prop_dict) and ('intent' in prop_dict):436 if prop_dict['intent'].lower() != 'in':437 if invalid_ok and (logger is not None):438 ctx = context_string(self.context)439 logger.warning("{} is marked constant but is intent {}{}".format(prop_dict['local_name'], prop_dict['intent'], ctx))440 else:441 raise ParseSyntaxError("{} is marked constant but is intent {}".format(prop_dict['local_name'], prop_dict['intent']), context=self.context)442 # End if443 # End if444 # End if445 # Steal dict from caller446 self._prop_dict = prop_dict447 # Fill in default values for missing properties448 for propname in master_propdict:449 if (propname not in prop_dict) and master_propdict[propname].optional:450 self._prop_dict[propname] = master_propdict[propname].get_default_val(self._prop_dict, context=self.context)451 # End if452 # End for453 # Make sure all the variable values are valid454 try:455 for prop in self._prop_dict.keys():456 check = Var.get_prop(prop).valid_value(self._prop_dict[prop],457 error=True)458 # End for459 except CCPPError as cp:460 if invalid_ok and (logger is not None):461 ctx = context_string(self.context)462 logger.warning("{}: {}{}".format(self._prop_dict['local_name'], cp, ctx))463 else:464 raise ParseSyntaxError("{}: {}".format(self._prop_dict['local_name'], cp),465 context=self.context)466 # End if467 # End try468 def compatible(self, other, logger=None):469 # We accept character(len=*) as compatible with character(len=INTEGER_VALUE)470 stype = self.get_prop_value('type')471 skind = self.get_prop_value('kind')472 sunits = self.get_prop_value('units')473 srank= self.get_prop_value('tank')474 sstd_name = self.get_prop_value('standard_name')475 otype = other.get_prop_value('type')476 okind = other.get_prop_value('kind')477 ounits = other.get_prop_value('units')478 orank= other.get_prop_value('tank')479 ostd_name = other.get_prop_value('standard_name')480 if stype == 'character':481 kind_eq = ((skind == okind) or482 (skind == 'len=*' and okind.startswith('len=')) or483 (skind.startswith('len=') and okind == 'len=*'))484 else:485 kind_eq = skind == okind486 # End if487 if ((sstd_name == ostd_name) and kind_eq and488 (sunits == ounits) and (stype == otype) and (srank == orank)):489 return True490 elif logger is not None:491 if sstd_name != ostd_name:492 logger.info("standard_name: '{}' != '{}'".format(sstd_name, ostd_name))493 elif not kind_eq:494 logger.info("kind: '{}' != '{}'".format(skind, okind))495 elif sunits != ounits:496 logger.info("units: '{}' != '{}'".format(sunits, ounits))497 elif stype != otype:498 logger.info("type: '{}' != '{}'".format(stype, otype))499 elif srank != orank:500 logger.info("rank: '{}' != '{}'".format(srank, orank))501 else:502 logger.error('Why are these variables not compatible?')503 # End if504 return False505 else:506 return False507 # End if508 @classmethod509 def get_prop(cls, name, spec_type=None):510 if (spec_type is None) and (name in Var.__var_propdict):511 return Var.__var_propdict[name]512 elif (spec_type is not None) and (name in Var.__spec_propdict):513 return Var.__spec_propdict[name]514 else:515 return None516 def get_prop_value(self, name):517 if name in self._prop_dict:518 return self._prop_dict[name]519 else:520 return None521 @property522 def context(self):523 return self._context524 @property525 def source(self):526 return self._source527 @classmethod528 def loop_subst_dims(cls, dims):529 newdims = list()530 for dim in dims:531 # loop_subst_match swallows an entire dim string, even ranges532 ldim = VarDictionary.loop_subst_match(dim)533 if ldim is None:534 newdims.append(dim)535 else:536 newdims.append(ldim)537 # End if538 # End for539 return newdims540 def get_dimensions(self, loop_subst=False):541 "Return the variable's dimension string"542 dimval = self.get_prop_value('dimensions')543 dims = Var.get_prop('dimensions').valid_value(dimval)544 if loop_subst:545 newdims = loop_subst_dims(dims)546 else:547 newdims = dims548 # End if549 return newdims550 def write_def(self, outfile, indent, dict, allocatable=False, loop_subst=False):551 '''Write the definition line for the variable.'''552 vtype = self.get_prop_value('type')553 kind = self.get_prop_value('kind')554 name = self.get_prop_value('local_name')555 dims = self.get_dimensions(loop_subst=loop_subst)556 if (dims is not None) and (len(dims) > 0):557 if allocatable:558 dimstr = '(:' + ',:'*(len(dims) - 1) + ')'559 else:560 dimstr = '('561 comma = ''562 for dim in dims:563 # Only ranges or sizes go into declaration564 if VarDictionary.loop_var_match(dim):565 continue566 else:567 dstdnames = dim.split(':')568 dvars = [dict.find_variable(x) for x in dstdnames]569 if None in dvars:570 for dim in dstdnames:571 if dict.find_variable(dim) is None:572 raise CCPPError("No variable found for '{}'".format(dim))573 # End if574 # End for575 # End if576 dnames = [x.get_prop_value('local_name') for x in dvars]577 dimstr = dimstr + comma + ':'.join(dnames)578 comma = ', '579 # End if580 # End for581 dimstr = dimstr + ')'582 if dimstr == '()':583 dimstr = '' # It ends up being a scalar reference584 # End if585 # End if586 else:587 dimstr = ''588 # End if589 constant = self.get_prop_value('constant')590 intent = self.get_prop_value('intent')591 if constant and allocatable:592 raise CCPPError('Cannot create allocatable variable from constant, {}'.format(name))593 # End if594 if constant:595 intent_str = 'intent(in) '596 elif allocatable:597 if len(dimstr) > 0:598 intent_str = 'allocatable '599 else:600 intent_str = ' '*13601 # End if602 elif intent is not None:603 intent_str = 'intent({}){}'.format(intent, ' '*(5 - len(intent)))604 else:605 intent_str = ' '*13606 # End if607 if self.is_ddt():608 str = "type({kind}){cspc}{intent} :: {name}{dims}"609 cspc = ',' + ' '*(13 - len(kind))610 else:611 if (kind is not None) and (len(kind) > 0):612 str = "{type}({kind}){cspc}{intent} :: {name}{dims}"613 cspc = ',' + ' '*(17 - len(vtype) - len(kind))614 else:615 str = "{type}{cspc}{intent} :: {name}{dims}"616 cspc = ',' + ' '*(19 - len(vtype))617 # End if618 # End if619 outfile.write(str.format(type=vtype, kind=kind, intent=intent_str,620 name=name, dims=dimstr, cspc=cspc), indent)621 def is_ddt(self):622 '''Return True iff <self> is a DDT type.'''623 vtype = self.get_prop_value('type')624 return registered_fortran_ddt_name(vtype) is not None625 def host_arg_str(self, hvar, host_model, ddt):626 '''Create the proper statement of a piece of a host-model variable.627 If ddt is True, we can only have a single element selected628 '''629 hstr = hvar.get_prop_value('local_name')630 # Turn the dimensions string into a proper list and take the correct one631 hdims = hvar.get_dimensions()632 dimsep = ''633 # Does the local name have any extra indices?634 match = array_ref_re.match(hstr.strip())635 if match is not None:636 hstr = match.group(1)637 # Find real names for all the indices638 tokens = [x.strip() for x in match.group(2).strip().split(',')]639 for token in tokens:640 hsdim = self.find_host_model_var(token, host_model)641 dimstr = dimstr + dimsep + hsdim642 # End for643 # End if644 if len(hdims) > 0:645 dimstr = '('646 else:647 dimstr = ''648 # End if649 for hdim in hdims:650 if ddt and (':' in hdim):651 raise CCPPError("Invalid DDT dimension spec {}({})".format(hstr, hdimval))652 else:653 # Find the host model variable for each dim654 hsdims = self.find_host_model_var(hdim, host_model)655 dimstr = dimstr + dimsep + hsdims656 dimsep = ', '657 # End if658 # End for659 if len(hdims) > 0:660 dimstr = dimstr + ')'661 # End if662 return hstr + dimstr663 def print_debug(self):664 '''Print the data retrieval line for the variable.'''665 str='''Contents of {local_name} (* = mandatory for compatibility):666 standard_name = {standard_name} *667 long_name = {long_name}668 units = {units} *669 local_name = {local_name}670 type = {type} *671 dimensions = {dimensions} *672 kind = {kind} *673'''674 if 'intent' in self.__spec_propdict.keys():675 str += ' intent = {intent}\n'676 if 'optional' in self.__spec_propdict.keys():677 str += ' optional = {optional}\n'678 if self._context is not None:679 str += ' context = {}'.format(self._context)680 # End if681 return str.format(**self._prop_dict)682 def __str__(self):683 '''Print representation or string for Var objects'''684 return "<Var {standard_name}: {local_name}>".format(**self._prop_dict)685 def __repr__(self):686 '''Object representation for Var objects'''687 base = super(Var, self).__repr__()688 pind = base.find(' object ')689 if pind >= 0:690 pre = base[0:pind]691 else:692 pre = '<Var'693 # End if694 bind = base.find('at 0x')695 if bind >= 0:696 post = base[bind:]697 else:698 post = '>'699 # End if700 return '{} {}: {} {}'.format(pre, self._prop_dict['standard_name'], self._prop_dict['local_name'], post)701###############################################################################702class VarSpec(object):703 """A class to hold a standard_name description of a variable.704 A scalar variable is just a standard name while an array also705 contains a comma-separated list of dimension standard names in parentheses.706 """707 def __init__(self, var, loop_subst=False):708 self._name = var.get_prop_value('standard_name')709 self._dims = var.get_dimensions(loop_subst=loop_subst)710 if len(self._dims) == 0:711 self._dims = None712 # End if713 @property714 def name(self):715 return self._name716 def get_dimensions(self, loop_subst=False):717 if loop_subst:718 rdims = Var.loop_subst_dims(dims)719 else:720 rdims = dims721 # End if722 return rdims723 def __repr__(self):724 if self._dims is not None:725 return "{}({})".format(self._name, ', '.join(self._dims))726 else:727 return self._name728 # End if729###############################################################################730class VarDDT(Var):731 """A class to store a variable that is a component of a DDT (at any732 DDT nesting level).733 """734 def __init__(self, standard_name, var_ref_list, logger=None):735 self._standard_name = standard_name736 self._var_ref_list = list()737 for var in var_ref_list:738 self._var_ref_list.append(var)739 # End for740 self._vlen = len(self._var_ref_list)741 if logger is not None:742 lnames = [x.get_prop_value('local_name') for x in self._var_ref_list]743 logger.debug('Adding DDT field, {}, {}'.format(standard_name, lnames))744 # End if745 def compatible(self, other, logger=None):746 "Compare <other> to the intrinsic variable the end of the DDT chain"747 self._var_ref_list[-1].compare(other)748 def get_prop_value(self, name, index=0):749 "Return the indicated property value, defauling to the top-level DDT"750 if abs(index) >= self._vlen:751 raise ParseInternalError("VarDDT.get_prop_value index ({}) out of range".format(index))752 # End if753 return self._var_ref_list[index].get_prop_value(name)754 @property755 def context(self):756 "Return the context of the variable source (DDT root)"757 return self._var_ref_list[0].context758 @property759 def source(self):760 "Return the source of the variable source (DDT root)"761 return self._var_ref_list[0].source762 def get_dimensions(self, loop_subst=False, index=0):763 "Return the dimensions of the indicated var, defauling to the top-level DDT"764 if abs(index) >= self._vlen:765 raise ParseInternalError("VarDDT.get_prop_value index ({}) out of range".format(index))766 # End if767 return self._var_ref_list[index].get_dimensions(loop_subst)768 def write_def(self, outfile, indent, dict, allocatable=False, loop_subst=False):769 '''Write the definition line for the variable.'''770 pass771 def is_ddt(self):772 '''Return True iff <self> is a DDT type.'''773 return True774 def host_arg_str(self, hvar, host_model, ddt):775 '''Create the proper statement of a piece of a host-model variable.776 If ddt is True, we can only have a single element selected777 '''778 pass779 def print_debug(self):780 for var in self._var_ref_list:781 var.print(debug)782 # End for783 def __repr__(self):784 '''Print representation or string for VarDDT objects'''785 return "<{}>".format('%'.join([x.__repr__() for x in self._var_ref_list]))786###############################################################################787class VarDictionary(OrderedDict):788 """789 A class to store and cross-check variables from one or more metadata790 headers. The class also serves as a scoping construct so that a variable791 can be found in an innermost available scope.792 The dictionary is organized by standard_name. It is an error to try793 to add a variable if its standard name is already in the dictionary.794 Scoping is a tree of VarDictionary objects.795 >>> VarDictionary('foo')796 VarDictionary(foo)797 >>> VarDictionary('bar', variables={})798 VarDictionary(bar)799 >>> VarDictionary('baz', Var({'local_name' : 'foo', 'standard_name' : 'hi_mom', 'units' : 'm/s', 'dimensions' : '()', 'type' : 'real', 'intent' : 'in'}, ParseSource('vname', 'SCHEME', ParseContext()))) #doctest: +ELLIPSIS800 VarDictionary(baz, [('hi_mom', <__main__.Var hi_mom: foo at 0x...>)])801 >>> print("{}".format(VarDictionary('baz', Var({'local_name' : 'foo', 'standard_name' : 'hi_mom', 'units' : 'm/s', 'dimensions' : '()', 'type' : 'real', 'intent' : 'in'}, ParseSource('vname', 'SCHEME', ParseContext())))))802 VarDictionary(baz, ['hi_mom'])803 >>> VarDictionary('qux', [Var({'local_name' : 'foo', 'standard_name' : 'hi_mom', 'units' : 'm/s', 'dimensions' : '()', 'type' : 'real', 'intent' : 'in'}, ParseSource('vname', 'SCHEME', ParseContext()))]) #doctest: +ELLIPSIS804 VarDictionary(qux, [('hi_mom', <__main__.Var hi_mom: foo at 0x...>)])805 >>> VarDictionary('boo').add_variable(Var({'local_name' : 'foo', 'standard_name' : 'hi_mom', 'units' : 'm/s', 'dimensions' : '()', 'type' : 'real', 'intent' : 'in'}, ParseSource('vname', 'SCHEME', ParseContext())))806 >>> VarDictionary('who', variables=[Var({'local_name' : 'foo', 'standard_name' : 'hi_mom', 'units' : 'm/s', 'dimensions' : '()', 'type' : 'real', 'intent' : 'in'}, ParseSource('vname', 'SCHEME', ParseContext()))]).prop_list('local_name')807 ['foo']808 >>> VarDictionary('glitch', Var({'local_name' : 'foo', 'standard_name' : 'hi_mom', 'units' : 'm/s', 'dimensions' : '()', 'type' : 'real', 'intent' : 'in'}, ParseSource('vname', 'SCHEME', ParseContext()))).add_variable(Var({'local_name' : 'bar', 'standard_name' : 'hi_mom', 'units' : 'm/s', 'dimensions' : '()', 'type' : 'real', 'intent' : 'in'}, ParseSource('vname2', 'DDT', ParseContext()))) #doctest: +IGNORE_EXCEPTION_DETAIL809 Traceback (most recent call last):810 ParseSyntaxError: Invalid Duplicate standard name, 'hi_mom', at <standard input>:811 """812 # Loop variables813 __ccpp_loop_vars__ = ['horizontal_loop_begin', 'horizontal_loop_end',814 'thread_block_number', 'horizontal_loop_extent']815 # Loop substitutions816 __ccpp_loop_subst__ = {'horizontal_loop_extent' :817 ('horizontal_loop_begin', 'horizontal_loop_end'),818 'thread_block_begin:thread_block_end' :819 'thread_block_number'}820 # Dimension substitutions821 __ccpp_dim_subst__ = {'horizontal_loop_extent' : 'horizontal_dimension'}822 # Variable representing the constant integer, 1823 __var_one = Var({'local_name' : 'ccpp_one', 'constant' : 'True',824 'standard_name' : 'ccpp_constant_one',825 'units' : '1', 'dimensions' : '()', 'type' : 'integer'},826 ParseSource('VarDictionary', 'REGISTRY', ParseContext()))827 def __init__(self, name, variables=None, parent_dict=None, logger=None):828 "Unlike dict, VarDictionary only takes a Var or Var list"829 super(VarDictionary, self).__init__()830 self._name = name831 self._logger = logger832 self._parent_dict = parent_dict833 if parent_dict is not None:834 parent_dict.add_sub_scope(self)835 # End if836 self._sub_dicts = list()837 if isinstance(variables, Var):838 self.add_variable(variables)839 elif isinstance(variables, list):840 for var in variables:841 self.add_variable(var)842 # End for843 elif isinstance(variables, VarDictionary):844 for stdname in variables.keys():845 self[stdname] = variables[stdname]846 # End for847 elif isinstance(variables, dict):848 # variables will not be in 'order', but we accept them anyway849 for stdname in variables.keys():850 self[stdname] = variables[stdname]851 # End for852 elif variables is not None:853 raise ParseInternalError('Illegal type for variables, {} in {}'.format(type(variables), self.name))854 # End if855 @property856 def name(self):857 return self._name858 @property859 def parent(self):860 return self._parent_dict861 def include_var_in_list(self, var, std_vars, loop_vars, consts):862 '''Return True iff <var> is of a type allowed by the logicals,863 <std_vars> (not constants or loop_vars),864 <loop_vars> a variable ending in "_extent", "_begin", "_end", or865 <consts> a variable with the "constant" property.866 '''867 const_val = var.get_prop_value('constant')868 const_var = Var.get_prop('constant').valid_value(const_val)869 include_var = consts and const_var870 if not include_var:871 standard_name = var.get_prop_value('standard_name')872 loop_var = VarDictionary.loop_var_match(standard_name)873 include_var = loop_var and loop_vars874 if not include_var:875 std_var = not (loop_var or const_var)876 include_var = std_vars and std_var877 # End if878 # End if879 return include_var880 def variable_list(self, recursive=False,881 std_vars=True, loop_vars=True, consts=True):882 "Return a list of all variables"883 if recursive and (self._parent_dict is not None):884 vlist = self._parent_dict.variable_list(recursive=recursive,885 std_vars=std_vars,886 loop_vars=loop_vars,887 consts=consts)888 else:889 vlist = list()890 # End if891 for sn in self.keys():892 var = self[sn]893 if self.include_var_in_list(var, std_vars=std_vars,894 loop_vars=loop_vars, consts=consts):895 vlist.append(var)896 # End if897 # End for898 return vlist899 def add_variable(self, newvar, exists_ok=False):900 """Add a variable if it does not conflict with existing entries"""901 standard_name = newvar.get_prop_value('standard_name')902 if (standard_name in self) and (not exists_ok):903 # We already have a matching variable, error!904 if self._logger is not None:905 self._logger.error("Attempt to add duplicate variable, {} from {}".format(standard_name, newvar.source.name))906 # End if907 raise ParseSyntaxError("Duplicate standard name in {}".format(self.name),908 token=standard_name, context=newvar._context)909 # End if910 cvar = self.find_variable(standard_name)911 if (cvar is not None) and (not cvar.compatible(newvar, self._logger)):912 if self._logger is not None:913 self._logger.error("Attempt to add incompatible variable, {} from {}".format(standard_name, newvar.source.name))914 # End if915 errstr = "standard name, incompatible with {}"916 raise ParseSyntaxError(errstr.format(cvar.context),917 token=standard_name,918 context=newvar.source.context)919 # End if920 # If we make it to here without an exception, add the variable921 self[standard_name] = newvar922 def remove_variable(self, standard_name):923 """Remove <standard_name> from the dictionary.924 Ignore if <standard_name> is not in dict925 """926 if standard_name in self:927 del self[standard_name]928 # End if929 def find_variable(self, standard_name, any_scope=True, loop_subst=False):930 """Return the variable matching <standard_name> or None931 If any_scope is True, search parent scopes if not in current scope.932 """933 if standard_name in self:934 var = self[standard_name]935 elif any_scope and (self._parent_dict is not None):936 var = self._parent_dict.find_variable(standard_name, any_scope)937 else:938 var = None939 # End if940 if (var is None) and loop_subst:941 var = self.find_loop_subst(standard_name, any_scope=any_scope)942 # End if943 return var944 def add_sub_scope(self, sub_dict):945 'Add a child dictionary to enable traversal'946 self._sub_dicts.append(sub_dict)947 def prop_list(self, prop_name, std_vars=True, loop_vars=True, consts=True):948 '''Return a list of the <prop_name> property for each variable.949 std_vars are variables which are neither constants nor loop variables.950 '''951 plist = list()952 for standard_name in self.keys():953 var = self.find_variable(standard_name, any_scope=False, loop_subst=False)954 if self.include_var_in_list(var, std_vars=std_vars, loop_vars=loop_vars, consts=consts):955 plist.append(self[standard_name].get_prop_value(prop_name))956 # End if957 # End for958 return plist959 def declare_variables(self, outfile, indent,960 std_vars=True, loop_vars=True, consts=True):961 "Write out the declarations for this dictionary's variables"962 for standard_name in self.keys():963 var = self.find_variable(standard_name, any_scope=False, loop_subst=False)964 if self.include_var_in_list(var, std_vars=std_vars, loop_vars=loop_vars, consts=consts):965 self[standard_name].write_def(outfile, indent, self)966 # End if967 # End for968 def merge(self, other_dict):969 "Add new entries from <other_dict>"970 for ovar in other_dict.variable_list():971 self.add_variable(ovar)972 # End for973 def __str__(self):974 return "VarDictionary({}, {})".format(self.name, self.keys())975 def __repr__(self):976 srepr = super(VarDictionary, self).__repr__()977 vstart = len("VarDictionary") + 1978 if len(srepr) > vstart + 1:979 comma = ", "980 else:981 comma = ""982 # End if983 return "VarDictionary({}{}{}".format(self.name, comma, srepr[vstart:])984 def __del__(self):985 try:986 for key in self.keys():987 del self[key]988 # End for989 except Exception as e:990 pass # python does not guarantee object state during finalization991 # End try992 @classmethod993 def loop_var_match(cls, standard_name):994 'Return True iff <standard_name> is a loop variable'995 return standard_name in cls.__ccpp_loop_vars__996 @classmethod997 def loop_subst_match(cls, standard_name):998 'Return a loop substitution match, if any, for <standard_name>'999 if standard_name in cls.__ccpp_loop_subst__:1000 return cls.__ccpp_loop_subst__[standard_name]1001 else:1002 return None1003 # End if1004 def find_loop_subst(self, standard_name, any_scope=True, context=None):1005 """If <standard_name> is of the form <standard_name>_extent and that1006 variable is not in the dictionary, substitute a tuple of variables,1007 (<standard_name>_begin, <standard_name>_end), if those variables are1008 in the dictionary.1009 If <standard_name>_extent *is* present, return that variable as a1010 range, (__var_one, <standard_name>_extent)1011 In other cases, return None1012 """1013 loop_var = VarDictionary.loop_subst_match(standard_name)1014 logger_str = None1015 if loop_var is not None:1016 # Let us see if we can fix a loop variable1017 dict_var = self.find_variable(standard_name,1018 any_scope=any_scope, loop_subst=False)1019 if dict_var is not None:1020 my_var = (VarDictionary.__var_one, dict_var)1021 if self._logger is not None:1022 logger_str = "loop_subst: found {}{}".format(standard_name, context_string(context))1023 # End if1024 else:1025 my_vars = [self.find_variable(x) for x in loop_var]1026 if None not in my_vars:1027 my_var = tuple(my_vars)1028 if self._logger is not None:1029 names = [x.get_prop_value('local_name') for x in my_vars]1030 logger_str = "loop_subst: {} ==> (){}".format(standard_name, ', '.join(names), context_string(context))1031 # End if1032 else:1033 if self._logger is not None:1034 logger_str = "loop_subst: {} ==> ({}, {}) FAILED{}".format(standard_name, beg_name, end_name, context_string(context))1035 # End if1036 my_var = None1037 # End if1038 # End if1039 else:1040 if self._logger is not None:1041 logger_str = "loop_subst: {} is not a loop variable{}".format(standard_name, context_string(context))1042 # End if1043 my_var = None1044 # End if1045 if logger_str is not None:1046 self._logger.debug(logger_str)1047 # End if1048 return my_var1049 def find_dimension_subst(self, standard_name, any_scope=True, context=None):1050 """If <standard_name> is of the form <standard_name>_loop_extent1051 attempt to find a variable of the form <standard_name>_dimension1052 and return that. If such a variable is not found, raise an exception.1053 If <standard_name> is not of the form <standard_name>_extent, return1054 None.1055 """1056 loop_var = standard_name in VarDictionary.__ccpp_dim_subst__1057 logger_str = None1058 if loop_var:1059 # Let us see if we can replace the variable1060 dim_name = VarDictionary.__ccpp_dim_subst__[standard_name]1061 my_var = self.find_variable(dim_name, any_scope=any_scope)1062 if my_var is None:1063 raise CCPPError("Dimension variable, {} not found{}".format(dim_name, context_string(context)))1064 # End if1065 else:1066 my_var = None1067 # End if1068 return my_var1069###############################################################################1070if __name__ == "__main__":1071 import doctest...

Full Screen

Full Screen

Automation Testing Tutorials

Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.

LambdaTest Learning Hubs:

YouTube

You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.

Run pandera automation tests on LambdaTest cloud grid

Perform automation testing on 3000+ real desktop and mobile devices online.

Try LambdaTest Now !!

Get 100 minutes of automation test minutes FREE!!

Next-Gen App & Browser Testing Cloud

Was this article helpful?

Helpful

NotHelpful