1   
  2   
  3   
  4   
  5   
  6  """defines interface for all classes that writes L{code_creators.module_t} to file(s)""" 
  7   
  8  import os 
  9  import time 
 10  import codecs 
 11  import md5sum_repository 
 12  from pyplusplus import utils 
 13  from pyplusplus import _logging_ 
 14  from pyplusplus import code_creators 
 15  from pyplusplus import code_repository 
 18      """Base class for all module/code writers. 
 19       
 20      All writers should have similar usage:: 
 21       
 22        w = writer_class(module, file, ...) 
 23        w.write() 
 24      """ 
 25      logger = _logging_.loggers.file_writer 
 26       
 27 -    def __init__(self, extmodule, files_sum_repository=None, encoding='ascii'): 
  37   
 38      @property 
 40          """encoding name used to write generated code to files""" 
 41          return self.__encoding 
  42               
 43      @property 
 45          """The root of the code creator tree ( code_creators.module_t )""" 
 46          return self.__extmodule 
  47   
 48      @property 
 50          return self.__files_sum_repository 
  51   
 53          """ Main write method.  Should be overridden by derived classes. """ 
 54          raise NotImplementedError() 
  55          
 56      @staticmethod 
 58          """creates backup of the file, by renaming it to C{fpath + ~}""" 
 59          if not os.path.exists( fpath ): 
 60              return          
 61          backup_fpath = fpath + '~' 
 62          if os.path.exists( backup_fpath ): 
 63              os.remove( backup_fpath ) 
 64          os.rename( fpath, backup_fpath ) 
  65       
 76      @staticmethod 
 77 -    def write_file( fpath, content, files_sum_repository=None, encoding='ascii' ): 
  78          """Write a source file. 
 79   
 80          This method writes the string content into the specified file. 
 81          An additional fixed header is written at the top of the file before 
 82          content. 
 83   
 84          @param fpath: File name 
 85          @type fpath: str 
 86          @param content: The content of the file 
 87          @type content: str 
 88          """ 
 89          fname = os.path.split( fpath )[1] 
 90          writer_t.logger.debug( 'write code to file "%s" - started' % fpath ) 
 91          start_time = time.clock() 
 92          fcontent_new = [] 
 93          if os.path.splitext( fpath )[1] == '.py': 
 94              fcontent_new.append( '# This file has been generated by Py++.' ) 
 95          else: 
 96              fcontent_new.append( '// This file has been generated by Py++.' ) 
 97          fcontent_new.append( os.linesep * 2 ) 
 98          fcontent_new.append( content ) 
 99          fcontent_new.append( os.linesep )  
100          fcontent_new = ''.join( fcontent_new ) 
101          if not isinstance( fcontent_new, unicode ): 
102              fcontent_new = unicode( fcontent_new, encoding )  
103           
104          new_hash_value = None 
105          curr_hash_value = None 
106          if files_sum_repository: 
107              new_hash_value  = files_sum_repository.get_text_value( fcontent_new ) 
108              curr_hash_value = files_sum_repository.get_file_value( fname ) 
109              if new_hash_value == curr_hash_value: 
110                  writer_t.logger.debug( 'file was not changed( hash ) - done( %f seconds )' 
111                                         % ( time.clock() - start_time ) ) 
112                  return 
113   
114          if None is curr_hash_value and os.path.exists( fpath ): 
115               
116               
117               
118              f = codecs.open( fpath, 'rb', encoding ) 
119              fcontent = f.read() 
120              f.close() 
121              if fcontent == fcontent_new: 
122                  writer_t.logger.debug( 'file was not changed( content ) - done( %f seconds )' 
123                                         % ( time.clock() - start_time ) ) 
124                  return 
125           
126          writer_t.logger.debug( 'file changed or it does not exist' ) 
127               
128          writer_t.create_backup( fpath ) 
129          f = codecs.open( fpath, 'w+b', encoding ) 
130          f.write( fcontent_new ) 
131          f.close() 
132          if new_hash_value: 
133              files_sum_repository.update_value( fname, new_hash_value ) 
134          writer_t.logger.info( 'file "%s" - updated( %f seconds )' % ( fname, time.clock() - start_time ) ) 
 135       
143   
145          self.__exposed_decls_db.save( file_path ) 
  146