ยปCore Development>Code coverage>Tools/scripts/pathfix.py

Python code coverage for Tools/scripts/pathfix.py

#countcontent
1n/a#!/usr/bin/env python3
2n/a
3n/a# Change the #! line occurring in Python scripts. The new interpreter
4n/a# pathname must be given with a -i option.
5n/a#
6n/a# Command line arguments are files or directories to be processed.
7n/a# Directories are searched recursively for files whose name looks
8n/a# like a python module.
9n/a# Symbolic links are always ignored (except as explicit directory
10n/a# arguments). Of course, the original file is kept as a back-up
11n/a# (with a "~" attached to its name).
12n/a#
13n/a# Undoubtedly you can do this using find and sed or perl, but this is
14n/a# a nice example of Python code that recurses down a directory tree
15n/a# and uses regular expressions. Also note several subtleties like
16n/a# preserving the file's mode and avoiding to even write a temp file
17n/a# when no changes are needed for a file.
18n/a#
19n/a# NB: by changing only the function fixfile() you can turn this
20n/a# into a program for a different change to Python programs...
21n/a
22n/aimport sys
23n/aimport re
24n/aimport os
25n/afrom stat import *
26n/aimport getopt
27n/a
28n/aerr = sys.stderr.write
29n/adbg = err
30n/arep = sys.stdout.write
31n/a
32n/anew_interpreter = None
33n/apreserve_timestamps = False
34n/a
35n/adef main():
36n/a global new_interpreter
37n/a global preserve_timestamps
38n/a usage = ('usage: %s -i /interpreter -p file-or-directory ...\n' %
39n/a sys.argv[0])
40n/a try:
41n/a opts, args = getopt.getopt(sys.argv[1:], 'i:p')
42n/a except getopt.error as msg:
43n/a err(str(msg) + '\n')
44n/a err(usage)
45n/a sys.exit(2)
46n/a for o, a in opts:
47n/a if o == '-i':
48n/a new_interpreter = a.encode()
49n/a if o == '-p':
50n/a preserve_timestamps = True
51n/a if not new_interpreter or not new_interpreter.startswith(b'/') or \
52n/a not args:
53n/a err('-i option or file-or-directory missing\n')
54n/a err(usage)
55n/a sys.exit(2)
56n/a bad = 0
57n/a for arg in args:
58n/a if os.path.isdir(arg):
59n/a if recursedown(arg): bad = 1
60n/a elif os.path.islink(arg):
61n/a err(arg + ': will not process symbolic links\n')
62n/a bad = 1
63n/a else:
64n/a if fix(arg): bad = 1
65n/a sys.exit(bad)
66n/a
67n/aispythonprog = re.compile(r'^[a-zA-Z0-9_]+\.py$')
68n/adef ispython(name):
69n/a return bool(ispythonprog.match(name))
70n/a
71n/adef recursedown(dirname):
72n/a dbg('recursedown(%r)\n' % (dirname,))
73n/a bad = 0
74n/a try:
75n/a names = os.listdir(dirname)
76n/a except OSError as msg:
77n/a err('%s: cannot list directory: %r\n' % (dirname, msg))
78n/a return 1
79n/a names.sort()
80n/a subdirs = []
81n/a for name in names:
82n/a if name in (os.curdir, os.pardir): continue
83n/a fullname = os.path.join(dirname, name)
84n/a if os.path.islink(fullname): pass
85n/a elif os.path.isdir(fullname):
86n/a subdirs.append(fullname)
87n/a elif ispython(name):
88n/a if fix(fullname): bad = 1
89n/a for fullname in subdirs:
90n/a if recursedown(fullname): bad = 1
91n/a return bad
92n/a
93n/adef fix(filename):
94n/a## dbg('fix(%r)\n' % (filename,))
95n/a try:
96n/a f = open(filename, 'rb')
97n/a except IOError as msg:
98n/a err('%s: cannot open: %r\n' % (filename, msg))
99n/a return 1
100n/a line = f.readline()
101n/a fixed = fixline(line)
102n/a if line == fixed:
103n/a rep(filename+': no change\n')
104n/a f.close()
105n/a return
106n/a head, tail = os.path.split(filename)
107n/a tempname = os.path.join(head, '@' + tail)
108n/a try:
109n/a g = open(tempname, 'wb')
110n/a except IOError as msg:
111n/a f.close()
112n/a err('%s: cannot create: %r\n' % (tempname, msg))
113n/a return 1
114n/a rep(filename + ': updating\n')
115n/a g.write(fixed)
116n/a BUFSIZE = 8*1024
117n/a while 1:
118n/a buf = f.read(BUFSIZE)
119n/a if not buf: break
120n/a g.write(buf)
121n/a g.close()
122n/a f.close()
123n/a
124n/a # Finishing touch -- move files
125n/a
126n/a mtime = None
127n/a atime = None
128n/a # First copy the file's mode to the temp file
129n/a try:
130n/a statbuf = os.stat(filename)
131n/a mtime = statbuf.st_mtime
132n/a atime = statbuf.st_atime
133n/a os.chmod(tempname, statbuf[ST_MODE] & 0o7777)
134n/a except OSError as msg:
135n/a err('%s: warning: chmod failed (%r)\n' % (tempname, msg))
136n/a # Then make a backup of the original file as filename~
137n/a try:
138n/a os.rename(filename, filename + '~')
139n/a except OSError as msg:
140n/a err('%s: warning: backup failed (%r)\n' % (filename, msg))
141n/a # Now move the temp file to the original file
142n/a try:
143n/a os.rename(tempname, filename)
144n/a except OSError as msg:
145n/a err('%s: rename failed (%r)\n' % (filename, msg))
146n/a return 1
147n/a if preserve_timestamps:
148n/a if atime and mtime:
149n/a try:
150n/a os.utime(filename, (atime, mtime))
151n/a except OSError as msg:
152n/a err('%s: reset of timestamp failed (%r)\n' % (filename, msg))
153n/a return 1
154n/a # Return success
155n/a return 0
156n/a
157n/adef fixline(line):
158n/a if not line.startswith(b'#!'):
159n/a return line
160n/a if b"python" not in line:
161n/a return line
162n/a return b'#! ' + new_interpreter + b'\n'
163n/a
164n/aif __name__ == '__main__':
165n/a main()