Package buildbot :: Package steps :: Module python
[frames] | no frames]

Source Code for Module buildbot.steps.python

  1   
  2  from buildbot.status.builder import SUCCESS, FAILURE, WARNINGS 
  3  from buildbot.steps.shell import ShellCommand 
  4  import re 
  5   
  6  try: 
  7      import cStringIO 
  8      StringIO = cStringIO.StringIO 
  9  except ImportError: 
 10      from StringIO import StringIO 
 11   
 12   
13 -class BuildEPYDoc(ShellCommand):
14 name = "epydoc" 15 command = ["make", "epydocs"] 16 description = ["building", "epydocs"] 17 descriptionDone = ["epydoc"] 18
19 - def createSummary(self, log):
20 import_errors = 0 21 warnings = 0 22 errors = 0 23 24 for line in StringIO(log.getText()): 25 if line.startswith("Error importing "): 26 import_errors += 1 27 if line.find("Warning: ") != -1: 28 warnings += 1 29 if line.find("Error: ") != -1: 30 errors += 1 31 32 self.descriptionDone = self.descriptionDone[:] 33 if import_errors: 34 self.descriptionDone.append("ierr=%d" % import_errors) 35 if warnings: 36 self.descriptionDone.append("warn=%d" % warnings) 37 if errors: 38 self.descriptionDone.append("err=%d" % errors) 39 40 self.import_errors = import_errors 41 self.warnings = warnings 42 self.errors = errors
43
44 - def evaluateCommand(self, cmd):
45 if cmd.rc != 0: 46 return FAILURE 47 if self.warnings or self.errors: 48 return WARNINGS 49 return SUCCESS
50 51
52 -class PyFlakes(ShellCommand):
53 name = "pyflakes" 54 command = ["make", "pyflakes"] 55 description = ["running", "pyflakes"] 56 descriptionDone = ["pyflakes"] 57 flunkOnFailure = False 58 flunkingIssues = ["undefined"] # any pyflakes lines like this cause FAILURE 59 60 MESSAGES = ("unused", "undefined", "redefs", "import*", "misc") 61
62 - def createSummary(self, log):
63 counts = {} 64 summaries = {} 65 for m in self.MESSAGES: 66 counts[m] = 0 67 summaries[m] = [] 68 69 first = True 70 for line in StringIO(log.getText()).readlines(): 71 # the first few lines might contain echoed commands from a 'make 72 # pyflakes' step, so don't count these as warnings. Stop ignoring 73 # the initial lines as soon as we see one with a colon. 74 if first: 75 if line.find(":") != -1: 76 # there's the colon, this is the first real line 77 first = False 78 # fall through and parse the line 79 else: 80 # skip this line, keep skipping non-colon lines 81 continue 82 if line.find("imported but unused") != -1: 83 m = "unused" 84 elif line.find("*' used; unable to detect undefined names") != -1: 85 m = "import*" 86 elif line.find("undefined name") != -1: 87 m = "undefined" 88 elif line.find("redefinition of unused") != -1: 89 m = "redefs" 90 else: 91 m = "misc" 92 summaries[m].append(line) 93 counts[m] += 1 94 95 self.descriptionDone = self.descriptionDone[:] 96 for m in self.MESSAGES: 97 if counts[m]: 98 self.descriptionDone.append("%s=%d" % (m, counts[m])) 99 self.addCompleteLog(m, "".join(summaries[m])) 100 self.setProperty("pyflakes-%s" % m, counts[m], "pyflakes") 101 self.setProperty("pyflakes-total", sum(counts.values()), "pyflakes")
102 103
104 - def evaluateCommand(self, cmd):
105 if cmd.rc != 0: 106 return FAILURE 107 for m in self.flunkingIssues: 108 if self.getProperty("pyflakes-%s" % m): 109 return FAILURE 110 if self.getProperty("pyflakes-total"): 111 return WARNINGS 112 return SUCCESS
113
114 -class PyLint(ShellCommand):
115 '''A command that knows about pylint output. 116 It's a good idea to add --output-format=parseable to your 117 command, since it includes the filename in the message. 118 ''' 119 name = "pylint" 120 description = ["running", "pylint"] 121 descriptionDone = ["pylint"] 122 123 # Using the default text output, the message format is : 124 # MESSAGE_TYPE: LINE_NUM:[OBJECT:] MESSAGE 125 # with --output-format=parseable it is: (the outer brackets are literal) 126 # FILE_NAME:LINE_NUM: [MESSAGE_TYPE[, OBJECT]] MESSAGE 127 # message type consists of the type char and 4 digits 128 # The message types: 129 130 MESSAGES = { 131 'C': "convention", # for programming standard violation 132 'R': "refactor", # for bad code smell 133 'W': "warning", # for python specific problems 134 'E': "error", # for much probably bugs in the code 135 'F': "fatal", # error prevented pylint from further processing. 136 'I': "info", 137 } 138 139 flunkingIssues = ["F", "E"] # msg categories that cause FAILURE 140 141 _re_groupname = 'errtype' 142 _msgtypes_re_str = '(?P<%s>[%s])' % (_re_groupname, ''.join(MESSAGES.keys())) 143 _default_line_re = re.compile(r'%s\d{4}: *\d+:.+' % _msgtypes_re_str) 144 _parseable_line_re = re.compile(r'[^:]+:\d+: \[%s\d{4}[,\]] .+' % _msgtypes_re_str) 145
146 - def createSummary(self, log):
147 counts = {} 148 summaries = {} 149 for m in self.MESSAGES: 150 counts[m] = 0 151 summaries[m] = [] 152 153 line_re = None # decide after first match 154 for line in StringIO(log.getText()).readlines(): 155 if not line_re: 156 # need to test both and then decide on one 157 if self._parseable_line_re.match(line): 158 line_re = self._parseable_line_re 159 elif self._default_line_re.match(line): 160 line_re = self._default_line_re 161 else: # no match yet 162 continue 163 mo = line_re.match(line) 164 if mo: 165 msgtype = mo.group(self._re_groupname) 166 assert msgtype in self.MESSAGES 167 summaries[msgtype].append(line) 168 counts[msgtype] += 1 169 170 self.descriptionDone = self.descriptionDone[:] 171 for msg, fullmsg in self.MESSAGES.items(): 172 if counts[msg]: 173 self.descriptionDone.append("%s=%d" % (fullmsg, counts[msg])) 174 self.addCompleteLog(fullmsg, "".join(summaries[msg])) 175 self.setProperty("pylint-%s" % fullmsg, counts[msg]) 176 self.setProperty("pylint-total", sum(counts.values()))
177
178 - def evaluateCommand(self, cmd):
179 if cmd.rc != 0: 180 return FAILURE 181 for msg in self.flunkingIssues: 182 if self.getProperty("pylint-%s" % self.MESSAGES[msg]): 183 return FAILURE 184 if self.getProperty("pylint-total"): 185 return WARNINGS 186 return SUCCESS
187