Skip to content

Commit 1c1254c

Browse files
nox task for checking linting files added + tests
1 parent 2449410 commit 1c1254c

File tree

4 files changed

+260
-12
lines changed

4 files changed

+260
-12
lines changed

exasol/toolbox/nox/_gh.py

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
import nox
2+
from nox import Session
3+
from noxconfig import PROJECT_CONFIG
4+
import sys
5+
from pathlib import Path
6+
import json
7+
import sqlite3
8+
from typing import Iterable
9+
10+
11+
@nox.session(name="check:lint-files", python=False)
12+
def check_lint_files(session: Session) -> None:
13+
"""task to validate linting files"""
14+
if not_available := files_not_available(
15+
[".lint.json", ".lint.txt", ".security.json", ".coverage"],
16+
PROJECT_CONFIG.root):
17+
print(f"not available: {not_available}")
18+
sys.exit(1)
19+
20+
error = False
21+
if msg := check_lint_json(PROJECT_CONFIG.root):
22+
print(f"error in [.lint.json]: {msg}")
23+
error = True
24+
if msg := check_security_json(PROJECT_CONFIG.root):
25+
print(f"error in [.security.json]: {msg}")
26+
error = True
27+
if msg := check_coverage(PROJECT_CONFIG.root):
28+
print(f"error in [.coverage]: {msg}")
29+
error = True
30+
if error:
31+
sys.exit(1)
32+
33+
34+
def files_not_available(requested: list, path: Path) -> list:
35+
not_existing_files = requested.copy()
36+
for file in path.iterdir():
37+
if file.is_file():
38+
if file.name in not_existing_files:
39+
not_existing_files.remove(file.name)
40+
return not_existing_files
41+
42+
43+
def check_lint_json(path: Path) -> str:
44+
path = Path(path, ".lint.json")
45+
try:
46+
with path.open("r") as file:
47+
issues = json.load(file)
48+
error = False
49+
for issue in issues:
50+
attributes = ["type", "module", "obj", "line", "column", "endLine",
51+
"endColumn", "path", "symbol", "message", "message-id"]
52+
for attribute in attributes:
53+
error |= attribute not in issue
54+
if error:
55+
return "incompatible format"
56+
return ""
57+
58+
except json.JSONDecodeError:
59+
return "parsing of json not possible"
60+
61+
62+
def check_security_json(path: Path) -> str:
63+
path = Path(path, ".security.json")
64+
try:
65+
with path.open("r") as input_file:
66+
json_file = json.load(input_file)
67+
error = False
68+
attributes = ["errors", "generated_at", "metrics", "results"]
69+
for attribute in attributes:
70+
error |= attribute not in json_file
71+
if error:
72+
return "incompatible format"
73+
return ""
74+
75+
except json.JSONDecodeError:
76+
return "parsing of json not possible"
77+
78+
79+
def check_coverage(path: Path) -> str:
80+
path = Path(path, ".coverage")
81+
try:
82+
conn = sqlite3.connect(path)
83+
cursor = conn.cursor()
84+
not_existing_tables = ["coverage_schema", "meta", "file", "line_bits"]
85+
data = cursor.execute("select name from sqlite_schema where type == 'table'")
86+
for row in data:
87+
if row[0] in not_existing_tables:
88+
not_existing_tables.remove(row[0])
89+
conn.close()
90+
if not_existing_tables:
91+
return "not existing tables: " + str(not_existing_tables)
92+
return ""
93+
except sqlite3.Error:
94+
return "connection to database not possible"

exasol/toolbox/nox/tasks.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,8 @@ def check(session: Session) -> None:
6666
_version,
6767
python_files,
6868
)
69-
70-
69+
from exasol.toolbox.nox._gh import (
70+
check_lint_files
71+
)
7172
# isort: on
7273
# fmt: on

poetry.lock

Lines changed: 10 additions & 10 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

test/unit/lint_file_check_test.py

Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
import json
2+
3+
import pytest
4+
from pathlib import Path
5+
import sqlite3
6+
7+
from exasol.toolbox.nox import _gh
8+
9+
@pytest.mark.parametrize(
10+
"files,requested_files,expected",
11+
[
12+
(
13+
[".lint.json", ".lint.txt", ".security.json", ".coverage"],
14+
[".lint.json", ".lint.txt", ".security.json", ".coverage"],
15+
[]
16+
), (
17+
[".lint.txt", ".security.json", ".coverage"],
18+
[".lint.json", ".lint.txt", ".security.json", ".coverage"],
19+
[".lint.json"]
20+
), (
21+
[".lint.json", ".security.json", ".coverage"],
22+
[".lint.json", ".lint.txt", ".security.json", ".coverage"],
23+
[".lint.txt"]
24+
), (
25+
[".lint.json", ".lint.txt", ".coverage"],
26+
[".lint.json", ".lint.txt", ".security.json", ".coverage"],
27+
[".security.json"]
28+
), (
29+
[".lint.json", ".lint.txt", ".security.json"],
30+
[".lint.json", ".lint.txt", ".security.json", ".coverage"],
31+
[".coverage"]
32+
), (
33+
[],
34+
[".lint.json", ".lint.txt", ".security.json", ".coverage"],
35+
[".lint.json", ".lint.txt", ".security.json", ".coverage"]
36+
),
37+
]
38+
)
39+
def test_check_lint_files(files, requested_files, expected, tmp_path):
40+
path = Path(tmp_path)
41+
for file in files:
42+
Path(path, file).touch()
43+
44+
actual = _gh.files_not_available(requested_files, path)
45+
assert actual == expected
46+
47+
48+
@pytest.mark.parametrize(
49+
"attributes,expected",
50+
[
51+
(
52+
["type", "module", "obj", "line", "column", "endLine",
53+
"endColumn", "path", "symbol", "message", "message-id"],
54+
""
55+
), (
56+
["module", "obj", "line", "column", "endLine",
57+
"endColumn", "path", "symbol", "message", "message-id"],
58+
"incompatible format"
59+
), (
60+
["type", "obj", "line", "column", "endLine",
61+
"endColumn", "path", "symbol", "message", "message-id"],
62+
"incompatible format"
63+
), (
64+
["type", "module", "line", "column", "endLine",
65+
"endColumn", "path", "symbol", "message", "message-id"],
66+
"incompatible format"
67+
), (
68+
["type", "module", "obj", "column", "endLine",
69+
"endColumn", "path", "symbol", "message", "message-id"],
70+
"incompatible format"
71+
), (
72+
["type", "module", "obj", "line", "endLine",
73+
"endColumn", "path", "symbol", "message", "message-id"],
74+
"incompatible format"
75+
), (
76+
["type", "module", "obj", "line", "column",
77+
"endColumn", "path", "symbol", "message", "message-id"],
78+
"incompatible format"
79+
), (
80+
["type", "module", "obj", "line", "column", "endLine",
81+
"path", "symbol", "message", "message-id"],
82+
"incompatible format"
83+
), (
84+
["type", "module", "obj", "line", "column", "endLine",
85+
"endColumn", "symbol", "message", "message-id"],
86+
"incompatible format"
87+
), (
88+
["type", "module", "obj", "line", "column", "endLine",
89+
"endColumn", "path", "message", "message-id"],
90+
"incompatible format"
91+
), (
92+
["type", "module", "obj", "line", "column", "endLine",
93+
"endColumn", "path", "symbol", "message-id"],
94+
"incompatible format"
95+
), (
96+
["type", "module", "obj", "line", "column", "endLine",
97+
"endColumn", "path", "symbol", "message"],
98+
"incompatible format"
99+
),
100+
]
101+
)
102+
def test_check_lint_json(attributes, expected, tmp_path):
103+
path = Path(tmp_path, ".lint.json")
104+
path.touch()
105+
attributes_dict = {}
106+
for attribute in attributes:
107+
attributes_dict[attribute] = None
108+
with path.open("w") as file:
109+
json.dump([attributes_dict], file)
110+
actual = _gh.check_lint_json(path.parent)
111+
assert actual == expected
112+
113+
114+
@pytest.mark.parametrize(
115+
"attributes,expected",
116+
[
117+
(['errors', 'generated_at', 'metrics', 'results'], ""),
118+
(["generated_at", "metrics", "results"], "incompatible format"),
119+
(["errors", "metrics", "results"], "incompatible format"),
120+
(["errors", "generated_at", "results"], "incompatible format"),
121+
(["errors", "generated_at", "metrics"], "incompatible format"),
122+
]
123+
)
124+
def test_check_lint_json(attributes, expected, tmp_path):
125+
path = Path(tmp_path, ".security.json")
126+
path.touch()
127+
attributes_dict = {}
128+
for attribute in attributes:
129+
attributes_dict[attribute] = None
130+
with path.open("w") as file:
131+
json.dump(attributes_dict, file)
132+
actual = _gh.check_security_json(path.parent)
133+
assert actual == expected
134+
135+
136+
@pytest.mark.parametrize(
137+
"tables, expected",
138+
[
139+
(["coverage_schema", "meta", "file", "line_bits"], ""),
140+
(["meta", "file", "line_bits"], "not existing tables: ['coverage_schema']"),
141+
(["coverage_schema", "file", "line_bits"], "not existing tables: ['meta']"),
142+
(["coverage_schema", "meta", "line_bits"], "not existing tables: ['file']"),
143+
(["coverage_schema", "meta", "file", ], "not existing tables: ['line_bits']"),
144+
]
145+
)
146+
def test_check_coverage(tables, expected, tmp_path):
147+
path = Path(tmp_path, ".coverage")
148+
connection = sqlite3.connect(path)
149+
cursor = connection.cursor()
150+
for table in tables:
151+
cursor.execute(f"CREATE TABLE IF NOT EXISTS {table} (test INTEGER)")
152+
actual = _gh.check_coverage(path.parent)
153+
assert actual == expected

0 commit comments

Comments
 (0)