Module DocGenerator
[hide private]
[frames] | no frames]

Source Code for Module DocGenerator

  1  #!/usr/bin/env python 
  2  #-*- coding: UTF8 -*- 
  3  # 
  4  #    Project: The EDNA Kernel 
  5  #             http://www.edna-site.org 
  6  # 
  7  #    File: "$Id: DocGenerator.py 1092 2010-02-02 kieffer $" 
  8  # 
  9  #    Copyright (C) 2008-2010 European Synchrotron Radiation Facility 
 10  #                            Grenoble, France 
 11  # 
 12  # 
 13  #    This program is free software: you can redistribute it and/or modify 
 14  #    it under the terms of the GNU Lesser General Public License as published 
 15  #    by the Free Software Foundation, either version 3 of the License, or 
 16  #    (at your option) any later version. 
 17  # 
 18  #    This program is distributed in the hope that it will be useful, 
 19  #    but WITHOUT ANY WARRANTY; without even the implied warranty of 
 20  #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 21  #    GNU Lesser General Public License for more details. 
 22  # 
 23  #    You should have received a copy of the GNU General Public License 
 24  #    and the GNU Lesser General Public License  along with this program.   
 25  #    If not, see <http://www.gnu.org/licenses/>. 
 26  # 
 27   
 28  """ 
 29  This is the documentation generator of the EDNA projet, it relies on EpyDoc, please have a look on  
 30  U{the epydoc homepage<http://epydoc.sourceforge.net>} 
 31  """ 
 32   
 33  __author__ = "Jérôme Kieffer" 
 34  __contact__ = "Jerome.Kieffer@esrf.eu" 
 35  __license__ = "GPLv3" 
 36  __date__ = "2011-04-13" 
 37  __copyright__ = "2011-ESRF" 
 38   
 39   
 40  # 
 41  # First locate EDNA_HOME 
 42  # 
 43   
 44  import sys, os, tempfile 
 45  cwd = os.getcwd() 
 46  pyStrProgramPath = os.path.abspath(sys.argv[0]) 
 47  pyStrBinPath = os.path.split(pyStrProgramPath)[0] 
 48  pyStrKernelPath = os.path.split(pyStrBinPath)[0] 
 49  pyStrEdnaHomePath = os.path.split(pyStrKernelPath)[0] 
 50  os.environ["EDNA_HOME"] = pyStrEdnaHomePath 
 51   
 52  ################################################################################ 
 53  # Due to a bug in Epydoc ... it will not be runned through python but rather using the command line 
 54  ################################################################################ 
 55   
 56  #blacklist = ["EDPluginExecSRBRegisterv10", "EDPluginExecProcess"] 
 57  strEdnaKernel = os.path.join(pyStrEdnaHomePath, "kernel", "src") 
 58  sys.path.append(strEdnaKernel) 
 59  if not "PYTHONPATH" in os.environ: 
 60      os.environ["PYTHONPATH"] = strEdnaKernel 
 61  else: 
 62      os.environ["PYTHONPATH"] += strEdnaKernel 
 63  os.environ["PYTHONPATH"] += os.pathsep + os.path.join(pyStrEdnaHomePath, "kernel", "tests", "src") 
 64  os.environ["PYTHONPATH"] += os.pathsep + os.path.join(pyStrEdnaHomePath, "kernel", "tests", "testsuite") 
 65   
 66   
 67  from EDJob                  import EDJob 
 68  from EDUtilsParallel        import EDUtilsParallel 
 69  from EDVerbose              import EDVerbose 
 70  from EDFactoryPluginStatic  import EDFactoryPluginStatic 
 71  EDUtilsParallel.initializeNbThread() 
 72  EDFactoryPluginStatic.loadModule("XSDataDocumentation") 
 73  from XSDataDocumentation import XSDataString, XSDataFile, XSDataInputEpydoc, XSDataInteger 
 74  dictJobs = {} 
 75   
76 -def findPlugins(EDNAHome, EDPluginPrefix="EDPlugin", XSDataPrefix="XSData", pythonExtension=".py",):
77 """ 78 This function is the walker that goes through all directories in EDNA_HOME directory and searches for EDNA plugins ... 79 80 @param EDNAHome: the path of EDNA_HOME 81 @type EDNAHome: string 82 @param EDPluginPrefix: the start of the name of an EDNA Plugin 83 @type EDPluginPrefix: string 84 @param pythonExtension: the extension of an EDNA plugin, usually .py 85 @type pythonExtension: string 86 @return: to be definied but probably a dictionary with {EDPlugin: path} 87 @rtype: python dictionary 88 """ 89 results = {} 90 PythonPath = [] 91 for root, dirs, files in os.walk(EDNAHome): 92 if '.svn' in dirs: 93 dirs.remove('.svn')# don't visit SVN directories 94 if 'tests' in dirs: 95 dirs.remove('tests')# don't visit test directories 96 if "template" in dirs: 97 dirs.remove('template')# don't visit template directories 98 if "src" in dirs: 99 PythonPath.append(os.path.abspath(os.path.join(EDNAHome, root, "src"))) 100 if files != []: 101 for oneFile in files: 102 if oneFile.endswith(pythonExtension): 103 if oneFile.find(EDPluginPrefix) == 0 : #here we have a plugin 104 results[os.path.splitext(oneFile)[0] ] = os.path.split(os.path.abspath(os.path.join(EDNAHome, root)))[0] 105 if oneFile.find(XSDataPrefix) == 0 : #here we have a Datamodel binding 106 PythonPath.append(os.path.abspath(os.path.join(EDNAHome, root))) 107 for mydir in PythonPath: 108 if not mydir in sys.path: 109 sys.path.append(mydir) 110 os.environ["PYTHONPATH"] += ":" + mydir 111 return results
112 113
114 -def findProjects(EDNAHome):
115 """ 116 This function is the walker that goes through all directories in EDNA_HOME directory and searches for EDNA projects or libraries ... 117 118 @param EDNAHome: the path of the EDNA_HOME top directory 119 @type EDNAHome: string 120 @param EDPluginPrefix: the start of the name of an EDNA Plugin 121 @type EDPluginPrefix: string 122 @param pythonExtension: the extension of an EDNA plugin, usually .py 123 @type pythonExtension: string 124 @return: a list of RelativeProjectPath 125 @rtype: python list 126 """ 127 pylResults = [] 128 for dirname in os.listdir(EDNAHome): 129 if not os.path.isdir(os.path.join(EDNAHome, dirname)): 130 continue 131 elif dirname in ['.svn', 'tests', 'template', "tmp", "temp", ".settings"]: 132 continue 133 elif dirname.find("libraries") == 0: 134 for subdir in os.listdir(os.path.join(EDNAHome, dirname)): 135 if subdir in ['.svn', 'tests', 'template', "tmp", "temp", ".settings"]: 136 continue 137 elif os.path.isdir(os.path.join(EDNAHome, dirname, subdir)): 138 pylResults.append(os.path.join(dirname, subdir)) 139 else: 140 pylResults.append(dirname) 141 return pylResults
142 143
144 -def findFile(pluginDir, pythonExtension=".py", excludePrefixes=["XSData", "dna_", "ALJy", "EDJob", "EDParallelExecute", "EDUtilsParallel"]):
145 """ 146 This function is the walker that goes through all directories in plugin directory and searches for python source files ... 147 148 @param pluginDir: the path to the plugin 149 @type pluginDir: string 150 @param pythonExtension: the extension of an EDNA plugin, usually .py 151 @type pythonExtension: string 152 @param excludePrefix: prefix that will not be included in code generation, typically the XSData bindings 153 @type excludePrefix: python string 154 @return: list of python files 155 @rtype: python list 156 157 """ 158 results = [] 159 for root, dirs, files in os.walk(pluginDir): 160 if '.svn' in dirs: 161 dirs.remove('.svn')# don't visit SVN directories 162 if files != []: 163 for oneFile in files: 164 if oneFile.endswith(pythonExtension): 165 for oneExt in excludePrefixes: 166 if oneFile.startswith(oneExt): 167 break 168 else: #this is executed only if no break was encountered 169 results.append(os.path.join(pluginDir, root, oneFile)) 170 return results
171
172 -def rmdir(topdir, bypass=False):
173 """Delete everything reachable from the directory named in "top", 174 assuming there are no symbolic links. 175 CAUTION: This is dangerous! For example, if top == '/', it 176 could delete all your disk files. 177 @param topdir: the directory to remove, the directory will stay there, but emptied. 178 @type topdir: python string 179 @param bypass: bypass the security if True 180 @type bypass: boolean 181 """ 182 topdir = os.path.abspath(topdir) 183 if not os.path.isdir(topdir): 184 EDVerbose.screen("The argument topdir= %s is not a directory, giving up" % (topdir)) 185 return 186 if ((topdir.find(pyStrEdnaHomePath) != 0) or (pyStrEdnaHomePath == topdir))and not bypass : 187 EDVerbose.screen("This is a dangerous method, lets play only in sub-directories of EDNA_HOME") 188 return 189 for root, dirs, files in os.walk(topdir, topdown=False): 190 if '.svn' in dirs: 191 dirs.remove('.svn')# don't visit SVN directories 192 for name in files: 193 os.remove(os.path.join(root, name)) 194 for name in dirs: 195 try: 196 os.rmdir(os.path.join(root, name)) 197 except OSError: 198 EDVerbose.screen("Error in removing: " + os.path.join(root, name))
199 200 201 202 ############################################################################### 203 # this is the main program if somebody wants to use this as a library 204 ############################################################################### 205 if __name__ == '__main__': 206 cwd = os.getcwd() 207 workdir = tempfile.mkdtemp("doc", "tmp", os.getenv("HOME")) 208 # if not os.path.exists(workdir): 209 # os.makedirs(workdir) 210 os.chdir(workdir) 211 docFormat = "html" 212 CleanAll = False 213 WebSite = False 214 bVerbose = False 215 pathWebDoc = "" 216 for i in sys.argv: 217 if i == "--pdf": 218 docFormat = "pdf " 219 elif i == "--clean": 220 CleanAll = True 221 elif i == "--website": 222 WebSite = True 223 elif i == "-v": 224 bVerbose = True 225 elif os.path.isdir(i): 226 pathWebDoc = i 227 228 if WebSite and pathWebDoc: 229 print "Generating web documentation in ", pathWebDoc 230 rmdir(pathWebDoc, bypass=True) 231 for oneproject in findProjects(pyStrEdnaHomePath): 232 print ("Generating HTML pages for " + oneproject) 233 docPath = os.path.join(pathWebDoc, oneproject) 234 os.makedirs(docPath, int("755", 8)) 235 listOfPythonFiles = findFile(os.path.join(pyStrEdnaHomePath, oneproject)) 236 listOfPythonFiles.sort() 237 if len(listOfPythonFiles) > 0: 238 epydocJob = EDJob("EDPluginExecEpydocv1_0") 239 dictJobs[oneproject] = epydocJob 240 xsd = XSDataInputEpydoc() 241 xsd.setDocPath(XSDataFile(XSDataString(docPath))) 242 xsd.setProjectName(XSDataString(oneproject)) 243 xsd.setDocType(XSDataString(docFormat)) 244 if bVerbose: 245 xsd.setVerbosity(XSDataInteger(1)) 246 else: 247 xsd.setVerbosity(XSDataInteger(-1)) 248 xsd.setSources([XSDataFile(XSDataString(oneFile)) for oneFile in listOfPythonFiles]) 249 epydocJob.setDataInput(xsd) 250 epydocJob.execute() 251 else: 252 print ("Error: No python files for project %s" % oneproject) 253 254 else: 255 plugins = findPlugins(pyStrEdnaHomePath) 256 pluginPathProcessed = [] 257 for oneplugin in plugins: 258 pluginPath = plugins[oneplugin] 259 if not pluginPath in pluginPathProcessed: 260 pluginPathProcessed.append(pluginPath) 261 docPath = os.path.join(pluginPath, "doc") 262 if not os.path.isdir(docPath): 263 os.mkdir(docPath) 264 if CleanAll: 265 rmdir(docPath) 266 EDVerbose.screen("%40s --> %s" % (oneplugin, plugins[oneplugin])) 267 myPluginPath = os.path.join(pluginPath, "plugins", oneplugin + ".py") 268 listOfPythonFiles = [] 269 if os.path.isfile(myPluginPath): 270 listOfPythonFiles = [myPluginPath] 271 for onePyFile in findFile(pluginPath): 272 if not onePyFile in listOfPythonFiles: 273 listOfPythonFiles.append(onePyFile) 274 if len(listOfPythonFiles) > 0: 275 epydocJob = EDJob("EDPluginExecEpydocv1_0") 276 dictJobs[oneplugin] = epydocJob 277 xsd = XSDataInputEpydoc() 278 xsd.setDocPath(XSDataFile(XSDataString(docPath))) 279 xsd.setProjectName(XSDataString(oneplugin)) 280 xsd.setDocType(XSDataString(docFormat)) 281 if bVerbose: 282 xsd.setVerbosity(XSDataInteger(2)) 283 else: 284 xsd.setVerbosity(XSDataInteger(-1)) 285 xsd.setSources([XSDataFile(XSDataString(oneFile)) for oneFile in listOfPythonFiles ]) 286 epydocJob.setDataInput(xsd) 287 epydocJob.execute() 288 else: 289 print ("Error: No python files for plugin %s" % oneplugin) 290 EDVerbose.screen("Back to main") 291 for jobName in dictJobs: 292 job = dictJobs[jobName] 293 if job.getStatus() in [EDJob.PLUGIN_STATE_RUNNING, EDJob.PLUGIN_STATE_UNITIALIZED]: 294 EDVerbose.screen("Waiting for job %s to finish" % jobName) 295 job.synchronize() 296 EDVerbose.screen("Generation of documentation finished") 297 os.chdir(cwd) 298 EDJob.stats() 299