Exemple #1
0
    def _load_csmodule(self, modName, options):
        '''
        Import a module given its name, and return the object.
        If there are any problems finding or loading the module we return None.
        If the module has python errors in it we treat as catastrophic
        failure and allow caller to handle.
        '''
        csmoduleClassInstance = None
        try:
            # Load the module called modName, and then get class inside the
            # module with the same name
            moduleFile = __import__(self.PACKAGE_PREFIX + modName)
            module = getattr(moduleFile, modName)
            moduleClass = getattr(module, modName)

            # Instantiate the module
            csmoduleClassInstance = moduleClass(options)

            # Make sure required methods are in the class; fatal error if not
            for method in self.RequiredMethods:
                getattr(csmoduleClassInstance, method)

        except (ImportError, AttributeError):
            trace.traceback()
            raise utils.SurveyorException(uistrings.STR_ErrorLoadingModule.format(modName))
        return csmoduleClassInstance
Exemple #2
0
    def __init__(self, configOptions):

        # Modules overrides to tell config validation what they can measure
        self.measures = []
        self.verbs    = []
        self.verbEnds = {}

        # We store this each measure call in case derived class wants to use
        self._currentPath = None

        # Delegate that subclasses can call to add config options
        self._configOptionDict = {}
        self._cs_init_config_options()

        # Process any config options
        for optName, optValue in configOptions:
            trace.config(2, "ConfigOpt:  {0}:{1}".format(optName, optValue))
            try:
                configCode, _configHelp = self._configOptionDict[optName]
            except KeyError, e:
                raise utils.CsModuleException("Invalid Config Option: {0}".format(str(e)))
            trace.config(3, "ConfigCode:  {0}".format(configCode))
            try:
                exec(configCode)
            except Exception, e:
                trace.traceback()
                raise utils.CsModuleException("Error executing Config Option: {0}".format(str(e)))
Exemple #3
0
    def _survey(self, fileObject, configEntry, measurements, _analysis):
        if not fileObject:
            return

        self.totalLines = 0
        self.blankLines = 0
        self.contentLines = 0
        try:

            measureMethod = self.filetypeMeasures.get(self._currentPath.fileExt, None)
            if measureMethod is not None:
                measureMethod(fileObject, measurements)

            # Otherwise if it is a delta list comparison
            elif isinstance(fileObject, list):
                self._measure_text(fileObject, measurements)

            # Otherwise if it is a text File
            elif filetype.is_text_file(fileObject):
                self._measure_text(fileObject, measurements)

            # TBD -- what to with binary files without handlers

            # Pack up our measurements
            measurements[ self.LINES_TOTAL   ] = self.totalLines
            measurements[ self.LINES_BLANK   ] = self.blankLines
            measurements[ self.LINES_CONTENT ] = self.contentLines

            return True

        except Exception, e:
            trace.traceback()
            raise utils.FileMeasureError(
                    "Problem processing file {0} with module: {1}\n\t{1}".format(
                    self._currentPath.filePath, self.__class__.__name__, str(e)))
Exemple #4
0
    def _survey(self, fileObject, configEntry, measurements, _analysis):
        if not fileObject:
            return

        self.totalLines = 0
        self.blankLines = 0
        self.contentLines = 0
        try:

            measureMethod = self.filetypeMeasures.get(self._currentPath.fileExt, None)
            if measureMethod is not None:
                measureMethod(fileObject, measurements)

            # Otherwise if it is a delta list comparison
            elif isinstance(fileObject, list):
                self._measure_text(fileObject, measurements)

            # Otherwise if it is a text File
            elif filetype.is_text_file(fileObject):
                self._measure_text(fileObject, measurements)

            # TBD -- what to with binary files without handlers

            # Pack up our measurements
            measurements[ self.LINES_TOTAL   ] = self.totalLines
            measurements[ self.LINES_BLANK   ] = self.blankLines
            measurements[ self.LINES_CONTENT ] = self.contentLines

            return True

        except Exception, e:
            trace.traceback()
            raise utils.FileMeasureError(
                    "Problem processing file {0} with module: {1}\n\t{1}".format(
                    self._currentPath.filePath, self.__class__.__name__, str(e)))
Exemple #5
0
 def _validate_file(self, configEntries):
     if not configEntries:
         trace.config(2, "  EMPTY")
     else:
         try:
             self._validate_entries(configEntries)
         except Exception, e:
             trace.traceback()
             raise utils.ConfigError(uistrings.STR_ErrorConfigValidate.format(str(e)))
Exemple #6
0
 def _parse_command_line(self, cmdArgs):
     utils.init_surveyor_dir(cmdArgs[0])
     self._args = cmdlineargs.SurveyorCmdLineArgs(cmdArgs, self)
     helpText = None
     try:
         helpText = self._args.parse_args()
     except KeyboardInterrupt:
         self._keyboardInterrupt()
     except Exception, e:
         trace.traceback()
         helpText = STR_HelpText_Usage
         if len(e.args):
             helpText += STR_ErrorCmdLineText.format(str(self._args.args), str(e))
         else:
             helpText += STR_ErrorParsingCommandLine
Exemple #7
0
    def run(self):
        '''
        Process entry point - set up debug/profile context
        '''
        try:
            trace.set_context(self._dbgContext)

            if self._profileName is not None:
                import cProfile;
                cProfile.runctx('self._run()', globals(), {'self': self}, self._profileName + self.name)
            else:
                self._run()

        except Exception, e:
            self._controlQueue.put_nowait(('JOB', 'EXCEPTION', e))
            trace.traceback()
Exemple #8
0
    def run(self):
        trace.cc(1, "STARTING: Begining to process output queue...")
        try:
            if self._profileName is not None:
                import cProfile;
                cProfile.runctx('self._run()', globals(), {'self': self}, self._profileName + self.name)
            else:
                self._run()
            trace.cc(1, "FINISHED processing output queue")

        except KeyboardInterrupt:
            trace.cc(1, "Ctrl-c occurred in OUTPUT THREAD")
            thread.interrupt_main()
        except Exception, e:
            trace.cc(1, "EXCEPTION occurred while processing output queue")
            self._controlQueue.put_nowait(('JOB', 'EXCEPTION', e))
            trace.traceback(2)
Exemple #9
0
    def run(self):
        '''
        Process entry point - set up debug/profile context
        '''
        try:
            trace.set_context(self._dbgContext)

            if self._profileName is not None:
                import cProfile
                cProfile.runctx('self._run()', globals(), {'self': self},
                                self._profileName + self.name)
            else:
                self._run()

        except Exception, e:
            self._controlQueue.put_nowait(('JOB', 'EXCEPTION', e))
            trace.traceback()
Exemple #10
0
    def _measure_file(self, workItem):
        '''
        Unpack workItem and run all measures requested by the configItems
        for the file
        '''
        (   path,
            deltaPath,
            fileName,
            configItems,
            options,
            numFilesInFolder
            ) = workItem

        self._currentFilePath = os.path.join(path, fileName)
        trace.file(3, "Processing: {0}".format(self._currentFilePath))

        deltaFilePath = None
        if deltaPath is not None:
            deltaFilePath = os.path.join(deltaPath, fileName)

        continueProcessing = True
        try:
            for configItem in configItems:
                if self._check_for_stop():
                    break

                self._open_file(configItem.module, deltaFilePath)

                #
                # Synchronus delegation to the measure module defined in the config file
                #
                configItem.module.process_file(
                        self._currentFilePath,
                        self._currentFileIterator,
                        configItem,
                        numFilesInFolder,
                        self.file_measured_callback)

        except utils.FileMeasureError, e:
            trace.traceback(2)
            self._currentFileErrors.append(
                    uistrings.STR_ErrorMeasuringFile.format(self._currentFilePath, str(e)))
            continueProcessing = not options.breakOnError
Exemple #11
0
    def _measure_file(self, workItem):
        '''
        Unpack workItem and run all measures requested by the configItems
        for the file
        '''
        (path, deltaPath, fileName, configItems, options,
         numFilesInFolder) = workItem

        self._currentFilePath = os.path.join(path, fileName)
        trace.file(1, "Processing: {0}".format(self._currentFilePath))

        deltaFilePath = None
        if deltaPath is not None:
            deltaFilePath = os.path.join(deltaPath, fileName)

        continueProcessing = True
        try:
            for configItem in configItems:
                if self._check_for_stop():
                    break

                self._open_file(configItem.module, deltaFilePath)

                #
                # Synchronus delegation to the measure module defined in the config file
                #
                configItem.module.process_file(self._currentFilePath,
                                               self._currentFileIterator,
                                               configItem, numFilesInFolder,
                                               self.file_measured_callback)

        except utils.FileMeasureError, e:
            trace.traceback(2)
            self._currentFileErrors.append(
                uistrings.STR_ErrorMeasuringFile.format(
                    self._currentFilePath, str(e)))
            continueProcessing = not options.breakOnError
Exemple #12
0
    def _survey_lines(self, linesToSurvey, params, measurements, analysis):
        '''
        Analyze file line by line. linesToSurvey is an iterable set of lines.
        Processing is driven by the regular expressions in member variables.
        The order of processing each line is:
             - Preprocess line string
             - Detect machine vs. human code
             - Detect blank lines
             - Detect single and multi-line comments
             - Capture line measures
             - Peform line processing (searches, routines, etc.)
        '''
        # Setup dictionary for measures and searches we'll do
        self._survey_start(params)

        # If no lines to process, we may still want to output empty measures
        if linesToSurvey is None:
            linesToSurvey = []

        # Track whether we are inside a multi-line comment - we ignore nesting
        scanningMultiLine = False

        # If we have a line seperator, apply it
        for bufferLine in linesToSurvey:
            self.counts['RawLines'][self._activeBlock] += 1
            if self._traceLevel: trace.file(4, "Raw: {0}".format(bufferLine))

            # Allow specializations to special-case certain lines
            if self._alternate_line_processing(bufferLine):
                continue

            lines = [bufferLine]
            if self.addLineSep is not None:
                lines = bufferLine.split(self.addLineSep)

            #
            # Read through the file lines and process them one at a time
            # This is the main processing loop for all csmodules derived from NBNC
            #
            try:
                for rawLine in lines:
                    self.counts['TotalLines'][self._activeBlock] += 1

                    # Allow for clean up of artifacts or other pre-processing
                    line = self._preprocess_line(rawLine)

                    # Detect true blank lines
                    if self.reTrueBlankLine.match(line):
                        self.counts['TrueBlankLines'][self._activeBlock] += 1
                        self._trace_line(line, "T")
                        continue

                    # Block Detection
                    if len(self.blockDetectors) > 1:
                        if self._detect_block_change(line, analysis):
                            scanningMultiLine = False  # Don't allow multi-line comment to span blocks

                    # Determine comment state
                    # This is done before blank lines to make sure we consider multi-line
                    # comment syntax that will be counted as "blank", e.g., /* on it's own line
                    onCommentLine, scanningMultiLine = self._detect_line_comment(
                        line, scanningMultiLine)

                    # Detect blank lines
                    if self._detect_blank_line(line):
                        continue

                    # Measure and analyze -- overriden in derived classes
                    self._measure_line(line, onCommentLine)
                    self._analyze_line(line, analysis, onCommentLine)

            except Exception, e:
                trace.traceback()
                raise utils.FileMeasureError(
                    "Problem processing line: {0} with module: {1}\n{2}".
                    format(str(sum(self.counts['RawLines'])),
                           self.__class__.__name__, str(e)))
Exemple #13
0
            if self._profileName is not None:
                import cProfile
                cProfile.runctx('self._run()', globals(), {'self': self},
                                self._profileName + self.name)
            else:
                self._run()

        except Exception, e:
            self._controlQueue.put_nowait(('JOB', 'EXCEPTION', e))
            trace.traceback()
        except KeyboardInterrupt:
            trace.cc(1, "Ctrl-c occurred in job worker loop")
        except Exception, e:
            trace.cc(1, "EXCEPTION occurred in job worker loop")
            self._controlQueue.put_nowait(('JOB', 'EXCEPTION', e))
            trace.traceback()
        finally:
            # We know the input and out queues are empty or that we're bailing
            # on them, so we cancel_join_thread (don't wait for them to clear)
            self._inputQueue.close()
            self._inputQueue.cancel_join_thread()
            self._outputQueue.close()
            self._outputQueue.cancel_join_thread()
            # We may have put items on the control queue, so we join_thread to
            # make sure what we've put in the pipe is flushed
            self._controlQueue.close()
            self._controlQueue.join_thread()
            trace.cc(1, "TERMINATING")

    def _run(self):
        '''
Exemple #14
0
 def _exception(self, e):
     trace.cc(1, "EXCEPTION -- EXITING JOB...")
     self._send_workers_command('EXIT')
     self._send_output_command('EXIT')
     trace.traceback()
     raise e
Exemple #15
0
    def _survey_lines(self, linesToSurvey, params, measurements, analysis):
        '''
        Analyze file line by line. linesToSurvey is an iterable set of lines.
        Processing is driven by the regular expressions in member variables.
        The order of processing each line is:
             - Preprocess line string
             - Detect machine vs. human code
             - Detect blank lines
             - Detect single and multi-line comments
             - Capture line measures
             - Peform line processing (searches, routines, etc.)
        '''
        # Setup dictionary for measures and searches we'll do
        self._survey_start(params)

        # If no lines to process, we may still want to output empty measures
        if linesToSurvey is None:
            linesToSurvey = []

        # Track whether we are inside a multi-line comment - we ignore nesting
        scanningMultiLine = False

        # Loop through the raw lines we were passed
        for bufferLine in linesToSurvey:
            self.counts['RawLines'][self._activeBlock] += 1
            if self._traceLevel: trace.file(4, "Raw: {0}".format(bufferLine))

            # Allow specializations to skip and/or special-case certain lines
            if self._alternate_line_processing(bufferLine):
                continue

            # If we have a line seperator, apply it
            lines = [bufferLine]
            if self.addLineSep is not None:
                lines = bufferLine.split(self.addLineSep)

            #
            # Read through the lines to measure and process them one at a time
            # This is the main measure loop for csmodules derived from NBNC
            #
            try:
                for rawLine in lines:
                    self.counts['TotalLines'][self._activeBlock] += 1

                    # Allow for clean up of artifacts or other pre-processing
                    line = self._preprocess_line(rawLine)

                    # Detect true blank lines
                    if self.reTrueBlankLine.match(line):
                        self.counts['TrueBlankLines'][self._activeBlock] += 1
                        self._trace_line(line, "T")
                        continue

                    # Block Detection
                    if len(self.blockDetectors) > 1:
                        if self._detect_block_change(line, analysis):
                            scanningMultiLine = False  # Don't allow multi-line comment to span blocks

                    # Determine comment state
                    # This is done before blank lines to make sure we consider multi-line
                    # comment syntax that will be counted as "blank", e.g., /* on it's own line
                    onCommentLine, scanningMultiLine = self._detect_line_comment(line, scanningMultiLine)

                    # Detect "blank" lines with no useful info
                    if self._detect_blank_line(line):
                        continue

                    # Measure and analyze -- overriden in derived classes
                    self._measure_line(line, onCommentLine)
                    self._analyze_line(line, analysis, onCommentLine)

            except Exception, e:
                trace.traceback()
                raise utils.FileMeasureError(
                        "Problem processing line: {0} with module: {1}\n{2}".format(
                        str(sum(self.counts['RawLines'])), self.__class__.__name__, str(e)))
Exemple #16
0
            if self._profileName is not None:
                import cProfile;
                cProfile.runctx('self._run()', globals(), {'self': self}, self._profileName + self.name)
            else:
                self._run()

        except Exception, e:
            self._controlQueue.put_nowait(('JOB', 'EXCEPTION', e))
            trace.traceback()
        except KeyboardInterrupt:
            trace.cc(1, "Ctrl-c occurred in job worker loop")
        except Exception, e:
            trace.cc(1, "EXCEPTION occurred in job worker loop")
            self._controlQueue.put_nowait(('JOB', 'EXCEPTION', e))
            trace.traceback()
        finally:
            # We know the input and out queues are empty or that we're bailing
            # on them, so we cancel_join_thread (don't wait for them to clear)
            self._inputQueue.close()
            self._inputQueue.cancel_join_thread()
            self._outputQueue.close()
            self._outputQueue.cancel_join_thread()
            # We may have put items on the control queue, so we join_thread to
            # make sure what we've put in the pipe is flushed
            self._controlQueue.close()
            self._controlQueue.join_thread()
            trace.cc(1, "TERMINATING")


    def _run(self):
Exemple #17
0
    def _parse_file(self, configFile, configEntries):
        '''
        Parse config file lines
        '''
        configEntry = configentry.ConfigEntry('_ _ _ _')  # Init to empty object to prevent PyChecker warnings
        constants = {}
        readingVerbs = False
        verbEndMarker = None
        for whiteSpaceRawline in configFile:
            trace.config(3, "Config line: {0}".format(whiteSpaceRawline))
            rawLine = whiteSpaceRawline.strip()
            line = rawLine

            # Skip comments, blank lines
            if self.comment.match(line) or self.blankLine.match(line):
                trace.config(4, "comment/blank")
                continue

            # Skip ignore blocks (or go to end of file if no closing block)
            if self.ignoreStart.match(line):
                trace.config(4, "ignoreBlock")
                try:
                    while not self.ignoreStop.match(line):
                        line = configFile.next()
                        trace.config(4, "Config ignore: {0}".format(line))
                except Exception:
                    trace.config(4, "Exception while seeking end of ignore block")
                    pass
                continue

            # Includes
            # Attempt to load the requested file and add it's entries
            # to our entries, in the form INCLUDE:path: tagInfo
            includeMatch = self.include.match(line)
            if includeMatch:
                includePath = includeMatch.group(1)
                newTags = includeMatch.group(2)
                if not os.path.isabs(includePath):
                    includePath = os.path.join(os.path.dirname(configFile.name), includePath)
                trace.config(1, "Include: {0}".format(includePath))
                newEntries = self._read_file(includePath, [])

                existingFileFilterStrings = [entry.fileFilter for entry in configEntries]
                for entry in newEntries:
                    # If an entry has already been defined with the SAME FILE FILTER STRING,
                    # the INCLUDED ENTRY WILL BE IGNORED
                    if entry.fileFilter in existingFileFilterStrings:
                        continue
                    # If 'tagInfo' is provided, it will be added to ALL entries of the file
                    # that was included
                    # We RELOAD THE MODULE in case new options need processed
                    if newTags:
                        entry.add_tags_and_options(newTags.split())
                        self._load_csmodule(entry)
                    configEntries.append(entry)
                continue

            # If line closes out a verb entry store the config entry
            if readingVerbs and re.match(verbEndMarker, line):
                trace.config(4, "verbend: {0}".format(line))
                readingVerbs = False
                configEntries.append(configEntry)
                continue

            # Handle continued lines
            fullLine = ""
            while True:
                contLineMatch = self.continuedLine.match(line)
                if contLineMatch:
                    fullLine += contLineMatch.group(CONT_LINE_START)
                    line = configFile.next().strip()
                    trace.config(3, "FullLine: {0}".format(line))
                else:
                    fullLine += line
                    break
            assert fullLine
            line = fullLine

            # If line defines a normal constant, store asis
            constantMatch = self.constant.match(line)
            if constantMatch:
                # Assign cosntant, strip spaces to support config lines that are space-delimited
                constants[constantMatch.group(1)] = constantMatch.group(2)
                trace.config(2, "Constant: {0}".format(constantMatch.group(2)))
                continue

            # If line defines a no blanks constant, strip spaces and store
            constantMatch = self.constant_noblanks.match(line)
            if constantMatch:
                constants[constantMatch.group(1)] = constantMatch.group(2).replace(' ', '')
                trace.config(2, "Noblank constant: {0}".format(constantMatch.group(2)))
                continue

            # Replace any constants used in the line
            line = self._replace_constants(line, constants)
            trace.config(4, "fullline: {0}".format(line))

            # Strip any inline comments
            line = line.split(' #')[0]

            # If the line is a parameter (e.g., search terms), delegate to module
            # to get processed parameters and store for later usage
            # We keep the unprocessed raw version around for consistency checking
            if readingVerbs:
                configEntry.paramsRaw.append(rawLine)
                try:
                    paramTuple = configEntry.module.add_param(line, rawLine)
                    configEntry.paramsProcessed.append(paramTuple)
                    trace.config(2, "LoadedParam: {0} => {1}".format(
                            configEntry.module.__class__.__name__, paramTuple))
                except Exception, e:
                    trace.traceback()
                    raise utils.ConfigError(uistrings.STR_ErrorConfigParam.format(
                            str(configEntry), rawLine, str(e)))

            # Otherwise assume we're at the start of a config entry definition,
            else:
                try:
                    # Load and validate the config line and its module
                    configEntry = configentry.ConfigEntry(line, self._extraLineContent, configFile.name)
                    self._load_csmodule(configEntry)
                    self._validate_line(configEntry)

                    # Check to see if there are parameter lines to read
                    verbEndMarker = configEntry.module.verb_end_marker(configEntry.verb)
                    if verbEndMarker is not None:
                        readingVerbs = True

                    # Add the completed config entry to our list
                    if not readingVerbs:
                        configEntries.append(configEntry)

                except Exception, e:
                    trace.traceback()
                    raise utils.ConfigError(uistrings.STR_ErrorConfigEntry.format(
                            rawLine, str(e)))