pyNastran
0.5.0
pyNastran BDF Reader/Writer, OP2 Parser, and GUI
|
00001 ## GNU Lesser General Public License 00002 ## 00003 ## Program pyNastran - a python interface to NASTRAN files 00004 ## Copyright (C) 2011-2012 Steven Doyle, Al Danial 00005 ## 00006 ## Authors and copyright holders of pyNastran 00007 ## Steven Doyle <mesheb82@gmail.com> 00008 ## Al Danial <al.danial@gmail.com> 00009 ## 00010 ## This file is part of pyNastran. 00011 ## 00012 ## pyNastran is free software: you can redistribute it and/or modify 00013 ## it under the terms of the GNU Lesser General Public License as published by 00014 ## the Free Software Foundation, either version 3 of the License, or 00015 ## (at your option) any later version. 00016 ## 00017 ## pyNastran is distributed in the hope that it will be useful, 00018 ## but WITHOUT ANY WARRANTY; without even the implied warranty of 00019 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00020 ## GNU General Public License for more details. 00021 ## 00022 ## You should have received a copy of the GNU Lesser General Public License 00023 ## along with pyNastran. If not, see <http://www.gnu.org/licenses/>. 00024 ## 00025 # pylint: disable=C0103,R0902,R0904,R0914 00026 00027 from __future__ import division, print_function 00028 import os 00029 import sys 00030 00031 class BDFReader(object): 00032 def __init__(self, debug, log): 00033 self.relpath = True 00034 if sys.version_info < (2, 6): 00035 #version = sys.version_info 00036 self.relpath = False 00037 #raise RuntimeError("must use python 2.6 or greater...version=%s" 00038 # %(str(version))) 00039 00040 if log is None: 00041 from pyNastran.general.logger import dummyLogger 00042 if debug: 00043 word = 'debug' 00044 else: 00045 word = 'info' 00046 loggerObj = dummyLogger() 00047 log = loggerObj.startLog(word) # or info 00048 self.log = log 00049 00050 def print_filename(self, filename): 00051 """ 00052 Takes a path such as C:/work/fem.bdf and locates the file using 00053 relative paths. If it's on another drive, the path is not modified. 00054 @param self the object pointer 00055 @param filename a filename string 00056 @retval filenameString a shortened representation of the filename 00057 """ 00058 driveLetter = os.path.splitdrive(os.path.abspath(filename))[0] 00059 if driveLetter == os.path.splitdrive(os.curdir)[0] and self.relpath: 00060 return os.path.relpath(filename) 00061 else: 00062 return filename 00063 ### 00064 00065 def open_file(self, infileName): 00066 """ 00067 Takes a filename and opens the file. 00068 This method is used in order to support INCLUDE files. 00069 """ 00070 #print self.isOpened 00071 if self.isOpened[infileName] == False: 00072 self._active_filenames.append(infileName) 00073 #self.log.info("*openFile bdf=|%s| pwd=|%s|" %(infileName, 00074 # os.getcwd())) 00075 if not os.path.exists(infileName): 00076 msg = "infileName=|%s| does not exist..." % (infileName) 00077 raise IOError(msg) 00078 infile = open(infileName, 'r') 00079 self.infilesPack.append(infile) 00080 self.lineNumbers.append(0) 00081 self.isOpened[infileName] = True 00082 self.linesPack.append([]) 00083 ### 00084 else: 00085 pass 00086 #print "is already open...skipping" 00087 ### 00088 00089 def get_file_stats(self): 00090 """ 00091 gets information about the active BDF file being read 00092 @param self the object pointer 00093 @retval lineNumber the active file's line number 00094 """ 00095 filename = self._active_filenames[-1] 00096 return (filename, self.get_line_number()) 00097 00098 def get_line_number(self): 00099 """ 00100 Gets the line number of the active BDF (used for debugging). 00101 @param self the object pointer 00102 @retval returns the line number of the active BDF filename 00103 """ 00104 lineNumber = self.lineNumbers[-1] 00105 return lineNumber 00106 00107 def get_next_line(self, debug=False): 00108 """ 00109 Gets the next line in the BDF 00110 @param self 00111 the BDF object 00112 @param debug 00113 developer debug 00114 @retval line 00115 the next line in the BDF or None if it's the end of the current file 00116 """ 00117 self.lineNumbers[-1] += 1 00118 linesPack = self._make_lines_pack(debug=False) 00119 #print "len(linesPack) = ", len(linesPack) 00120 #for line in linesPack: 00121 #print("$ |%r|" %(line)) 00122 00123 if len(linesPack) == 0: 00124 self.close_file() 00125 return None 00126 #linesPack = self._make_lines_pack(debug=debug) 00127 #return lastLine 00128 #print linesPack[0] 00129 return linesPack.pop(0) 00130 00131 def close_file(self, debug=False): 00132 """ 00133 Closes the active file object. 00134 If no files are open, the function is skipped. 00135 This method is used in order to support INCLUDE files. 00136 @param self the object pointer 00137 @param debug developer debug 00138 """ 00139 if len(self.infilesPack) == 0: 00140 return 00141 if debug: 00142 self.log.debug("*closing") 00143 infile = self.infilesPack.pop() 00144 infile.close() 00145 00146 #if debug: 00147 # print [os.path.relpath(fname) for fname in self._active_filenames] 00148 lineNumbers = self.lineNumbers.pop() 00149 active_filename = self._active_filenames.pop() 00150 linesPack = self.linesPack.pop() 00151 self.isOpened[active_filename] = False 00152 00153 if len(self.linesPack) == 0: 00154 raise IOError('\nThe bdf closed unexpectedly...\n an Executive ' 00155 'and Case Control Decks are required...' 00156 'put a CEND and BEGIN BULK in the BDF') 00157 nlines = len(self.linesPack[-1]) 00158 00159 ## determines if self.activefilename should be closed at the next 00160 ## opportunity 00161 self.doneReading = False 00162 if debug: 00163 fnameA = self.print_filename(active_filename) 00164 fnameB = self.print_filename(self.bdf_filename) 00165 00166 self.log.debug("active_filename=|%s| infilename=%s len(pack)=%s\n" 00167 %(fnameA,fnameB,nlines)) 00168 ### 00169 #print "\n\n" 00170 00171 def _set_infile(self, bdf_filename, includeDir=None): 00172 """ 00173 Sets up the basic file/lines/cardCounting operations 00174 @param self 00175 the BDF object 00176 @param bdf_filename 00177 the input BDF filename 00178 @param includeDir 00179 the location of include files if an absolute/relative path is 00180 not used (not supported in Nastran) 00181 """ 00182 ## automatically rejects every parsable card (default=False) 00183 self.autoReject = False 00184 ## is the active file done reading 00185 self.doneReading = False 00186 ## was an ENDDATA card found 00187 self.foundEndData = False 00188 00189 if includeDir is None: 00190 includeDir = os.path.dirname(bdf_filename) 00191 ## the active filename (string) 00192 self.bdf_filename = bdf_filename 00193 ## the directory of the 1st BDF (include BDFs are relative to this one) 00194 self.includeDir = includeDir 00195 ## list of infile objects (needed for INCLUDE files) 00196 self.infilesPack = [] 00197 ## list of lines from self.activeFilename that are stored 00198 self.linesPack = [] 00199 ## list of all open filenames 00200 self._active_filenames = [] 00201 ## stores the line number of self.activefilename that the parser is on 00202 ## very helpful when debugging 00203 self.lineNumbers = [] 00204 ## dictionary that says whether self.bdf_filename is open/close 00205 ## (boolean) 00206 self.isOpened = {self.bdf_filename: False} 00207 ## list of all read in cards - useful in determining if 00208 ## entire BDF was read & really useful in debugging 00209 self.cardCount = {} 00210 ## stores the cardCount of cards that have been rejected 00211 self.rejectCount = {} 00212