| 186 | |
| 187 | |
| 188 | class _ScriptTarget(_ExecutableTarget): |
| 189 | def __init__(self, target): |
| 190 | self._check(target) |
| 191 | self._target = self._safe_realpath(target) |
| 192 | |
| 193 | # If PYTHONSAFEPATH (-P) is not set, sys.path[0] is the directory |
| 194 | # of pdb, and we should replace it with the directory of the script |
| 195 | if not sys.flags.safe_path: |
| 196 | sys.path[0] = os.path.dirname(self._target) |
| 197 | |
| 198 | @staticmethod |
| 199 | def _check(target): |
| 200 | """ |
| 201 | Check that target is plausibly a script. |
| 202 | """ |
| 203 | if not os.path.exists(target): |
| 204 | print(f'Error: {target} does not exist') |
| 205 | sys.exit(1) |
| 206 | if os.path.isdir(target): |
| 207 | print(f'Error: {target} is a directory') |
| 208 | sys.exit(1) |
| 209 | |
| 210 | @staticmethod |
| 211 | def _safe_realpath(path): |
| 212 | """ |
| 213 | Return the canonical path (realpath) if it is accessible from the userspace. |
| 214 | Otherwise (for example, if the path is a symlink to an anonymous pipe), |
| 215 | return the original path. |
| 216 | |
| 217 | See GH-142315. |
| 218 | """ |
| 219 | realpath = os.path.realpath(path) |
| 220 | return realpath if os.path.exists(realpath) else path |
| 221 | |
| 222 | def __repr__(self): |
| 223 | return self._target |
| 224 | |
| 225 | @property |
| 226 | def filename(self): |
| 227 | return self._target |
| 228 | |
| 229 | @property |
| 230 | def code(self): |
| 231 | # Open the file each time because the file may be modified |
| 232 | with io.open_code(self._target) as fp: |
| 233 | return f"exec(compile({fp.read()!r}, {self._target!r}, 'exec'))" |
| 234 | |
| 235 | @property |
| 236 | def namespace(self): |
| 237 | return dict( |
| 238 | __name__='__main__', |
| 239 | __file__=self._target, |
| 240 | __builtins__=__builtins__, |
| 241 | __spec__=None, |
| 242 | ) |
| 243 | |
| 244 | |
| 245 | class _ModuleTarget(_ExecutableTarget): |
no outgoing calls
no test coverage detected
searching dependent graphs…