def double_or_blank(card, n, fieldname, default=None): """ :param card: BDF card as a list :param n: field number :param fieldname: name of field :param default: the default value for the field (default=None) """ assert isinstance(card, BDFCard), type(card) assert isinstance(n, int), type(n) assert is_string(fieldname), type(fieldname) #try: svalue = card.field(n) #except IndexError: #return default if isinstance(svalue, float): return svalue elif isinstance(svalue, int): Type = getType(svalue) raise SyntaxError('%s = %r (field #%s) on card must be a float or blank (not %s).\ncard=%s' % (fieldname, svalue, n, Type, card) ) elif is_string(svalue): svalue = svalue.strip() if not svalue: return default try: return double(card, n, fieldname) except: Type = getType(svalue) raise SyntaxError('%s = %r (field #%s) on card must be a float or blank (not %s).\ncard=%s' % (fieldname, svalue, n, Type, card) ) return default
def string(card, n, fieldname): """ :param card: BDF card as a list :param n: field number :param fieldname: name of field """ assert isinstance(card, BDFCard), type(card) assert isinstance(n, int), type(n) assert is_string(fieldname), type(fieldname) svalue = card.field(n) if is_string(svalue): svalue = svalue.strip() else: Type = getType(svalue) raise SyntaxError('%s = %r (field #%s) on card must be an string (not %s).\ncard=%s' % (fieldname, svalue, n, Type, card) ) if svalue.isdigit() or '.' in svalue: value = integer_or_double(card, n, fieldname) Type = getType(value) raise SyntaxError('%s = %r (field #%s) on card must be an string with a character (not %s).\ncard=%s' % (fieldname, value, n, Type, card) ) if svalue: # string return str(svalue) Type = getType(svalue) msg = '%s = %r (field #%s) on card must be an string (not %s).\ncard=%s' % (fieldname, svalue, n, Type, card) raise SyntaxError(msg)
def double_or_string(card, n, fieldname): """ :param card: BDF card as a list :param n: field number :param fieldname: name of field """ assert isinstance(card, BDFCard), type(card) assert isinstance(n, int), type(n) assert is_string(fieldname), type(fieldname) #try: svalue = card.field(n) #except IndexError: #raise SyntaxError('%s (field #%s) on card must be a float or string (not blank).\ncard=%s' % (fieldname, n, card) ) if isinstance(svalue, float): return svalue elif svalue is None or isinstance(svalue, int): Type = getType(svalue) raise SyntaxError('%s = %r (field #%s) on card must be an float or string (not %s).\ncard=%s' % (fieldname, svalue, n, Type, card) ) elif is_string(svalue): svalue = svalue.strip() if '.' in svalue: # float try: return double(card, n, fieldname) except: Type = getType(svalue) raise SyntaxError('%s = %r (field #%s) on card must be an float or string (not %s).\ncard=%s' % (fieldname, svalue, n, Type, card) ) elif svalue.isdigit(): # fail pass elif svalue: # string return svalue Type = getType(svalue) raise SyntaxError('%s = %r (field #%s) on card must be an float or string (not %s).\ncard=%s' % (fieldname, svalue, n, Type, card) )
def string_or_blank(card, n, fieldname, default=None): """ :param card: BDF card as a list :param n: field number :param fieldname: name of field :param default: the default value for the field (default=None) """ assert isinstance(card, BDFCard), type(card) assert isinstance(n, int), type(n) assert is_string(fieldname), type(fieldname) svalue = card.field(n) if svalue is None: return default elif is_string(svalue): svalue = svalue.strip() else: Type = getType(svalue) raise SyntaxError('%s = %r (field #%s) on card must be an string (not %s).\ncard=%s' % (fieldname, svalue, n, Type, card) ) svalue = svalue.strip() if svalue.isdigit() or '.' in svalue: Type = getType(svalue) raise SyntaxError('%s = %r (field #%s) on card must be an string or blank (not %s).\ncard=%s' % (fieldname, svalue, n, Type, card) ) if svalue: # string return str(svalue) return default
def integer_or_blank(card, n, fieldname, default=None): """ :param card: BDF card as a list :param n: field number :param fieldname: name of field :param default: the default value for the field (default=None) """ assert isinstance(card, BDFCard), type(card) assert isinstance(n, int), type(n) assert is_string(fieldname), type(fieldname) #try: svalue = card.field(n) #except IndexError: # return default if isinstance(svalue, int): return svalue elif svalue is None: return default elif is_string(svalue): if len(svalue) == 0: return default elif '.' in svalue: Type = getType(svalue) raise SyntaxError('%s = %r (field #%s) on card must be an integer or blank (not %s).\ncard=%s' % (fieldname, svalue, n, Type, card) ) try: return int(svalue) except: Type = getType(svalue) raise SyntaxError('%s = %r (field #%s) on card must be an integer or blank (not %s).\ncard=%s' % (fieldname, svalue, n, Type, card) ) Type = getType(svalue) raise SyntaxError('%s = %r (field #%s) on card must be an integer (not %s).\ncard=%s' % (fieldname, svalue, n, Type, card) )
def integer_or_double(card, n, fieldname): """ :param card: BDF card as a list :param n: field number :param fieldname: name of field :returns value: the value with the proper type :raises SyntaxError: if there's an invalid type """ assert isinstance(card, BDFCard), type(card) assert isinstance(n, int), type(n) assert is_string(fieldname), type(fieldname) #try: svalue = card.field(n) #except IndexError: #raise SyntaxError('%s (field #%s) on card must be an integer or float.\ncard=%s' % (fieldname, n, card) ) if isinstance(svalue, int) or isinstance(svalue, float): return svalue elif svalue is None: raise SyntaxError('%s (field #%s) on card must be an integer or float (not blank).\ncard=%s' % (fieldname, n, card) ) if '.' in svalue: # float/exponent try: value = double(card, n, fieldname) except ValueError: Type = getType(svalue) raise SyntaxError('%s = %r (field #%s) on card must be a integer or a float (not %s).\ncard=%s' % (fieldname, svalue, n, Type, card) ) else: # int try: value = int(svalue) except: Type = getType(svalue) raise SyntaxError('%s = %r (field #%s) on card must be an integer or a float (not %s).\ncard=%s' % (fieldname, svalue, n, Type, card) ) return value
def integer_or_string(card, n, fieldname): """ :param card: BDF card as a list :param n: field number :param fieldname: name of field :param default: the default value for the field (default=None) """ assert isinstance(card, BDFCard), type(card) assert isinstance(n, int), type(n) assert is_string(fieldname), type(fieldname) #try: svalue = card.field(n) #except IndexError: #raise SyntaxError('%s (field #%s) on card must be an integer or string.\ncard=%s' % (fieldname, n, card) ) if isinstance(svalue, int): return svalue elif isinstance(svalue, float): Type = getType(svalue) raise SyntaxError('%s = %r (field #%s) on card must be an integer or string (not %s).\ncard=%s' % (fieldname, svalue, n, Type, card) ) elif svalue is None: Type = getType(svalue) raise SyntaxError('%s = %r (field #%s) on card must be an integer or string (not %s).\ncard=%s' % (fieldname, svalue, n, Type, card) ) if svalue.isdigit(): # int try: value = int(svalue) except ValueError: Type = getType(svalue) raise SyntaxError('%s = %r (field #%s) on card must be an integer or string (not %s).\ncard=%s' % (fieldname, svalue, n, Type, card) ) elif isinstance(svalue, float): Type = getType(svalue) raise SyntaxError('%s = %r (field #%s) on card must be an integer or string (not %s).\ncard=%s' % (fieldname, svalue, n, Type, card) ) else: # string return str(svalue) return value
def integer_double_or_string(card, n, fieldname): """ :param card: BDF card as a list :param n: field number :param fieldname: name of field """ assert isinstance(card, BDFCard), type(card) assert isinstance(n, int), type(n) assert is_string(fieldname), type(fieldname) #try: svalue = card.field(n) #except IndexError: #raise SyntaxError('%s (field #%s) on card must be an integer, float, or string.\ncard=%s' % (fieldname, n, card) ) if isinstance(svalue, int) or isinstance(svalue, float): return svalue svalue = str(svalue.strip()) if svalue: # integer/float/string if '.' in svalue: # float value = double(card, n, fieldname) elif svalue.isdigit(): # int try: value = int(svalue) except ValueError: raise SyntaxError('%s = %r (field #%s) on card must be an integer, float, or string (not blank).\ncard=%s' % (fieldname, svalue, n, card) ) else: value = svalue return value Type = getType(svalue) raise SyntaxError('%s = %r (field #%s) on card must be an integer, float, or string (not %s).\ncard=%s' % (fieldname, svalue, n, Type, card) )
def field(card, n, fieldname): """ :param card: BDF card as a list :param n: field number :param fieldname: name of field """ assert isinstance(card, BDFCard), type(card) assert isinstance(n, int), type(n) assert is_string(fieldname), type(fieldname) return integer_double_string_or_blank(card, n, fieldname, default=None)
def _add_data(self, key, value, options, param_type): key = update_param_name(key) #print("adding isubcase=%s key=|%s| value=|%s| options=|%s| " # "param_type=%s" %(self.id, key, value, options, param_type)) if is_string(value) and value.isdigit(): value = int(value) (key, value, options) = self._simplify_data(key, value, options, param_type) self.params[key] = [value, options, param_type]
def double(card, n, fieldname): """ :param card: BDF card as a list :param n: field number :param fieldname: name of field """ assert isinstance(card, BDFCard), type(card) assert isinstance(n, int), type(n) assert is_string(fieldname), type(fieldname) try: svalue = card.field(n) except IndexError: raise SyntaxError('%s (field #%s) on card must be a float.\ncard=%s' % (fieldname, n, card) ) if isinstance(svalue, float): return svalue elif isinstance(svalue, int): Type = getType(svalue) raise SyntaxError('%s = %r (field #%s) on card must be a float (not %s).\ncard=%s' % (fieldname, svalue, n, Type, card) ) elif svalue is None or len(svalue) == 0: ## None Type = getType(svalue) raise SyntaxError('%s = %r (field #%s) on card must be a float (not %s).\ncard=%s' % (fieldname, svalue, n, Type, card) ) if svalue.isdigit(): # if only int Type = getType(int(svalue)) raise SyntaxError('%s = %r (field #%s) on card must be a float (not %s).\ncard=%s' % (fieldname, svalue, n, Type, card) ) #svalue = svalue.strip() try: # 1.0, 1.0E+3, 1.0E-3 value = float(svalue) except TypeError: Type = getType(svalue) raise SyntaxError('%s = %r (field #%s) on card must be a float (not %s).\ncard=%s' % (fieldname, svalue, n, Type, card) ) except ValueError: # 1D+3, 1D-3, 1-3 try: svalue = svalue.upper() if 'D' in svalue: # 1.0D+3, 1.0D-3 svalue2 = svalue.replace('D','E') return float(svalue2) # 1.0+3, 1.0-3 sign = '' if '+' in svalue[0] or '-' in svalue[0]: svalue = svalue[1:] sign = svalue[0] if '+' in svalue: svalue = sign + svalue.replace('+','E+') elif '-' in svalue: svalue = sign + svalue.replace('-','E-') value = float(svalue) except ValueError: Type = getType(svalue) raise SyntaxError('%s = %r (field #%s) on card must be a float (not %s).\ncard=%s' % (fieldname, svalue, n, Type, card) ) return value
def fields_or_blank(f, card, fieldname, i, j=None, defaults=None): assert isinstance(card, BDFCard), type(card) assert is_string(fieldname), type(fieldname) fs = [] if j is None: j = len(card) assert j - i == len(defaults), 'j=%s i=%s j-i=%s len(defaults)=%s\ncard=%s' % (j,i,j-i, len(defaults), card) for ii, default in enumerate(defaults): fs.append( f(card, ii + i, fieldname + str(ii), default) ) return fs
def blank(card, n, fieldname, default=None): """ :param card: BDF card as a list :param n: field number :param fieldname: name of field :param default: the default value for the field (default=None) """ assert isinstance(card, BDFCard), type(card) assert isinstance(n, int), type(n) assert is_string(fieldname), type(fieldname) svalue = card.field(n) if svalue is None: return default if is_string(svalue): svalue = svalue.strip() if len(svalue) == 0: return default Type = getType(svalue) raise SyntaxError('%s = %r (field #%s) on card must be blank (not %s).\ncard=%s' % (fieldname, svalue, n, Type, card) )
def is_same(value1, value2): """ Checks to see if 2 values are the same .. note:: this method is used by almost every card when printing """ if is_string(value1) or value1 is None: return True if value1 == value2 else False return True if (value1 == value2 or type(value1) == type(value2) and not isinf(value1) and allclose(value1, value2)) else False
def fields(f, card, fieldname, i, j=None): """ .. todo:: improve fieldname """ assert isinstance(card, BDFCard), type(card) assert is_string(fieldname), type(fieldname) fs = [] if j is None: j = len(card) for ii in range(i,j): fs.append( f(card, ii, fieldname) ) return fs
def double_string_or_blank(card, n, fieldname, default=None): """ :param card: BDF card as a list :param n: field number :param fieldname: name of field :param default: the default value for the field (default=None) :returns value: a double, string, or default value :raises SyntaxError: if there is an invalid type """ assert isinstance(card, BDFCard), type(card) assert isinstance(n, int), type(n) assert is_string(fieldname), type(fieldname) #try: svalue = card.field(n) #except IndexError: #return default if isinstance(svalue, float): return svalue elif svalue is None: return default elif is_string(svalue): svalue = svalue.strip() elif isinstance(svalue, int): Type = getType(svalue) raise SyntaxError('%s = %r (field #%s) on card must be an float, string, or blank (not %s).\ncard=%s' % (fieldname, svalue, n, Type, card) ) if '.' in svalue: try: return double(card, n, fieldname) except: Type = getType(svalue) msg = '%s = %r (field #%s) on card must be a float, string or blank (not %s).\ncard=%s' % (fieldname, svalue, n, Type, card) raise SyntaxError(msg) elif svalue.isdigit(): Type = getType(svalue) raise SyntaxError('%s = %r (field #%s) on card must be a float, string or blank (not %s).\ncard=%s' % (fieldname, svalue, n, Type, card) ) elif svalue == '': return default return svalue
def components(card, n, fieldname): """ :param card: BDF card as a list :param n: field number :param fieldname: name of field """ assert isinstance(card, BDFCard), type(card) assert isinstance(n, int), type(n) assert is_string(fieldname), type(fieldname) svalue = card.field(n) if isinstance(svalue, int): pass elif svalue is None or '.' in svalue: Type = getType(svalue) msg = '%s = %r (field #%s) on card must be an integer (not %s).\ncard=%s' % (fieldname, svalue, n, Type, card) raise SyntaxError(msg) try: value = int(svalue) except: Type = getType(svalue) msg = '%s = %r (field #%s) on card must be an integer (not %s).\ncard=%s' % (fieldname, svalue, n, Type, card) raise SyntaxError(msg) if value > 0 and is_string(svalue): if '0' in svalue: value2 = str(svalue).replace('0', '') msg = '%s = %r (field #%s) on card must contain 0 or %s (not both).\ncard=%s' % (fieldname, svalue, n, value2, card) raise SyntaxError(msg) svalue2 = str(value) svalue3 = ''.join(sorted(svalue2)) for i,v in enumerate(svalue3): if v not in '0123456': msg = '%s = %r (field #%s) on card contains an invalid component %r.\ncard=%s' % (fieldname, svalue, n, v, card) raise SyntaxError(msg) if v in svalue3[i + 1:]: msg = '%s = %r (field #%s) on card must not contain duplicate entries.\ncard=%s' % (fieldname, svalue, n, card) raise SyntaxError(msg) return svalue3
def __repr__(self): if self.nonlinear_factor is not None: return self.__reprTransient__() msg = '---BAR STRESS---\n' msg += '%-6s %6s ' % ('EID', 'eType') headers = ['s1', 's2', 's3', 's4', 'Axial', 'sMax', 'sMin'] for header in headers: msg += '%8s ' % header msg += '\n' for eid, S1s in sorted(self.s1.items()): eType = self.eType[eid] axial = self.axial[eid] #MSt = self.MSt[eid] #MSc = self.MSc[eid] s1 = self.s1[eid] s2 = self.s2[eid] s3 = self.s3[eid] s4 = self.s4[eid] smax = self.smax[eid] smin = self.smin[eid] msg += '%-6i %6s ' % (eid, eType) vals = [s1[0], s2[0], s3[0], s4[0], axial, smax[0], smin[0]] for val in vals: if abs(val) < 1e-6: msg += '%8s ' % '0' else: msg += '%8i ' % val msg += '\n' msg += '%s ' % (' ' * 13) vals = [s1[1], s2[1], s3[1], s4[1], '', smax[1], smin[1]] for val in vals: if is_string(val): msg += '%8s ' % val elif abs(val) < 1e-6: msg += '%8s ' % '0' else: msg += '%8i ' % val msg += '\n' #msg += "eid=%-4s eType=%s s1=%-4i s2=%-4i s3=%-4i s4=%-4i axial=-%5i smax=%-5i smax=%-4i\n" %(eid,eType,s1[0],s2[0],s3[0],s4[0],axial, smax[0],smin[0]) #msg += "%s s1=%-4i s2=%-4i s3=%-4i s4=%-4i %s smax=%-5i smax=%-4i\n" %(' '*4, s1[1],s2[1],s3[1],s4[1],' ',smax[1],smin[1]) return msg
def __repr__(self): if self.isTransient: return self.__reprTransient__() msg = '---BAR STRAIN---\n' msg += '%-8s %6s ' % ('EID', 'eType') headers = ['e1', 'e2', 'e3', 'e4', 'Axial', 'eMax', 'eMin'] for header in headers: msg += '%10s ' % header msg += '\n' for eid, E1s in sorted(self.e1.items()): eType = self.eType[eid] axial = self.axial[eid] #MSt = self.MS_tension[eid] #MSc = self.MS_compression[eid] e1 = self.e1[eid] e2 = self.e2[eid] e3 = self.e3[eid] e4 = self.e4[eid] emax = self.emax[eid] emin = self.emin[eid] msg += '%-8i %6s ' % (eid, eType) vals = [e1[0], e2[0], e3[0], e4[0], axial, emax[0], emin[0]] for val in vals: if abs(val) < 1e-6: msg += '%10s ' % '0' else: msg += '%10.3g ' % val msg += '\n' msg += '%s ' % (' ' * 17) vals = [e1[1], e2[1], e3[1], e4[1], '', emax[1], emin[1]] for val in vals: if is_string(val): msg += '%10s ' % val elif abs(val) < 1e-6: msg += '%10s ' % '0' else: msg += '%10.3g ' % val msg += '\n' #msg += "eid=%-4s eType=%s s1=%-4i s2=%-4i s3=%-4i s4=%-4i axial=-%5i smax=%-5i smax=%-4i\n" %(eid,eType,s1[0],s2[0],s3[0],s4[0],axial, smax[0],smin[0]) #msg += "%s s1=%-4i s2=%-4i s3=%-4i s4=%-4i %s smax=%-5i smax=%-4i\n" %(' '*4, s1[1],s2[1],s3[1],s4[1],' ',smax[1],smin[1]) return msg
def getType(value): """ Get the type of the input value in a form that is clear. :param value: the value to get the type of """ #print('Type value=%s' % value) try: value = interpret_value(value) except: pass if value is None: Type = 'blank' elif isinstance(value, int): Type = 'an integer' elif isinstance(value, float): Type = 'a double' elif is_string(value): Type = 'a string' else: Type = str(type(value)) return Type
def components_or_blank(card, n, fieldname, default=None): """ :param card: BDF card as a list :param n: field number :param fieldname: name of field :param default: the default value for the field (default=None) """ assert isinstance(card, BDFCard), type(card) assert isinstance(n, int), type(n) assert is_string(fieldname), type(fieldname) svalue = card.field(n) if svalue is None: return default elif isinstance(svalue, int): svalue = str(svalue) else: svalue = svalue.strip() if svalue: return components(card, n, fieldname) else: return default
def _cleanup_xy(self, xy, isData=False): """ Removes the **ENDT** field. :param xy: the xy data as a table with alternating x, y entries :param isData: did this come from the OP2/BDF (True -> OP2) """ xy2 = [] # remove extra ENDTs if 1: # hardcoded b/c ENDT has been removed return xy foundENDT = False for value in xy: if is_string(value) and 'ENDT' in value.upper(): foundENDT = True else: xy2.append(value) if not isData: assert foundENDT == True, xy return xy2
def wipe_empty_fields(card): """ Removes an trailing Nones from the card. Also converts empty strings to None. :param card: the fields on the card as a list :returns shortCard: the card with no trailing blank fields """ cardB = [] for field in card: if is_string(field): field = field.strip() if field == '': field = None cardB.append(field) i = 0 iMax = 0 while i < len(card): if cardB[i] is not None: iMax = i i += 1 return cardB[:iMax + 1]
def integer(card, n, fieldname): """ :param card: BDF card as a list :param n: field number :param fieldname: name of field """ assert isinstance(card, BDFCard), type(card) assert isinstance(n, int), type(n) assert is_string(fieldname), type(fieldname) try: svalue = card.field(n) except IndexError: raise SyntaxError('%s (field #%s) on card must be an integer.' % (fieldname, n) ) if isinstance(svalue, float): Type = getType(svalue) raise SyntaxError('%s = %r (field #%s) on card must be an integer (not %s).\ncard=%s' % (fieldname, svalue, n, Type, card) ) try: return int(svalue) except: Type = getType(svalue) raise SyntaxError('%s = %r (field #%s) on card must be an integer (not %s).\ncard=%s' % (fieldname, svalue, n, Type, card) )
def initOfftBit(self, card): field8 = integer_double_string_or_blank(card, 8, 'field8') if isinstance(field8, float): self.isOfft = False self.offt = None self.bit = field8 elif field8 is None: self.isOfft = True self.offt = 'GGG' # default self.bit = None elif is_string(field8): self.isOfft = True self.bit = None self.offt = field8 #print("self.offt = ", self.offt) msg = 'invalid offt parameter of CBEAM...offt=%s' % self.offt assert self.offt[0] in ['G', 'B', 'O', 'E'], msg assert self.offt[1] in ['G', 'B', 'O', 'E'], msg assert self.offt[2] in ['G', 'B', 'O', 'E'], msg else: msg = ('field8 on %s card is not a string(offt) or bit ' '(float)...field8=%s\n' % (self.type, field8)) raise RuntimeError("Card Instantiation: %s" % msg)
def __init__(self, card=None, data=None, comment=''): LineElement.__init__(self, card, data) if comment: self._comment = comment if card: self.eid = integer(card, 1, 'eid') self.pid = integer_or_blank(card, 2, 'pid', self.eid) self.ga = integer(card, 3, 'ga') self.gb = integer(card, 4, 'gb') self.initX_G0(card) self.offt = string_or_blank(card, 8, 'offt', 'GGG') #print 'self.offt = |%s|' %(self.offt) self.pa = integer_or_blank(card, 9, 'pa', 0) self.pb = integer_or_blank(card, 10, 'pb', 0) self.w1a = double_or_blank(card, 11, 'w1a', 0.0) self.w2a = double_or_blank(card, 12, 'w2a', 0.0) self.w3a = double_or_blank(card, 13, 'w3a', 0.0) self.w1b = double_or_blank(card, 14, 'w1b', 0.0) self.w2b = double_or_blank(card, 15, 'w2b', 0.0) self.w3b = double_or_blank(card, 16, 'w3b', 0.0) assert len(card) <= 17, 'len(CBAR card) = %i' % len(card) else: #: .. todo:: verify #data = [[eid,pid,ga,gb,pa,pb,w1a,w2a,w3a,w1b,w2b,w3b],[f,g0]] #data = [[eid,pid,ga,gb,pa,pb,w1a,w2a,w3a,w1b,w2b,w3b],[f,x1,x2,x3]] main = data[0] flag = data[1][0] if flag in [0, 1]: self.g0 = None self.x1 = data[1][1] self.x2 = data[1][2] self.x3 = data[1][3] else: self.g0 = data[1][1] self.x1 = None self.x2 = None self.x3 = None self.eid = main[0] self.pid = main[1] self.ga = main[2] self.gb = main[3] #self.offt = str(data[4]) # GGG self.offt = 'GGG' #: .. todo:: offt can be an integer; translate to char self.pa = main[4] self.pb = main[5] self.w1a = main[6] self.w2a = main[7] self.w3a = main[8] self.w1b = main[9] self.w2b = main[10] self.w3b = main[11] #print("offt = %s" %(self.offt)) if not is_string(self.offt): raise SyntaxError('invalid offt expected a string of length 3 ' 'offt=|%r|; Type=%s' % (self.offt, type(self.offt))) msg = 'invalid offt parameter of %s...offt=%s' % (self.type, self.offt) # B,G,O assert self.offt[0] in ['G', 'B'], msg assert self.offt[1] in ['G', 'O', 'E'], msg assert self.offt[2] in ['G', 'O', 'E'], msg