8 """ |
9 """ |
9 |
10 |
10 import sys |
11 import sys |
11 import re |
12 import re |
12 import traceback |
13 import traceback |
13 from codecs import BOM_UTF8, BOM_UTF16, BOM_UTF32 |
14 |
|
15 from Tools import readEncodedFile, normalizeCode |
14 |
16 |
15 from py2flakes.checker import Checker |
17 from py2flakes.checker import Checker |
16 from py2flakes.messages import ImportStarUsed |
18 from py2flakes.messages import ImportStarUsed |
17 |
19 |
18 coding_regexps = [ |
20 def compile(file, codestring): |
19 (2, re.compile(r'''coding[:=]\s*([-\w_.]+)''')), |
|
20 (1, re.compile(r'''<\?xml.*\bencoding\s*=\s*['"]([-\w_.]+)['"]\?>''')), |
|
21 ] |
|
22 |
|
23 def get_coding(text): |
|
24 """ |
|
25 Function to get the coding of a text. |
|
26 |
|
27 @param text text to inspect (string) |
|
28 @return coding string |
|
29 """ |
|
30 lines = text.splitlines() |
|
31 for coding in coding_regexps: |
|
32 coding_re = coding[1] |
|
33 head = lines[:coding[0]] |
|
34 for l in head: |
|
35 m = coding_re.search(l) |
|
36 if m: |
|
37 return m.group(1).lower() |
|
38 return None |
|
39 |
|
40 def decode(text): |
|
41 """ |
|
42 Function to decode a text. |
|
43 |
|
44 @param text text to decode (string) |
|
45 @return decoded text and encoding |
|
46 """ |
|
47 try: |
|
48 if text.startswith(BOM_UTF8): |
|
49 # UTF-8 with BOM |
|
50 return unicode(text[len(BOM_UTF8):], 'utf-8'), 'utf-8-bom' |
|
51 elif text.startswith(BOM_UTF16): |
|
52 # UTF-16 with BOM |
|
53 return unicode(text[len(BOM_UTF16):], 'utf-16'), 'utf-16' |
|
54 elif text.startswith(BOM_UTF32): |
|
55 # UTF-32 with BOM |
|
56 return unicode(text[len(BOM_UTF32):], 'utf-32'), 'utf-32' |
|
57 coding = get_coding(text) |
|
58 if coding: |
|
59 return unicode(text, coding), coding |
|
60 except (UnicodeError, LookupError): |
|
61 pass |
|
62 |
|
63 # Assume UTF-8 |
|
64 try: |
|
65 return unicode(text, 'utf-8'), 'utf-8-guessed' |
|
66 except (UnicodeError, LookupError): |
|
67 pass |
|
68 |
|
69 # Assume Latin-1 (behaviour before 3.7.1) |
|
70 return unicode(text, "latin-1"), 'latin-1-guessed' |
|
71 |
|
72 def compile(file): |
|
73 """ |
21 """ |
74 Function to compile one Python source file to Python bytecode. |
22 Function to compile one Python source file to Python bytecode. |
75 |
23 |
76 @param file source filename (string) |
24 @param file source filename (string) |
|
25 @param codestring source code (string) |
77 @return A tuple indicating status (1 = an error was found), the |
26 @return A tuple indicating status (1 = an error was found), the |
78 filename, the linenumber, the code string, the error message |
27 filename, the linenumber, the code string and the error message |
79 and the full source code (boolean, string, string, string, |
28 (boolean, string, string, string, string). The values are only |
80 string, string). The values are only valid, if the status |
29 valid, if the status equals 1. |
81 equals 1. |
|
82 """ |
30 """ |
83 import __builtin__ |
31 import __builtin__ |
84 try: |
|
85 f = open(file) |
|
86 codestring, encoding = decode(f.read()) |
|
87 f.close() |
|
88 except IOError, msg: |
|
89 return (1, file, "1", "", "I/O Error: %s" % unicode(msg), "") |
|
90 |
|
91 if type(codestring) == type(u""): |
|
92 codestring = codestring.encode('utf-8') |
|
93 codestring = codestring.replace("\r\n","\n") |
|
94 codestring = codestring.replace("\r","\n") |
|
95 |
|
96 if codestring and codestring[-1] != '\n': |
|
97 codestring = codestring + '\n' |
|
98 |
32 |
99 try: |
33 try: |
100 if type(file) == type(u""): |
34 if type(file) == type(u""): |
101 file = file.encode('utf-8') |
35 file = file.encode('utf-8') |
102 |
36 |
127 else: |
61 else: |
128 fn = detail.filename |
62 fn = detail.filename |
129 line = detail.lineno and detail.lineno or 1 |
63 line = detail.lineno and detail.lineno or 1 |
130 code = "" |
64 code = "" |
131 error = detail.msg |
65 error = detail.msg |
132 return (1, fn, line, code, error, codestring) |
66 return (1, fn, line, code, error) |
133 except ValueError, detail: |
67 except ValueError, detail: |
134 try: |
68 try: |
135 fn = detail.filename |
69 fn = detail.filename |
136 line = detail.lineno |
70 line = detail.lineno |
137 error = detail.msg |
71 error = detail.msg |
138 except AttributeError: |
72 except AttributeError: |
139 fn = file |
73 fn = file |
140 line = 1 |
74 line = 1 |
141 error = unicode(detail) |
75 error = unicode(detail) |
142 code = "" |
76 code = "" |
143 return (1, fn, line, code, error, codestring) |
77 return (1, fn, line, code, error) |
144 except StandardError, detail: |
78 except StandardError, detail: |
145 try: |
79 try: |
146 fn = detail.filename |
80 fn = detail.filename |
147 line = detail.lineno |
81 line = detail.lineno |
148 code = "" |
82 code = "" |
149 error = detail.msg |
83 error = detail.msg |
150 return (1, fn, line, code, error, codestring) |
84 return (1, fn, line, code, error) |
151 except: # this catchall is intentional |
85 except: # this catchall is intentional |
152 pass |
86 pass |
153 |
87 |
154 return (0, None, None, None, None, codestring) |
88 return (0, None, None, None, None) |
155 |
89 |
156 def flakesCheck(fileName, codestring, ignoreStarImportWarnings): |
90 def flakesCheck(fileName, codestring, ignoreStarImportWarnings): |
157 """ |
91 """ |
158 Function to perform a pyflakes check. |
92 Function to perform a pyflakes check. |
159 |
93 |
196 print "" |
130 print "" |
197 print "" |
131 print "" |
198 print "No file name given." |
132 print "No file name given." |
199 else: |
133 else: |
200 filename = sys.argv[-1] |
134 filename = sys.argv[-1] |
201 syntaxerror, fname, line, code, error, codestring = compile(filename) |
135 try: |
|
136 codestring = readEncodedFile(filename)[0] |
|
137 codestring = normalizeCode(codestring) |
|
138 |
|
139 syntaxerror, fname, line, code, error = compile(filename, codestring) |
|
140 except IOError, msg: |
|
141 # fake a syntax error |
|
142 syntaxerror, fname, line, code, error = \ |
|
143 1, filename, "1", "", "I/O Error: %s" % unicode(msg) |
202 |
144 |
203 if syntaxerror: |
145 if syntaxerror: |
204 print "ERROR" |
146 print "ERROR" |
205 else: |
147 else: |
206 print "NO_ERROR" |
148 print "NO_ERROR" |