__init__.py #1

  • //
  • guest/
  • matthew_janulewicz/
  • p4spam-1.1/
  • pylib/
  • p4spam/
  • perforce/
  • commands/
  • __init__.py
  • View
  • Commits
  • Open Download .zip Download (5 KB)
##
## Copyright (c) 2006 Jason Dillon
##
## Licensed under the Apache License, Version 2.0 (the "License");
## you may not use this file except in compliance with the License.
## You may obtain a copy of the License at
##
##     http://www.apache.org/licenses/LICENSE-2.0
##
## Unless required by applicable law or agreed to in writing, software
## distributed under the License is distributed on an "AS IS" BASIS,
## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
## See the License for the specific language governing permissions and
## limitations under the License.
##

##
## $Id: __init__.py 78 2009-08-25 12:21:04Z mindwanderer $
##

import os, sys, popen2, marshal

from p4spam import log, config

# Logger for the create() factory method
_log = log.getLogger("p4spam.perforce.commands")

def create(name, p4):
    assert name != None
    
    try:
        mod_name = "p4spam.perforce.commands.%s" % name
        _log.debug("Loading: %s" % mod_name)
        mod = __import__(mod_name, globals(), locals(), [ "create" ])
        assert mod != None
        _log.debug("Loaded: %s" % mod)
    
    except ImportError:
        raise Exception("Unconfigured command: %s" % name)
    
    factory = getattr(mod, "create")
    _log.debug("Factory: %s" % factory)
    
    return factory(p4);

##
## ResultSupport
##

class ResultSupport:
    def toString(this):
        raise "Abstract method"
    
    def __str__(this):
        return this.toString()
    
    def __repr__(this):
        return this.toString()

##
## CommandSupport
##

class CommandSupport:
    def __init__(this, name, p4):
        this.log = log.getLogger(this)
        
        this.name = name
        this.p4 = p4
        this.p4flags = "-G"
        this.pipeMode = 'b'
    
    def createCommandLine(this, args):
        cmdline = []
        
        for arg in config.P4_CMDLINE:
            cmdline.append(str(arg))
        
        if this.p4flags != None and len(this.p4flags.strip()) != 0:
            cmdline.append(this.p4flags)
        
        # Only append command name if this is not a special raw command
        if this.name not in ("raw", "rawstream"):
            cmdline.append(this.name)
        
        for arg in args:
            cmdline.append(str(arg))
        
        # If this is not a posix system, then need to convert cmdline to a string
        if os.name != 'posix':
            buff = cmdline[0] # don't quote
            for arg in cmdline[1:]:
                buff = '%s "%s"' % (buff, str(arg))
            cmdline = buff
            this.log.debug("Converted cmdline sequence into string for non-posix os: %s" % cmdline)
        
        return cmdline
    
    def processOutput(this, stream):
        raise "Abstract method"
    
    def execute(this, args):
        cmdline = this.createCommandLine(args)
        
        this.log.debug("Executing: %s" % str(cmdline))
        (fromchild, tochild, childerr) = popen2.popen3(cmdline, mode=this.pipeMode )
        
        # Try and detect early failure if anything has been written to the childs stderr
        #
        # NOTE: This is less than ideal, as the errors might not have poped out yet
        #
        #errors = childerr.readlines()
        #if len(errors):
        #    for line in errors:
        #        this.log.error(line)
        #    
        #    raise "Child process spat out some errors: %s" % str(errors)
        
        result = this.processOutput(fromchild)
        this.log.debug("Result: %s" % result)
        
        return result

##
## SingleResultCommand
##

class SingleResultCommand(CommandSupport):
    def createResult(this, entry):
        raise "Abstract method"
    
    def processOutput(this, stream):
        entry = marshal.load(stream)
        assert entry != None
        
        this.log.debug("Entry: %s" % entry)
        
        return this.createResult(entry)

##
## RawResultCommand
##

class RawResultCommand(SingleResultCommand):
    def __init__(this, name, p4):
        SingleResultCommand.__init__(this, name, p4)
        this.p4flags = "" # Clear the -G flag
        this.pipeMode = 't'
    
    def isValid(this, lines):
        return True
    
    def validate(this, lines):
        if not this.isValid(lines):
            raise Exception("Raw content does not look like output from `p4 %s`: %s" % (this.name, lines))
    
    def processOutput(this, stream):
        lines = stream.readlines()
        
        for line in lines:
            this.log.debug(line.rstrip())
        
        this.validate(lines)
        
        return lines

##
## StreamedResultCommand
##

class StreamedResultCommand(CommandSupport):
    def createResult(this, entry):
        raise "Abstract method"
    
    def processOutput(this, stream):
        return StreamedResultIterator(stream, this)

##
## StreamedResultIterator
##

class StreamedResultIterator:
    def __init__(this, stream, resultFactory):
        this.log = log.getLogger(this)
        this.stream = stream
        this.resultFactory = resultFactory
    
    def __iter__(this):
        return this
   
    def next(this):
        try:
            entry = marshal.load(this.stream)
            assert entry != None
            
            this.log.debug("Entry: %s" % entry)
            
            return this.resultFactory.createResult(entry)
        
        except EOFError:
            raise StopIteration

# Change User Description Committed
#1 7731 Matthew Janulewicz Adding P4Spam 1.1 code from http://p4spam.sourceforge.net/wiki/Main_Page

"P4Spam is a Perforce change review daemon which spits out sexy HTML-styled notification emails."