timeit

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

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

Решение на Статичен анализ на python код от Александрина Ламбова

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

Към профила на Александрина Ламбова

Резултати

  • 9 точки от тестове
  • 0 бонус точки
  • 9 точки общо
  • 10 успешни тест(а)
  • 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
import ast


def update(critics, line, mess):
    if line not in critics:
        critics[line] = set()
    critics[line].add(mess)
    return critics


def analysis(node, nesting, indentation, rules, used_lines, critics):
    if rules['forbid_semicolons'] and node.lineno in used_lines:
        critics = update(
            critics, node.lineno, 'multiple expressions on the same line')
    else:
        used_lines.add(node.lineno)
        if node.col_offset != indentation:
            critics = update(
                critics, node.lineno, 'indentation is {} instead of {}'.format(
                    node.col_offset, indentation))
    if rules['max_nesting'] and nesting > rules['max_nesting']:
        critics = update(
            critics, node.lineno, 'nesting too deep ({} > {})'.format(
                nesting, rules['max_nesting']))
    if isinstance(node, ast.Expr) or isinstance(
            node, ast.Expression) or not hasattr(node, 'body'):
        return (1, used_lines, critics)
    sum_lines = 0
    count_methods = 0
    for child in node.body:
        lines, used_lines, critics = analysis(
            child, nesting + 1,
            indentation + rules['indentation_size'],
            rules, used_lines, critics)
        sum_lines += lines
        if isinstance(child, ast.FunctionDef):
            count_methods += 1
    if hasattr(node, 'orelse'):
        for child in node.orelse:
            lines, used_lines, critics = analysis(
                child, nesting + 1,
                indentation + rules['indentation_size'],
                rules, used_lines, critics)
            sum_lines += lines
    if rules['methods_per_class'] and isinstance(
            node, ast.ClassDef) and count_methods > rules['methods_per_class']:
        critics = update(
            critics, node.lineno, 'too many methods in class({} > {})'.format(
                count_methods, rules['methods_per_class']))
    if rules['max_lines_per_function'] and isinstance(
            node, ast.FunctionDef) and sum_lines > rules[
                'max_lines_per_function']:
        critics = update(
            critics, node.lineno,
            'method with too many lines ({} > {})'.format(
                sum_lines, rules['max_lines_per_function']))
    if rules['max_arity'] and isinstance(
            node, ast.FunctionDef):
        count = len(node.args.args) + len(node.args.kwonlyargs)
        if node.args.vararg:
            count += 1
        if node.args.kwarg:
            count += 1
        if count > rules['max_arity']:
            critics = update(
                critics, node.lineno, 'too many arguments({} > {})'.format(
                    count, rules['max_arity']))
    return (sum_lines + 1, used_lines, critics)


def default_rules(rules):
    if 'line_length' not in rules:
        rules['line_length'] = 79
    if 'forbid_semicolons' not in rules:
        rules['forbid_semicolons'] = True
    if 'max_nesting' not in rules:
        rules['max_nesting'] = None
    if 'indentation_size' not in rules:
        rules['indentation_size'] = 4
    if 'methods_per_class' not in rules:
        rules['methods_per_class'] = None
    if 'max_arity' not in rules:
        rules['max_arity'] = None
    if 'forbid_trailing_whitespace' not in rules:
        rules['forbid_trailing_whitespace'] = True
    if 'max_lines_per_function' not in rules:
        rules['max_lines_per_function'] = None
    return rules


def critic(code, **rules):
    tree = ast.parse(code)
    rules = default_rules(rules)
    lines = code.split("\n")
    critics = {}
    used_lines = set()
    for i in range(0, len(lines)):
        if len(lines[i]) > rules['line_length']:
            critics = update(
                critics, i+1, 'line too long ({} > {})'.format(
                    len(lines[i]), rules['line_length']))
        if rules['forbid_trailing_whitespace'] and lines[i].endswith(' '):
            critics = update(
                critics, i+1, 'trailing whitespace')
    for node in tree.body:
        sth, used_lines, critics = analysis(
            node, 0, 0, rules, used_lines, critics)
    return critics

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

......F....
======================================================================
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: Items in the first set but not the second:
'method with too many lines (13 > 5)'

----------------------------------------------------------------------
Ran 11 tests in 0.107s

FAILED (failures=1)

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

Александрина обнови решението на 17.05.2016 23:57 (преди над 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
import ast


def update(critics, line, mess):
    if line not in critics:
        critics[line] = set()
    critics[line].add(mess)
    return critics


def analysis(node, nesting, indentation, rules, used_lines, critics):
    if rules['forbid_semicolons'] and node.lineno in used_lines:
        critics = update(
            critics, node.lineno, 'multiple expressions on the same line')
    else:
        used_lines.add(node.lineno)
        if node.col_offset != indentation:
            critics = update(
                critics, node.lineno, 'indentation is {} instead of {}'.format(
                    node.col_offset, indentation))
    if rules['max_nesting'] and nesting > rules['max_nesting']:
        critics = update(
            critics, node.lineno, 'nesting too deep ({} > {})'.format(
                nesting, rules['max_nesting']))
    if isinstance(node, ast.Expr) or isinstance(
            node, ast.Expression) or not hasattr(node, 'body'):
        return (1, used_lines, critics)
    sum_lines = 0
    count_methods = 0
    for child in node.body:
        lines, used_lines, critics = analysis(
            child, nesting + 1,
            indentation + rules['indentation_size'],
            rules, used_lines, critics)
        sum_lines += lines
        if isinstance(child, ast.FunctionDef):
            count_methods += 1
    if hasattr(node, 'orelse'):
        for child in node.orelse:
            lines, used_lines, critics = analysis(
                child, nesting + 1,
                indentation + rules['identation_size'],
                rules, used_lines, critics)
            sum_lines += lines
    if rules['methods_per_class'] and isinstance(
            node, ast.ClassDef) and count_methods > rules['methods_per_class']:
        critics = update(
            critics, node.lineno, 'too many methods in class({} > {})'.format(
                count_methods, rules['methods_per_class']))
    if rules['max_lines_per_function'] and isinstance(
            node, ast.FunctionDef) and sum_lines > rules[
                'max_lines_per_function']:
        critics = update(
            critics, node.lineno,
            'method with too many lines ({} > {})'.format(
                sum_lines, rules['max_lines_per_function']))
    if rules['max_arity'] and isinstance(
            node, ast.FunctionDef):
        count = len(node.args.args) + len(node.args.kwonlyargs)
        if node.args.vararg:
            count += 1
        if node.args.kwarg:
            count += 1
        if count > rules['max_arity']:
            critics = update(
                critics, node.lineno, 'too many arguments({} > {})'.format(
                    count, rules['max_arity']))
    return (sum_lines + 1, used_lines, critics)


def default_rules(rules):
    if 'line_length' not in rules:
        rules['line_length'] = 79
    if 'forbid_semicolons' not in rules:
        rules['forbid_semicolons'] = True
    if 'max_nesting' not in rules:
        rules['max_nesting'] = None
    if 'indentation_size' not in rules:
        rules['indentation_size'] = 4
    if 'methods_per_class' not in rules:
        rules['methods_per_class'] = None
    if 'max_arity' not in rules:
        rules['max_arity'] = None
    if 'forbid_trailing_whitespace' not in rules:
        rules['forbid_trailing_whitespace'] = True
    if 'max_lines_per_function' not in rules:
        rules['max_lines_per_function'] = None
    return rules


def critic(code, **rules):
    tree = ast.parse(code)
    rules = default_rules(rules)
    lines = code.split("\n")
    critics = {}
    used_lines = set()
    for i in range(0, len(lines)):
        if len(lines[i]) > rules['line_length']:
            critics = update(
                critics, i+1, 'line too long ({} > {})'.format(
                    len(lines[i]), rules['line_length']))
        if rules['forbid_trailing_whitespace'] and lines[i].endswith(' '):
            critics = update(
                critics, i+1, 'trailing whitespace')
    for node in tree.body:
        critics = (analysis(
            node, 0, 0, rules, used_lines, critics))[2]
    return critics

Александрина обнови решението на 18.05.2016 00:07 (преди над 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
import ast


def update(critics, line, mess):
    if line not in critics:
        critics[line] = set()
    critics[line].add(mess)
    return critics


def analysis(node, nesting, indentation, rules, used_lines, critics):
    if rules['forbid_semicolons'] and node.lineno in used_lines:
        critics = update(
            critics, node.lineno, 'multiple expressions on the same line')
    else:
        used_lines.add(node.lineno)
        if node.col_offset != indentation:
            critics = update(
                critics, node.lineno, 'indentation is {} instead of {}'.format(
                    node.col_offset, indentation))
    if rules['max_nesting'] and nesting > rules['max_nesting']:
        critics = update(
            critics, node.lineno, 'nesting too deep ({} > {})'.format(
                nesting, rules['max_nesting']))
    if isinstance(node, ast.Expr) or isinstance(
            node, ast.Expression) or not hasattr(node, 'body'):
        return (1, used_lines, critics)
    sum_lines = 0
    count_methods = 0
    for child in node.body:
        lines, used_lines, critics = analysis(
            child, nesting + 1,
            indentation + rules['indentation_size'],
            rules, used_lines, critics)
        sum_lines += lines
        if isinstance(child, ast.FunctionDef):
            count_methods += 1
    if hasattr(node, 'orelse'):
        for child in node.orelse:
            lines, used_lines, critics = analysis(
                child, nesting + 1,
                indentation + rules['indentation_size'],
                rules, used_lines, critics)
            sum_lines += lines
    if rules['methods_per_class'] and isinstance(
            node, ast.ClassDef) and count_methods > rules['methods_per_class']:
        critics = update(
            critics, node.lineno, 'too many methods in class({} > {})'.format(
                count_methods, rules['methods_per_class']))
    if rules['max_lines_per_function'] and isinstance(
            node, ast.FunctionDef) and sum_lines > rules[
                'max_lines_per_function']:
        critics = update(
            critics, node.lineno,
            'method with too many lines ({} > {})'.format(
                sum_lines, rules['max_lines_per_function']))
    if rules['max_arity'] and isinstance(
            node, ast.FunctionDef):
        count = len(node.args.args) + len(node.args.kwonlyargs)
        if node.args.vararg:
            count += 1
        if node.args.kwarg:
            count += 1
        if count > rules['max_arity']:
            critics = update(
                critics, node.lineno, 'too many arguments({} > {})'.format(
                    count, rules['max_arity']))
    return (sum_lines + 1, used_lines, critics)


def default_rules(rules):
    if 'line_length' not in rules:
        rules['line_length'] = 79
    if 'forbid_semicolons' not in rules:
        rules['forbid_semicolons'] = True
    if 'max_nesting' not in rules:
        rules['max_nesting'] = None
    if 'indentation_size' not in rules:
        rules['indentation_size'] = 4
    if 'methods_per_class' not in rules:
        rules['methods_per_class'] = None
    if 'max_arity' not in rules:
        rules['max_arity'] = None
    if 'forbid_trailing_whitespace' not in rules:
        rules['forbid_trailing_whitespace'] = True
    if 'max_lines_per_function' not in rules:
        rules['max_lines_per_function'] = None
    return rules


def critic(code, **rules):
    tree = ast.parse(code)
    rules = default_rules(rules)
    lines = code.split("\n")
    critics = {}
    used_lines = set()
    for i in range(0, len(lines)):
        if len(lines[i]) > rules['line_length']:
            critics = update(
                critics, i+1, 'line too long ({} > {})'.format(
                    len(lines[i]), rules['line_length']))
        if rules['forbid_trailing_whitespace'] and lines[i].endswith(' '):
            critics = update(
                critics, i+1, 'trailing whitespace')
    for node in tree.body:
        critics = (analysis(
            node, 0, 0, rules, used_lines, critics))[2]
    return critics

Александрина обнови решението на 18.05.2016 16:18 (преди над 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
import ast


def update(critics, line, mess):
    if line not in critics:
        critics[line] = set()
    critics[line].add(mess)
    return critics


def analysis(node, nesting, indentation, rules, used_lines, critics):
    if rules['forbid_semicolons'] and node.lineno in used_lines:
        critics = update(
            critics, node.lineno, 'multiple expressions on the same line')
    else:
        used_lines.add(node.lineno)
        if node.col_offset != indentation:
            critics = update(
                critics, node.lineno, 'indentation is {} instead of {}'.format(
                    node.col_offset, indentation))
    if rules['max_nesting'] and nesting > rules['max_nesting']:
        critics = update(
            critics, node.lineno, 'nesting too deep ({} > {})'.format(
                nesting, rules['max_nesting']))
    if isinstance(node, ast.Expr) or isinstance(
            node, ast.Expression) or not hasattr(node, 'body'):
        return (1, used_lines, critics)
    sum_lines = 0
    count_methods = 0
    for child in node.body:
        lines, used_lines, critics = analysis(
            child, nesting + 1,
            indentation + rules['indentation_size'],
            rules, used_lines, critics)
        sum_lines += lines
        if isinstance(child, ast.FunctionDef):
            count_methods += 1
    if hasattr(node, 'orelse'):
        for child in node.orelse:
            lines, used_lines, critics = analysis(
                child, nesting + 1,
                indentation + rules['indentation_size'],
                rules, used_lines, critics)
            sum_lines += lines
    if rules['methods_per_class'] and isinstance(
            node, ast.ClassDef) and count_methods > rules['methods_per_class']:
        critics = update(
            critics, node.lineno, 'too many methods in class({} > {})'.format(
                count_methods, rules['methods_per_class']))
    if rules['max_lines_per_function'] and isinstance(
            node, ast.FunctionDef) and sum_lines > rules[
                'max_lines_per_function']:
        critics = update(
            critics, node.lineno,
            'method with too many lines ({} > {})'.format(
                sum_lines, rules['max_lines_per_function']))
    if rules['max_arity'] and isinstance(
            node, ast.FunctionDef):
        count = len(node.args.args) + len(node.args.kwonlyargs)
        if node.args.vararg:
            count += 1
        if node.args.kwarg:
            count += 1
        if count > rules['max_arity']:
            critics = update(
                critics, node.lineno, 'too many arguments({} > {})'.format(
                    count, rules['max_arity']))
    return (sum_lines + 1, used_lines, critics)


def default_rules(rules):
    if 'line_length' not in rules:
        rules['line_length'] = 79
    if 'forbid_semicolons' not in rules:
        rules['forbid_semicolons'] = True
    if 'max_nesting' not in rules:
        rules['max_nesting'] = None
    if 'indentation_size' not in rules:
        rules['indentation_size'] = 4
    if 'methods_per_class' not in rules:
        rules['methods_per_class'] = None
    if 'max_arity' not in rules:
        rules['max_arity'] = None
    if 'forbid_trailing_whitespace' not in rules:
        rules['forbid_trailing_whitespace'] = True
    if 'max_lines_per_function' not in rules:
        rules['max_lines_per_function'] = None
    return rules


def critic(code, **rules):
    tree = ast.parse(code)
    rules = default_rules(rules)
    lines = code.split("\n")
    critics = {}
    used_lines = set()
    for i in range(0, len(lines)):
        if len(lines[i]) > rules['line_length']:
            critics = update(
                critics, i+1, 'line too long ({} > {})'.format(
                    len(lines[i]), rules['line_length']))
        if rules['forbid_trailing_whitespace'] and lines[i].endswith(' '):
            critics = update(
                critics, i+1, 'trailing whitespace')
    for node in tree.body:
        sth, used_lines, critics = analysis(
            node, 0, 0, rules, used_lines, critics)
    return critics