def _nastran_set(self, name, cid, attrs, unique_int): """We go through the text that we have and make the needed substitution. name: str cid: int or str Specifies the id of the card. attrs: [{fieldnum: value_to_insert}] We may have to change a few fields for a given line. Those changes are stored in attrs. unique_int: int This integer is needed for writing out the continuations in the Nastran file. It must be unique within the file (!beware). """ card = None for index, line in enumerate(self.text): if line.startswith(name): match = re.match("(?P<name>[a-zA-Z0-9*]*) +(?P<num>\d+) ", line) if match and \ (match.group("name") == name or \ match.group("name") == name + "*") \ and match.group("num") == str(cid): if not card: card = index else: raise RuntimeError("There were two cards with the " + \ "same id. You don't want this. " + \ "Two cards: " + match.group("name") +\ " id: " + match.group("num")) if card is None: raise RuntimeError("Could not find card " + name + " with id " + str(cid)) # are we dealing with a long card? long_card = False if self.text[card].startswith(name + "*") or \ name.endswith("*"): long_card = True offset = 16 if long_card else 8 divisions = 6 if long_card else 10 # parse it up items = [] current_row = card continuation = None while current_row < len(self.text) and \ (current_row == card or self.text[current_row].startswith(" ") or \ (continuation and self.text[current_row].replace(" ", "").startswith(continuation))): # in both long and short forms, the first slot is 8 characters wide # then the rest are either 8 or 16 wide last_index = 0 for i in [8 + i * offset for i in range(divisions)]: items.append(self.text[current_row][last_index:i]) last_index = i # continuations are in the last slot if len(items[-1]) > 0: continuation = items[-1].replace(" ", "") if not continuation.startswith("+") and \ not continuation.startswith("*"): raise RuntimeError("Your continuations should start" + \ "with either * or +. `" + continuation + "` is not" + \ "acceptable") current_row += 1 # we want to delete the row(s) from the file del self.text[card:current_row] # now we add the field with the change applied # we're also going to conver the field to long # form and add it to the end of the file long_format = 16 divisions = 6 # change the value we're supposed to change for attr in attrs: fieldnum = attr["fieldnum"] value = attr["value"] #print "supposed to change", fieldnum, "to", value items[fieldnum] = stringify(value, length=long_format) # remove the continuations to_remove = None if not long_card: to_remove = [i for i in range(9, len(items), 10)] + \ [i for i in range(10, len(items), 10)] else: to_remove = [i for i in range(5, len(items), 6)] + \ [i for i in range(6, len(items), 6)] to_remove.sort(reverse=True) for i in to_remove: del items[i] # write it to the end of the file unique_int, new_rows = _items_to_long_form(items, unique_int) for row in new_rows[::-1]: self.text.insert(card, row) #print "\n".join(new_rows) return unique_int
def replace(self, input_variables): """ Replace the ``input_variables`` in the text with the corresponding values. input_variables: {variable_name: value} We want to replace the instances of ``variable_name`` with a value. ``variable_name`` should be a string; ``value`` should be a stringafiable object. Note that although the actual variables are specified, like ``%varname`` in the Nastran file, the variable name here should just be ``varname``. Changes ``self.text``. Running this twice should probably error out since it wouldn't find the variables it was meant to replace. """ # should be an array of lines nastran_text = self.text # we want all the variables in the nastran text all_variables = set() for line in nastran_text: matches = re.findall(variable_match, line) for match in matches: if match in all_variables: # This should be given to the user... but # maybe not in stdout print "There is a duplicate variable called", match print "They will get the same value" all_variables.add(match) # make sure we have all the variables that are declared # in the file extras = all_variables.difference(input_variables.keys()) if len(extras) > 0: raise ValueError("There are variables in the file that aren't " +\ "provided as input variables: " + \ str(extras)) not_used = set(input_variables.keys()).difference(all_variables) if len(not_used) > 0: # we really want to be logging this to DEBUG, or equiv print "Hey, just a heads up. You are passing in variables " +\ "that are not being replaced because they are not " +\ "in the file. This could indicate that you made a " +\ "mistake, or not. The offending variables are: " + \ str(not_used) new_nastran_text = [] for line in nastran_text: new_nastran_text.append(line[:]) matches = re.findall(variable_match, line) for match in matches: # If the variable starts with ``*'', we will not # simply replace the 8 character block, but we # will just overwrite the location of the variable if match.startswith("*"): value = str(input_variables[match]) if len(value) < (len(match) + 1): value = value.ljust(len(match)+1) start_pos = new_nastran_text[-1].find("%" + match) end_pos = start_pos + len(value) # exclusive new_nastran_text[-1] = new_nastran_text[-1][:start_pos] + \ value + \ new_nastran_text[-1][end_pos:] #print "replacing", match, new_nastran_text, line else: new_nastran_text[-1] = \ nastran_replace_inline(new_nastran_text[-1],\ "%" + match, \ stringify(input_variables[match])) self.text = new_nastran_text
def replace(self, input_variables): """ Replace the ``input_variables`` in the text with the corresponding values. input_variables: {variable_name: value} We want to replace the instances of ``variable_name`` with a value. ``variable_name`` should be a string; ``value`` should be a stringafiable object. Note that although the actual variables are specified, like ``%varname`` in the Nastran file, the variable name here should just be ``varname``. Changes ``self.text``. Running this twice should probably error out since it wouldn't find the variables it was meant to replace. """ # should be an array of lines nastran_text = self.text # we want all the variables in the nastran text all_variables = set() for line in nastran_text: matches = re.findall(variable_match, line) for match in matches: if match in all_variables: # This should be given to the user... but # maybe not in stdout print "There is a duplicate variable called", match print "They will get the same value" all_variables.add(match) # make sure we have all the variables that are declared # in the file extras = all_variables.difference(input_variables.keys()) if len(extras) > 0: raise ValueError("There are variables in the file that aren't " +\ "provided as input variables: " + \ str(extras)) not_used = set(input_variables.keys()).difference(all_variables) if len(not_used) > 0: # we really want to be logging this to DEBUG, or equiv print "Hey, just a heads up. You are passing in variables " +\ "that are not being replaced because they are not " +\ "in the file. This could indicate that you made a " +\ "mistake, or not. The offending variables are: " + \ str(not_used) new_nastran_text = [] for line in nastran_text: new_nastran_text.append(line[:]) matches = re.findall(variable_match, line) for match in matches: # If the variable starts with ``*'', we will not # simply replace the 8 character block, but we # will just overwrite the location of the variable if match.startswith("*"): value = str(input_variables[match]) if len(value) < (len(match) + 1): value = value.ljust(len(match) + 1) start_pos = new_nastran_text[-1].find("%" + match) end_pos = start_pos + len(value) # exclusive new_nastran_text[-1] = new_nastran_text[-1][:start_pos] + \ value + \ new_nastran_text[-1][end_pos:] #print "replacing", match, new_nastran_text, line else: new_nastran_text[-1] = \ nastran_replace_inline(new_nastran_text[-1],\ "%" + match, \ stringify(input_variables[match])) self.text = new_nastran_text