• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

devonfw / IDEasy / 20815662835

08 Jan 2026 11:43AM UTC coverage: 69.937% (+0.04%) from 69.902%
20815662835

Pull #1671

github

web-flow
Merge 8484d3194 into a329c529a
Pull Request #1671: #1602: Being offline can block ide startup

3989 of 6280 branches covered (63.52%)

Branch coverage included in aggregate %.

10202 of 14011 relevant lines covered (72.81%)

3.15 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

73.53
cli/src/main/java/com/devonfw/tools/ide/tool/python/Python.java
1
package com.devonfw.tools.ide.tool.python;
2

3
import java.nio.file.Files;
4
import java.nio.file.Path;
5
import java.nio.file.StandardCopyOption;
6
import java.util.Set;
7

8
import com.devonfw.tools.ide.cli.CliException;
9
import com.devonfw.tools.ide.common.Tag;
10
import com.devonfw.tools.ide.context.IdeContext;
11
import com.devonfw.tools.ide.io.FileAccess;
12
import com.devonfw.tools.ide.process.EnvironmentContext;
13
import com.devonfw.tools.ide.tool.LocalToolCommandlet;
14
import com.devonfw.tools.ide.tool.ToolCommandlet;
15
import com.devonfw.tools.ide.tool.ToolInstallRequest;
16
import com.devonfw.tools.ide.tool.ToolInstallation;
17
import com.devonfw.tools.ide.tool.uv.Uv;
18
import com.devonfw.tools.ide.version.VersionIdentifier;
19

20
/**
21
 * {@link ToolCommandlet} for <a href="https://www.python.org/">python</a>.
22
 */
23
public class Python extends LocalToolCommandlet {
24

25
  private final VersionIdentifier PYTHON_MIN_VERSION = VersionIdentifier.of("3.8.2");
4✔
26

27
  /**
28
   * The constructor.
29
   *
30
   * @param context the {@link IdeContext}.
31
   */
32
  public Python(IdeContext context) {
33

34
    super(context, "python", Set.of(Tag.PYTHON));
6✔
35
  }
1✔
36

37
  @Override
38
  protected VersionIdentifier performToolInstallation(ToolInstallRequest request, Path installationPath, VersionIdentifier resolvedVersion) {
39

40
    if (resolvedVersion.compareVersion(PYTHON_MIN_VERSION).isLess()) {
6!
41
      throw new CliException("Python version must be at least " + this.PYTHON_MIN_VERSION);
×
42
    }
43

44
    FileAccess fileAccess = this.context.getFileAccess();
4✔
45
    if (Files.exists(installationPath)) {
5!
46
      fileAccess.backup(installationPath);
×
47
    }
48
    Path softwarePath = installationPath.getParent();
3✔
49
    Uv uv = this.context.getCommandletManager().getCommandlet(Uv.class);
7✔
50

51
    uv.installPython(softwarePath, resolvedVersion, request.getProcessContext());
6✔
52
    renameVenvFolderToPython(fileAccess, softwarePath, installationPath);
5✔
53
    this.context.writeVersionFile(resolvedVersion, installationPath);
5✔
54
    createWindowsSymlinkBinFolder(fileAccess, installationPath);
4✔
55
    return resolvedVersion;
2✔
56
  }
57

58
  @Override
59
  public void setEnvironment(EnvironmentContext environmentContext, ToolInstallation toolInstallation, boolean additionalInstallation) {
60

61
    super.setEnvironment(environmentContext, toolInstallation, additionalInstallation);
5✔
62
    environmentContext.withEnvVar("VIRTUAL_ENV", toolInstallation.rootDir().toString());
7✔
63
  }
1✔
64

65
  @Override
66
  protected boolean isIgnoreSoftwareRepo() {
67

68
    return true;
2✔
69
  }
70

71
  /**
72
   * Creates a symlink from the "Scripts" folder to the "bin" folder on Windows systems. This is necessary for compatibility with tools that expect a "bin"
73
   * directory.
74
   *
75
   * @param fileAccess the {@link FileAccess} utility for file operations.
76
   * @param installationPath the path where Python is installed.
77
   */
78
  private void createWindowsSymlinkBinFolder(FileAccess fileAccess, Path installationPath) {
79

80
    if (!this.context.getSystemInfo().isWindows()) {
5!
81
      return;
1✔
82
    }
83
    Path scriptsPath = installationPath.resolve("Scripts");
×
84
    Path binPath = installationPath.resolve("bin");
×
85
    fileAccess.symlink(scriptsPath, binPath);
×
86
  }
×
87

88
  /**
89
   * Renames the ".venv" folder into the installation path (Python).
90
   *
91
   * @param fileAccess the {@link FileAccess} utility for file operations.
92
   * @param softwarePath the path where the software is installed.
93
   * @param installationPath the target path where the ".venv" folder should be moved.
94
   */
95
  private void renameVenvFolderToPython(FileAccess fileAccess, Path softwarePath, Path installationPath) {
96

97
    Path venvPath = softwarePath.resolve(".venv");
4✔
98
    fileAccess.move(venvPath, installationPath, StandardCopyOption.REPLACE_EXISTING);
10✔
99
  }
1✔
100

101
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc