-
Notifications
You must be signed in to change notification settings - Fork 71
/
w3c_validator.py
executable file
·131 lines (101 loc) · 3.17 KB
/
w3c_validator.py
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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
#!/usr/bin/python3
"""
W3C validator for Holberton School
For HTML and CSS files.
Based on 1 API:
- https://validator.w3.org/docs/api.html
Usage:
Simple file:
```
./w3c_validator.py index.html
```
Multiple files:
```
./w3c_validator.py index.html header.html styles/common.css
```
All errors are printed in `STDERR`
Return:
Exit status is the # of errors, 0 on Success
"""
import sys
import requests
import os
def __print_stdout(msg):
"""Print message in STDOUT
"""
sys.stdout.buffer.write(msg.encode('utf-8'))
def __print_stderr(msg):
"""Print message in STDERR
"""
sys.stderr.buffer.write(msg.encode('utf-8'))
def __is_empty(file):
if os.path.getsize(file) == 0:
raise OSError("File '{}' is empty.".format(file))
def __validate(file_path, type):
"""
Start validation of files
"""
h = {'Content-Type': "{}; charset=utf-8".format(type)}
# Open files in binary mode:
# https://requests.readthedocs.io/en/master/user/advanced/
d = open(file_path, "rb").read()
u = "https://validator.w3.org/nu/?out=json"
r = requests.post(u, headers=h, data=d)
if not r.status_code < 400:
raise ConnectionError("Unable to connect to API endpoint.")
res = []
messages = r.json().get('messages', [])
for m in messages:
# Capture files that have incomplete or broken HTML
if m['type'] == 'error' or m['type'] == 'info':
res.append("'{}' => {}".format(file_path, m['message']))
else:
res.append("[{}:{}] {}".format(
file_path, m['lastLine'], m['message']))
return res
def __analyse(file_path):
"""Start analyse of a file and print the result
"""
nb_errors = 0
try:
result = None
if file_path.endswith(".css"):
__is_empty(file_path)
result = __validate(file_path, "text/css")
elif file_path.endswith((".html", ".htm")):
__is_empty(file_path)
result = __validate(file_path, "text/html")
elif file_path.endswith(".svg"):
__is_empty(file_path)
result = __validate(file_path, "image/svg+xml")
else:
allowed_files = "'.css', '.html', '.htm' and '.svg'"
raise OSError(
"File {} does not have a valid file extension.\nOnly {} are "
"allowed.".format(file_path, allowed_files)
)
if len(result) > 0:
for msg in result:
__print_stderr("{}\n".format(msg))
nb_errors += 1
else:
__print_stdout("'{}' => OK\n".format(file_path))
except Exception as e:
__print_stderr("'{}' => {}\n".format(e.__class__.__name__, e))
return nb_errors
def __files_loop():
"""Loop that analyses for each file from input arguments
"""
nb_errors = 0
for file_path in sys.argv[1:]:
nb_errors += __analyse(file_path)
return nb_errors
if __name__ == "__main__":
"""Main
"""
if len(sys.argv) < 2:
__print_stderr("usage: w3c_validator.py file1 file2 ...\n")
exit(1)
"""execute tests, then exit. Exit status = # of errors (0 on success)
"""
sys.exit(__files_loop())