| 58 | return ExitStatus.ERROR |
| 59 | |
| 60 | def _install(self, targets: List[str], mode='install') -> Tuple[ |
| 61 | bytes, ExitStatus |
| 62 | ]: |
| 63 | pip_args = [ |
| 64 | 'install', |
| 65 | '--prefer-binary', |
| 66 | f'--prefix={self.dir}', |
| 67 | '--no-warn-script-location', |
| 68 | ] |
| 69 | if mode == 'upgrade': |
| 70 | pip_args.append('--upgrade') |
| 71 | pip_args.extend(targets) |
| 72 | |
| 73 | try: |
| 74 | stdout = run_pip(pip_args) |
| 75 | except PipError as pip_error: |
| 76 | error = pip_error |
| 77 | stdout = pip_error.stdout |
| 78 | else: |
| 79 | error = None |
| 80 | |
| 81 | self.env.stdout.write(stdout.decode()) |
| 82 | |
| 83 | if error: |
| 84 | reason = None |
| 85 | if error.stderr: |
| 86 | stderr = error.stderr.decode() |
| 87 | |
| 88 | if self.debug: |
| 89 | self.env.stderr.write('Command failed: ') |
| 90 | self.env.stderr.write('pip ' + ' '.join(pip_args) + '\n') |
| 91 | self.env.stderr.write(textwrap.indent(' ', stderr)) |
| 92 | |
| 93 | last_line = stderr.strip().splitlines()[-1] |
| 94 | severity, _, message = last_line.partition(': ') |
| 95 | if severity == 'ERROR': |
| 96 | reason = message |
| 97 | |
| 98 | stdout = error.stdout |
| 99 | exit_status = self.fail(mode, ', '.join(targets), reason) |
| 100 | else: |
| 101 | exit_status = ExitStatus.SUCCESS |
| 102 | |
| 103 | return stdout, exit_status |
| 104 | |
| 105 | def install(self, targets: List[str]) -> ExitStatus: |
| 106 | self.env.stdout.write(f"Installing {', '.join(targets)}...\n") |