Gentoo Archives: gentoo-commits

From: Mike Frysinger <vapier@g.o>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] proj/pax-utils:master commit in: /
Date: Wed, 28 Sep 2022 07:43:00
Message-Id: 1664350937.b07b25dcc8ad0e518d801bc23d01fb59cc6de442.vapier@gentoo
1 commit: b07b25dcc8ad0e518d801bc23d01fb59cc6de442
2 Author: Mike Frysinger <vapier <AT> chromium <DOT> org>
3 AuthorDate: Wed Sep 28 06:03:01 2022 +0000
4 Commit: Mike Frysinger <vapier <AT> gentoo <DOT> org>
5 CommitDate: Wed Sep 28 07:42:17 2022 +0000
6 URL: https://gitweb.gentoo.org/proj/pax-utils.git/commit/?id=b07b25dc
7
8 lddtree: add typing info to more places
9
10 Signed-off-by: Mike Frysinger <vapier <AT> gentoo.org>
11
12 lddtree.py | 87 +++++++++++++++++++++++++++++++++++++++++++-------------------
13 1 file changed, 61 insertions(+), 26 deletions(-)
14
15 diff --git a/lddtree.py b/lddtree.py
16 index ecb353d..6939bb6 100755
17 --- a/lddtree.py
18 +++ b/lddtree.py
19 @@ -48,6 +48,7 @@ import mmap
20 import os
21 import shutil
22 import sys
23 +from typing import Any, Iterable, Optional, Union
24
25 assert sys.version_info >= (3, 6), f'Python 3.6+ required, but found {sys.version}'
26
27 @@ -60,31 +61,31 @@ from elftools.common import exceptions
28 from elftools.elf.elffile import ELFFile
29
30
31 -def warn(msg, prefix='warning'):
32 +def warn(msg: Any, prefix: Optional[str] = "warning") -> None:
33 """Write |msg| to stderr with a |prefix| before it"""
34 print('%s: %s: %s' % (os.path.basename(sys.argv[0]), prefix, msg), file=sys.stderr)
35
36
37 -def err(msg, status=1):
38 +def err(msg: Any, status: Optional[int] = 1) -> None:
39 """Write |msg| to stderr and exit with |status|"""
40 warn(msg, prefix='error')
41 sys.exit(status)
42
43
44 -def dbg(debug, *args, **kwargs):
45 +def dbg(debug: bool, *args, **kwargs) -> None:
46 """Pass |args| and |kwargs| to print() when |debug| is True"""
47 if debug:
48 print(*args, **kwargs)
49
50
51 -def bstr(buf):
52 +def bstr(buf: Union[bytes, str]) -> str:
53 """Decode the byte string into a string"""
54 if isinstance(buf, str):
55 return buf
56 return buf.decode('utf-8')
57
58
59 -def normpath(path):
60 +def normpath(path: str) -> str:
61 """Normalize a path
62
63 Python's os.path.normpath() doesn't handle some cases:
64 @@ -96,7 +97,7 @@ def normpath(path):
65
66
67 @functools.lru_cache(maxsize=None)
68 -def readlink(path, root, prefixed=False):
69 +def readlink(path: str, root: str, prefixed: Optional[bool] = False) -> str:
70 """Like os.readlink(), but relative to a |root|
71
72 This does not currently handle the pathological case:
73 @@ -124,14 +125,14 @@ def readlink(path, root, prefixed=False):
74 return normpath((root + path) if prefixed else path)
75
76
77 -def dedupe(items):
78 +def dedupe(items: list[str]) -> list[str]:
79 """Remove all duplicates from |items| (keeping order)"""
80 - seen = {}
81 + seen: dict[str, str] = {}
82 return [seen.setdefault(x, x) for x in items if x not in seen]
83
84
85 @functools.lru_cache(maxsize=None)
86 -def interp_supports_argv0(interp) -> bool:
87 +def interp_supports_argv0(interp: str) -> bool:
88 """See whether |interp| supports the --argv0 option.
89
90 Starting with glibc-2.33, the ldso supports --argv0 to override argv[0].
91 @@ -141,7 +142,12 @@ def interp_supports_argv0(interp) -> bool:
92 return mm.find(b'--argv0') >= 0
93
94
95 -def GenerateLdsoWrapper(root, path, interp, libpaths=()):
96 +def GenerateLdsoWrapper(
97 + root: str,
98 + path: str,
99 + interp: str,
100 + libpaths: Iterable[str] = (),
101 +) -> None:
102 """Generate a shell script wrapper which uses local ldso to run the ELF
103
104 Since we cannot rely on the host glibc (or other libraries), we need to
105 @@ -190,7 +196,12 @@ exec \\
106
107
108 @functools.lru_cache(maxsize=None)
109 -def ParseLdPaths(str_ldpaths, root='', cwd=None, path=None):
110 +def ParseLdPaths(
111 + str_ldpaths: str,
112 + root: str = "",
113 + cwd: Optional[str] = None,
114 + path: str = "",
115 +) -> list[str]:
116 """Parse the colon-delimited list of paths and apply ldso rules to each
117
118 Note the special handling as dictated by the ldso:
119 @@ -232,7 +243,12 @@ def ParseLdPaths(str_ldpaths, root='', cwd=None, path=None):
120 return dedupe(ldpaths)
121
122
123 -def ParseLdSoConf(ldso_conf, root='/', debug=False, _first=True):
124 +def ParseLdSoConf(
125 + ldso_conf: str,
126 + root: str = "/",
127 + debug: bool = False,
128 + _first: bool = True,
129 +) -> list[str]:
130 """Load all the paths from a given ldso config file
131
132 This should handle comments, whitespace, and "include" statements.
133 @@ -283,7 +299,12 @@ def ParseLdSoConf(ldso_conf, root='/', debug=False, _first=True):
134 return paths
135
136
137 -def LoadLdpaths(root='/', cwd=None, prefix='', debug=False):
138 +def LoadLdpaths(
139 + root: str = "/",
140 + cwd: Optional[str] = None,
141 + prefix: str = "",
142 + debug: bool = False,
143 +) -> dict[str, list[str]]:
144 """Load linker paths from common locations
145
146 This parses the ld.so.conf and LD_LIBRARY_PATH env var.
147 @@ -297,7 +318,7 @@ def LoadLdpaths(root='/', cwd=None, prefix='', debug=False):
148 Returns:
149 dict containing library paths to search
150 """
151 - ldpaths = {
152 + ldpaths: dict[str, list[str]] = {
153 'conf': [],
154 'env': [],
155 'interp': [],
156 @@ -321,7 +342,7 @@ def LoadLdpaths(root='/', cwd=None, prefix='', debug=False):
157 return ldpaths
158
159
160 -def CompatibleELFs(elf1, elf2):
161 +def CompatibleELFs(elf1: ELFFile, elf2: ELFFile) -> bool:
162 """See if two ELFs are compatible
163
164 This compares the aspects of the ELF to see if they're compatible:
165 @@ -344,7 +365,13 @@ def CompatibleELFs(elf1, elf2):
166 elf1.header['e_machine'] == elf2.header['e_machine'])
167
168
169 -def FindLib(elf, lib, ldpaths, root='/', debug=False):
170 +def FindLib(
171 + elf: ELFFile,
172 + lib: str,
173 + ldpaths: list[str],
174 + root: str = "/",
175 + debug: bool = False,
176 +) -> tuple[Optional[str], Optional[str]]:
177 """Try to locate a |lib| that is compatible to |elf| in the given |ldpaths|
178
179 Args:
180 @@ -381,9 +408,17 @@ def FindLib(elf, lib, ldpaths, root='/', debug=False):
181
182 # We abuse the _all_libs state. We probably shouldn't, but we do currently.
183 # pylint: disable=dangerous-default-value
184 -def ParseELF(path, root='/', cwd=None, prefix='',
185 - ldpaths={'conf':[], 'env':[], 'interp':[]},
186 - display=None, debug=False, _first=True, _all_libs={}):
187 +def ParseELF(
188 + path: str,
189 + root: str = "/",
190 + cwd: Optional[str] = None,
191 + prefix: str = "",
192 + ldpaths={"conf": [], "env": [], "interp": []},
193 + display: Optional[str] = None,
194 + debug: bool = False,
195 + _first: bool = True,
196 + _all_libs={},
197 +) -> dict[str, Any]:
198 """Parse the ELF dependency tree of the specified file
199
200 Args:
201 @@ -522,7 +557,7 @@ def ParseELF(path, root='/', cwd=None, prefix='',
202 'path': fullpath,
203 'needed': [],
204 }
205 - if fullpath:
206 + if realpath is not None:
207 try:
208 lret = ParseELF(realpath, root, cwd, prefix, ldpaths, display=fullpath,
209 debug=debug, _first=False, _all_libs=_all_libs)
210 @@ -541,7 +576,7 @@ class _NormalizePathAction(argparse.Action):
211 setattr(namespace, self.dest, normpath(values))
212
213
214 -def _ActionShow(options, elf):
215 +def _ActionShow(options: argparse.Namespace, elf: dict):
216 """Show the dependency tree for this ELF"""
217 def _show(lib, depth):
218 chain_libs.append(lib)
219 @@ -568,7 +603,7 @@ def _ActionShow(options, elf):
220
221 shown_libs = set(elf['needed'])
222 new_libs = elf['needed'][:]
223 - chain_libs = []
224 + chain_libs: list[str] = []
225 interp = elf['interp']
226 if interp:
227 lib = os.path.basename(interp)
228 @@ -590,9 +625,9 @@ def _ActionShow(options, elf):
229 _show(lib, 1)
230
231
232 -def _ActionCopy(options, elf):
233 +def _ActionCopy(options: argparse.Namespace, elf: dict):
234 """Copy the ELF and its dependencies to a destination tree"""
235 - def _StripRoot(path):
236 + def _StripRoot(path: str) -> str:
237 return path[len(options.root) - 1:]
238
239 def _copy(realsrc, src, striproot=True, wrapit=False, libpaths=(),
240 @@ -687,7 +722,7 @@ def _ActionCopy(options, elf):
241 outdir=options.bindir)
242
243
244 -def GetParser():
245 +def GetParser() -> argparse.ArgumentParser:
246 """Get a CLI parser."""
247 parser = argparse.ArgumentParser(
248 description=__doc__,
249 @@ -758,7 +793,7 @@ def GetParser():
250 return parser
251
252
253 -def main(argv):
254 +def main(argv: list[str]) -> Optional[int]:
255 """The main entry point!"""
256 parser = GetParser()
257 options = parser.parse_args(argv)