timeit

Програмиране с Python

Курс във Факултета по Математика и Информатика към СУ

Решение на Статичен анализ на python код от Ивелин Тодоров

Обратно към всички решения

Към профила на Ивелин Тодоров

Резултати

  • 3 точки от тестове
  • 0 бонус точки
  • 3 точки общо
  • 3 успешни тест(а)
  • 8 неуспешни тест(а)

Код

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
import ast
import inspect
from collections import defaultdict


MESSAGES = {
    'line_length': 'line too long ({} > {})',
    'forbid_semicolons': 'multiple expressions on the same line',
    'max_nesting': 'nesting too deep ({} > {})',
    'indentation_size': 'indentation is {} instead of {}',
    'methods_per_class': 'too many methods in class({} > {})',
    'max_arity': 'too many arguments({} > {})',
    'forbid_trailing_whitespace': 'trailing whitespace',
    'max_lines_per_function': 'method with too many lines ({} > {})'
}


DEFAULTS = {
    'line_length': 79,
    'forbid_semicolons': True,
    'max_nesting': None,
    'indentation_size': 4,
    'methods_per_class': None,
    'max_arity': None,
    'forbid_trailing_whitespace': True,
    'max_lines_per_function': None
}


ERRORS = defaultdict(set)


def check_line_len(code, limit):
    current_len = 0
    current_line = 1
    print(len(code))
    for ind, char in enumerate(code):
        if char != '\n':
            current_len += 1
        elif current_len >= limit:
            ERRORS[current_line].add(MESSAGES['line_length']
            .format(current_line, DEFAULTS['line_length']))
            current_len = 0
        else:
            current_line += 1
        if ind == len(code) - 1 and current_len >= limit:
            ERRORS[current_line].add(MESSAGES['line_length']
                          .format(current_len, DEFAULTS['line_length']))
            current_len = 0
            current_line += 1
    #return ERRORS


def check_for_semicolons(code, forbidden):
    current_line = 1
    OFF = False
    for ind in code:
        if ind == '"' or ind == "'":
            True if not OFF else False
        elif not OFF:
            if ind == ';':
                ERRORS[current_line].add(MESSAGES['forbid_semicolons'])
            if ind == '\n':
                current_line += 1
    #return ERRORS


def check_nesting(code, max_nesting):
    current_max = 1
    indent_size = DEFAULTS['indentation_size']
    lines = code.split('\n')
    for ind, line in enumerate(lines):
        count_spaces = 0
        for char in line:
            if char == ' ':
                count_spaces += 1
            else:
                break
        if count_spaces % indent_size == 0:
            if count_spaces // indent_size > current_max:
                current_max = count_spaces // indent_size
                if current_max > max_nesting:
                    ERRORS[ind + 1].add(MESSAGES['max_nesting'] \
                    .format(current_max, max_nesting))


def check_indent(code, indentation_size):
    pass


def critic(code, **rules):
    DEFAULTS.update(rules)
    check_line_len(code, DEFAULTS['line_length'])
    check_for_semicolons(code, DEFAULTS['forbid_semicolons'])
    check_nesting(code, DEFAULTS['max_nesting'])
    return ERRORS

Лог от изпълнението

FFF.FFF.FF.
======================================================================
FAIL: test_dict_nesting (test.TestCritic)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/data/rails/pyfmi-2016/releases/20160307095126/lib/language/python/runner.py", line 67, in thread
    raise result
AssertionError: 2 != 0

======================================================================
FAIL: test_forbid_trailing_whitespace (test.TestCritic)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/data/rails/pyfmi-2016/releases/20160307095126/lib/language/python/runner.py", line 67, in thread
    raise result
AssertionError: 0 != 1

======================================================================
FAIL: test_indentation (test.TestCritic)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/data/rails/pyfmi-2016/releases/20160307095126/lib/language/python/runner.py", line 67, in thread
    raise result
AssertionError: 0 != 1

======================================================================
FAIL: test_long_line_with_several_statements (test.TestCritic)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/data/rails/pyfmi-2016/releases/20160307095126/lib/language/python/runner.py", line 67, in thread
    raise result
AssertionError: Items in the first set but not the second:
'line too long (132 > 79)'
Items in the second set but not the first:
'line too long (116 > 79)'

======================================================================
FAIL: test_max_lines_per_function (test.TestCritic)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/data/rails/pyfmi-2016/releases/20160307095126/lib/language/python/runner.py", line 67, in thread
    raise result
AssertionError: Items in the second set but not the first:
'method with too many lines (6 > 3)'

======================================================================
FAIL: test_multiple_issues_all_over_the_place (test.TestCritic)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/data/rails/pyfmi-2016/releases/20160307095126/lib/language/python/runner.py", line 67, in thread
    raise result
AssertionError: 6 != 5

======================================================================
FAIL: test_too_deep_nesting (test.TestCritic)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/data/rails/pyfmi-2016/releases/20160307095126/lib/language/python/runner.py", line 67, in thread
    raise result
AssertionError: 2 != 1

======================================================================
FAIL: test_too_many_arguments (test.TestCritic)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/data/rails/pyfmi-2016/releases/20160307095126/lib/language/python/runner.py", line 67, in thread
    raise result
AssertionError: 0 != 1

----------------------------------------------------------------------
Ran 11 tests in 0.136s

FAILED (failures=8)

История (1 версия и 0 коментара)

Ивелин обнови решението на 18.05.2016 16:39 (преди над 1 година)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
import ast
import inspect
from collections import defaultdict


MESSAGES = {
    'line_length': 'line too long ({} > {})',
    'forbid_semicolons': 'multiple expressions on the same line',
    'max_nesting': 'nesting too deep ({} > {})',
    'indentation_size': 'indentation is {} instead of {}',
    'methods_per_class': 'too many methods in class({} > {})',
    'max_arity': 'too many arguments({} > {})',
    'forbid_trailing_whitespace': 'trailing whitespace',
    'max_lines_per_function': 'method with too many lines ({} > {})'
}


DEFAULTS = {
    'line_length': 79,
    'forbid_semicolons': True,
    'max_nesting': None,
    'indentation_size': 4,
    'methods_per_class': None,
    'max_arity': None,
    'forbid_trailing_whitespace': True,
    'max_lines_per_function': None
}


ERRORS = defaultdict(set)


def check_line_len(code, limit):
    current_len = 0
    current_line = 1
    print(len(code))
    for ind, char in enumerate(code):
        if char != '\n':
            current_len += 1
        elif current_len >= limit:
            ERRORS[current_line].add(MESSAGES['line_length']
            .format(current_line, DEFAULTS['line_length']))
            current_len = 0
        else:
            current_line += 1
        if ind == len(code) - 1 and current_len >= limit:
            ERRORS[current_line].add(MESSAGES['line_length']
                          .format(current_len, DEFAULTS['line_length']))
            current_len = 0
            current_line += 1
    #return ERRORS


def check_for_semicolons(code, forbidden):
    current_line = 1
    OFF = False
    for ind in code:
        if ind == '"' or ind == "'":
            True if not OFF else False
        elif not OFF:
            if ind == ';':
                ERRORS[current_line].add(MESSAGES['forbid_semicolons'])
            if ind == '\n':
                current_line += 1
    #return ERRORS


def check_nesting(code, max_nesting):
    current_max = 1
    indent_size = DEFAULTS['indentation_size']
    lines = code.split('\n')
    for ind, line in enumerate(lines):
        count_spaces = 0
        for char in line:
            if char == ' ':
                count_spaces += 1
            else:
                break
        if count_spaces % indent_size == 0:
            if count_spaces // indent_size > current_max:
                current_max = count_spaces // indent_size
                if current_max > max_nesting:
                    ERRORS[ind + 1].add(MESSAGES['max_nesting'] \
                    .format(current_max, max_nesting))


def check_indent(code, indentation_size):
    pass


def critic(code, **rules):
    DEFAULTS.update(rules)
    check_line_len(code, DEFAULTS['line_length'])
    check_for_semicolons(code, DEFAULTS['forbid_semicolons'])
    check_nesting(code, DEFAULTS['max_nesting'])
    return ERRORS