#******************************************************************************* # ALMA - Atacama Large Millimeter Array # Copyright (c) UKATC - UK Astronomy Technology Centre, Science and Technology Facilities Council, 2011 # (in the framework of the ALMA collaboration). # All rights reserved. # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #******************************************************************************* ## Check ALMA Python scripts ## ## A M Chavan, ESO, 14-Jan-2005 ## ## $Id: ScriptValidator.py,v 1.3 2005/02/02 12:23:33 amchavan Exp $ import sys ## from pyclbr import readmodule ### NOT SUPPORTED BY JYTHON ## from posix import getcwd __all__ = [ 'ScriptValidator' ] class ScriptValidator: pathname = "" # Pathname of the script to check text = "" # Text of the script to check ignore = [] # List of names to be ignored report = "" # Verification report: if empty, all is OK superclass = "ControlScript" # name of script superclass ## Constructor ## Define a verifier for a Python script ## Args: ## pathname Pathname of the file containing the input script; ## relative pathnames are resolved from the current ## working directory. def __init__( self, pathname ): self.pathname = pathname try: f = open( pathname ) self.text = f.read() f.close() except IOError, e: self.report = self.formatIOError( e, pathname ) #print ">>>" + self.text + "<<<" ## Verify if the input script is valid. ## Verification steps include: ## Script is not empty ## Python syntax is correct ## The script is a valid ALMA script (TODO: see ## the verifyalma() method) ## ## Return: if all is well, an empty string is returned; ## otherwise, an error report is generated and returned. ## def verify( self ): # Report any errors reported by the # constructor #---------------------------------------- if len( self.report ) != 0: return self.report # Check script length #---------------------------------------- if self.text == None or len( self.text ) == 0: return "Script is empty" # Check if the given script is a valid # Python script #---------------------------------------- try: compile( self.text, "???", "exec" ) except SyntaxError, info: self.report = self.formatSyntaxError( info ) return self.report except Exception, info: self.report = info return self.report self.report = self.verifyalma() return self.report ## Analyze the given script and see if it contains ## a valid ALMA script. ## We assume that the script is a syntactically valid ## Python script. We also assume that the script pathame ## ends with the ".py" extension. ## ## TODO: define "what" exactly constitutes a valid ## ALMA Python script ## ## Return: if all is well, an empty string is returned; ## otherwise, an error report is generated and returned. ## def verifyalma( self ): l = len( self.pathname) # retrieve module name module = self.pathname[0:l-3] numsc = 0 # we found 0 script classes ## NOTE: following line requires the 'pyclbr' package, which ## is NOT SUPPORTED BY JYTHON ## mdesc = readmodule( module ) # parse the script mdesc = {} ret = "" # we return this error report for cname in mdesc.keys(): # foreach classname... if cname == 'ControlScript': # ignore this continue cdesc = mdesc[cname] super = cdesc.super # list of superclasses ## TODO ## Find out if a class is defined, and if ## that is a subclass of ControlScript # KEEP THE FOLLOWING LINES for future extension #============================================================ # print cdesc.module # print cdesc.name # print cdesc.super # print cdesc.methods # print cdesc.file # print cdesc.lineno return ret ## Utility function: format a SyntaxError exception nicely ## for display to user ## def formatSyntaxError( self, e ): ret = "SyntaxError: " + str( e ) + ":\n" + \ e.text + "\n" + "^".rjust( e.offset ) return ret ## Utility function: format an IOError exception nicely ## for display to user ## def formatIOError( self, e, info="" ): msg = e.args[0] ret = "IOError: %s: %s" % (info, msg ) return ret