]> crepu.dev Git - config.git/blame_incremental - djavu-asus/elpy/rpc-venv/lib/python3.11/site-packages/pyflakes/api.py
ActualizaciĆ³n de Readme
[config.git] / djavu-asus / elpy / rpc-venv / lib / python3.11 / site-packages / pyflakes / api.py
... / ...
CommitLineData
1"""
2API for the command-line I{pyflakes} tool.
3"""
4import ast
5import os
6import platform
7import re
8import sys
9
10from pyflakes import checker, __version__
11from pyflakes import reporter as modReporter
12
13__all__ = ['check', 'checkPath', 'checkRecursive', 'iterSourceCode', 'main']
14
15PYTHON_SHEBANG_REGEX = re.compile(br'^#!.*\bpython(3(\.\d+)?|w)?[dmu]?\s')
16
17
18def check(codeString, filename, reporter=None):
19 """
20 Check the Python source given by C{codeString} for flakes.
21
22 @param codeString: The Python source to check.
23 @type codeString: C{str}
24
25 @param filename: The name of the file the source came from, used to report
26 errors.
27 @type filename: C{str}
28
29 @param reporter: A L{Reporter} instance, where errors and warnings will be
30 reported.
31
32 @return: The number of warnings emitted.
33 @rtype: C{int}
34 """
35 if reporter is None:
36 reporter = modReporter._makeDefaultReporter()
37 # First, compile into an AST and handle syntax errors.
38 try:
39 tree = ast.parse(codeString, filename=filename)
40 except SyntaxError as e:
41 reporter.syntaxError(filename, e.args[0], e.lineno, e.offset, e.text)
42 return 1
43 except Exception:
44 reporter.unexpectedError(filename, 'problem decoding source')
45 return 1
46 # Okay, it's syntactically valid. Now check it.
47 w = checker.Checker(tree, filename=filename)
48 w.messages.sort(key=lambda m: m.lineno)
49 for warning in w.messages:
50 reporter.flake(warning)
51 return len(w.messages)
52
53
54def checkPath(filename, reporter=None):
55 """
56 Check the given path, printing out any warnings detected.
57
58 @param reporter: A L{Reporter} instance, where errors and warnings will be
59 reported.
60
61 @return: the number of warnings printed
62 """
63 if reporter is None:
64 reporter = modReporter._makeDefaultReporter()
65 try:
66 with open(filename, 'rb') as f:
67 codestr = f.read()
68 except OSError as e:
69 reporter.unexpectedError(filename, e.args[1])
70 return 1
71 return check(codestr, filename, reporter)
72
73
74def isPythonFile(filename):
75 """Return True if filename points to a Python file."""
76 if filename.endswith('.py'):
77 return True
78
79 # Avoid obvious Emacs backup files
80 if filename.endswith("~"):
81 return False
82
83 max_bytes = 128
84
85 try:
86 with open(filename, 'rb') as f:
87 text = f.read(max_bytes)
88 if not text:
89 return False
90 except OSError:
91 return False
92
93 return PYTHON_SHEBANG_REGEX.match(text)
94
95
96def iterSourceCode(paths):
97 """
98 Iterate over all Python source files in C{paths}.
99
100 @param paths: A list of paths. Directories will be recursed into and
101 any .py files found will be yielded. Any non-directories will be
102 yielded as-is.
103 """
104 for path in paths:
105 if os.path.isdir(path):
106 for dirpath, dirnames, filenames in os.walk(path):
107 for filename in filenames:
108 full_path = os.path.join(dirpath, filename)
109 if isPythonFile(full_path):
110 yield full_path
111 else:
112 yield path
113
114
115def checkRecursive(paths, reporter):
116 """
117 Recursively check all source files in C{paths}.
118
119 @param paths: A list of paths to Python source files and directories
120 containing Python source files.
121 @param reporter: A L{Reporter} where all of the warnings and errors
122 will be reported to.
123 @return: The number of warnings found.
124 """
125 warnings = 0
126 for sourcePath in iterSourceCode(paths):
127 warnings += checkPath(sourcePath, reporter)
128 return warnings
129
130
131def _exitOnSignal(sigName, message):
132 """Handles a signal with sys.exit.
133
134 Some of these signals (SIGPIPE, for example) don't exist or are invalid on
135 Windows. So, ignore errors that might arise.
136 """
137 import signal
138
139 try:
140 sigNumber = getattr(signal, sigName)
141 except AttributeError:
142 # the signal constants defined in the signal module are defined by
143 # whether the C library supports them or not. So, SIGPIPE might not
144 # even be defined.
145 return
146
147 def handler(sig, f):
148 sys.exit(message)
149
150 try:
151 signal.signal(sigNumber, handler)
152 except ValueError:
153 # It's also possible the signal is defined, but then it's invalid. In
154 # this case, signal.signal raises ValueError.
155 pass
156
157
158def _get_version():
159 """
160 Retrieve and format package version along with python version & OS used
161 """
162 return ('%s Python %s on %s' %
163 (__version__, platform.python_version(), platform.system()))
164
165
166def main(prog=None, args=None):
167 """Entry point for the script "pyflakes"."""
168 import argparse
169
170 # Handle "Keyboard Interrupt" and "Broken pipe" gracefully
171 _exitOnSignal('SIGINT', '... stopped')
172 _exitOnSignal('SIGPIPE', 1)
173
174 parser = argparse.ArgumentParser(prog=prog,
175 description='Check Python source files for errors')
176 parser.add_argument('-V', '--version', action='version', version=_get_version())
177 parser.add_argument('path', nargs='*',
178 help='Path(s) of Python file(s) to check. STDIN if not given.')
179 args = parser.parse_args(args=args).path
180 reporter = modReporter._makeDefaultReporter()
181 if args:
182 warnings = checkRecursive(args, reporter)
183 else:
184 warnings = check(sys.stdin.read(), '<stdin>', reporter)
185 raise SystemExit(warnings > 0)