timeit

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

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

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

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

Към профила на Веселин Иванов

Резултати

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

Код

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
97
98
99
100
101
102
103
104
105
106
107
108
109
import ast


def check_line_length(line, max_line_length=79):
    line_length = len(line)
    if line_length > max_line_length:
        return 'line too long ({} > {})'.format(line_length, max_line_length)


def _find_quotes(stripped_line):
    in_quote = False
    start_index = -1
    quotes = []
    for idx, ch in enumerate(stripped_line):
        if ch == '"' or ch == "'":
            if not in_quote:
                in_quote = True
                start_index = idx
            else:
                in_quote = False  # some comment;
                quotes.append((start_index, idx))

    return quotes


def _in_quotes(quotes, index):
    for start, end in quotes:
        if index > start and index < end:
            return True

    return False


def check_forbid_semicolons(line, forbid_semicolons=True):
    if not forbid_semicolons:
        return

    stripped = line.strip()
    if stripped.startswith('#'):
        return

    comment_index = stripped.find('#')
    quotes = _find_quotes(stripped)

    semicolon_index = stripped.find(';')
    if semicolon_index == -1:
        return
    elif comment_index != -1 and semicolon_index > comment_index:
        return
    elif _in_quotes(quotes, semicolon_index):
        return
    else:
        return 'multiple expressions on the same line'


def check_forbid_trailing_whitespace(line, forbid_trailing_whitespace=True):
    if not forbid_trailing_whitespace:
        return

    if line == '':
        return  # doesn't apply for empty line

    if line[-1].isspace():
        return 'trailing whitespace'


class FuncExtractor(ast.NodeVisitor):
    funcs = []

    def visit_FunctionDef(self, node):
        self.funcs.append(node)
        self.generic_visit(node)

    def extract(self, node):
        self.visit(node)


def check_max_arity(tree, max_arity=None):
    if not max_arity:
        return

    extractor = FuncExtractor()
    extractor.extract()


LINE_CHECKS = {'line_length': check_line_length,
               'forbid_semicolons': check_forbid_semicolons,
               'forbid_trailing_whitespace': check_forbid_trailing_whitespace}
AST_CHECKS = {'max_arity', check_max_arity}


def critic(code, **rules):
    lines = code.splitlines()
    result = {}
    for line_number, line in enumerate(lines, 1):
        for rule, func in LINE_CHECKS.items():
            ret_value = None
            if rule in rules:
                ret_value = func(line, rules[rule])
            else:
                ret_value = func(line)
            if ret_value:
                if line_number in result:
                    result[line_number].add(ret_value)
                else:
                    result[line_number] = set()
                    result[line_number].add(ret_value)

    return result

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

..F..FF.FF.
======================================================================
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_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: 0 != 1

======================================================================
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: 3 != 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: 0 != 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.098s

FAILED (failures=5)

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

Веселин обнови решението на 18.05.2016 16:58 (преди над 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
97
98
99
100
101
102
103
104
105
106
107
108
109
import ast


def check_line_length(line, max_line_length=79):
    line_length = len(line)
    if line_length > max_line_length:
        return 'line too long ({} > {})'.format(line_length, max_line_length)


def _find_quotes(stripped_line):
    in_quote = False
    start_index = -1
    quotes = []
    for idx, ch in enumerate(stripped_line):
        if ch == '"' or ch == "'":
            if not in_quote:
                in_quote = True
                start_index = idx
            else:
                in_quote = False  # some comment;
                quotes.append((start_index, idx))

    return quotes


def _in_quotes(quotes, index):
    for start, end in quotes:
        if index > start and index < end:
            return True

    return False


def check_forbid_semicolons(line, forbid_semicolons=True):
    if not forbid_semicolons:
        return

    stripped = line.strip()
    if stripped.startswith('#'):
        return

    comment_index = stripped.find('#')
    quotes = _find_quotes(stripped)

    semicolon_index = stripped.find(';')
    if semicolon_index == -1:
        return
    elif comment_index != -1 and semicolon_index > comment_index:
        return
    elif _in_quotes(quotes, semicolon_index):
        return
    else:
        return 'multiple expressions on the same line'


def check_forbid_trailing_whitespace(line, forbid_trailing_whitespace=True):
    if not forbid_trailing_whitespace:
        return

    if line == '':
        return  # doesn't apply for empty line

    if line[-1].isspace():
        return 'trailing whitespace'


class FuncExtractor(ast.NodeVisitor):
    funcs = []

    def visit_FunctionDef(self, node):
        self.funcs.append(node)
        self.generic_visit(node)

    def extract(self, node):
        self.visit(node)


def check_max_arity(tree, max_arity=None):
    if not max_arity:
        return

    extractor = FuncExtractor()
    extractor.extract()


LINE_CHECKS = {'line_length': check_line_length,
               'forbid_semicolons': check_forbid_semicolons,
               'forbid_trailing_whitespace': check_forbid_trailing_whitespace}
AST_CHECKS = {'max_arity', check_max_arity}


def critic(code, **rules):
    lines = code.splitlines()
    result = {}
    for line_number, line in enumerate(lines, 1):
        for rule, func in LINE_CHECKS.items():
            ret_value = None
            if rule in rules:
                ret_value = func(line, rules[rule])
            else:
                ret_value = func(line)
            if ret_value:
                if line_number in result:
                    result[line_number].add(ret_value)
                else:
                    result[line_number] = set()
                    result[line_number].add(ret_value)

    return result