source: pycodebattler/trunk/pycodebattler/score.py @ 45

Revision 45, 3.0 KB checked in by atzm, 13 years ago (diff)

add pycodebattler

Line 
1# -*- coding: utf-8 -*-
2# $Id: b671038756c9b47b724ae8e4909592194fc0b0b4 $
3
4import os
5import sys
6import token
7import parser
8
9import cc
10import pep8
11
12
13class Scorer:
14    def __init__(self, lines):
15        self._lines = lines
16        self._lnum = len(lines)
17        self._code = ''.join(lines)
18        self._bytes = len(self._code)
19
20        self._nlines = [l for l in lines if not l.strip().startswith('#')]
21        self._nlnum = len(self._nlines)
22        self._nbytes = sum(len(l) for l in self._nlines)
23
24        self._st = parser.suite(self._code)
25        self._p8c = self._pep8count()
26        self._cpsum, self._cplen = self._complexity()
27
28    def _complexity(self, item='all'):
29        try:
30            stat = cc.measure_complexity(self._code, item)
31            ccpp = cc.PrettyPrinter(None, True)
32            cplx = zip(*ccpp.flatten_stats(stat))[-1]
33            return sum(cplx) + 1, len(cplx) + 1
34        except:
35            return 256, 1
36
37    def _pep8count(self, name=''):
38        pep8.process_options([name])
39        p8ck = pep8.Checker(None)
40        p8ck.lines = self._lines
41        p8ck.filename = name
42
43        try:
44            tmpfp = sys.stdout
45            sys.stdout = open(os.devnull, 'w')
46
47            try:  # nest for 2.4 or earlier
48                return p8ck.check_all() + 1
49            except:
50                return 256
51        finally:
52            sys.stdout = tmpfp
53
54    def _parsebytes(self, types):
55        def litbytes(stp, bytes=0):
56            if not stp:
57                return bytes
58            if stp[0] in types:
59                bytes += len(stp[1])
60            else:
61                for p in stp[1:]:
62                    bytes = litbytes(p, bytes)
63            return bytes
64        return litbytes(self._st.totuple())
65
66    @staticmethod
67    def _strlen_max(seq, iferr=0):
68        try:
69            return max(len(l) for l in seq)
70        except:
71            return iferr
72
73    def pep8_score(self):
74        bytes = self._nbytes - self._parsebytes(
75            [token.NUMBER, token.STRING, token.NAME, token.COLON])
76        return (bytes / ((self._nlnum / 256) + 1) / self._p8c) + 1
77
78    def complex_score(self):
79        bmax = self._strlen_max(self._lines, 256)
80        return (32 * self._cplen / ((bmax / 79) + 1) / \
81                ((self._cpsum / 12) + 1)) + 1
82
83    def lines_score(self):
84        bmax = self._strlen_max(self._lines, 256)
85        bytes = self._nbytes - self._parsebytes(
86            [token.NUMBER, token.STRING, token.NAME, token.COLON])
87        return (bytes / ((bmax / (self._nlnum + 1)) + 1) / \
88                (self._nlnum + 1)) + 1
89
90    def const_score(self):
91        cbytes = self._parsebytes([token.NUMBER, token.STRING]) + 1
92        return (self._nbytes + 1) // cbytes
93
94    def colon_score(self):
95        bytes = self._nbytes + 1
96        cbytes = self._parsebytes([token.COLON]) + 1
97        return (bytes // ((bytes // cbytes) + 1)) + 1
98
99    def name_score(self):
100        bytes = self._nbytes + 1
101        nbytes = self._parsebytes([token.NAME]) + 1
102        return bytes // ((nbytes / 16) + 1)
Note: See TracBrowser for help on using the repository browser.