private @NotNull ProcessHandler executeTargetBasedProcess(@NotNull PyTargetAwareAdditionalData data) throws ExecutionException {
    var helper = myHelper;
    var script = myRunnerScript;
    assert (helper == null) != (script == null) : "Either script or helper must be set but not both";
    PythonScriptExecution execution;
    TargetEnvironmentRequest request;

    var uploadedPaths = new HashMap<@NotNull Path, @NotNull Function<TargetEnvironment, String>>();
    var helpersAwareRequest = PythonInterpreterTargetEnvironmentFactory.findPythonTargetInterpreter(mySdk, myModule.getProject());
    assert helpersAwareRequest != null : data.getClass() + " is not supported";
    if (helper != null) {
      // Special shortcut for helper: use it instead of creating environment request manually
      helpersAwareRequest.preparePyCharmHelpers();
      execution = PythonScripts.prepareHelperScriptExecution(helper, helpersAwareRequest);
    }
    else {
      execution = new PythonScriptExecution();
      // We do not know if script path is local or not, so we only support target script
      execution.setPythonScriptPath(constant(script));
    }
    request = helpersAwareRequest.getTargetEnvironmentRequest();

    customizePythonExecution(helpersAwareRequest, execution, myModule);

    // All paths params must be uploaded before call
    for (int i = 0; i < myParameters.size(); i++) {
      var paramValue = myParameters.get(i);
      var isPath = myPathParameterIndices.contains(i);

      if (isPath) {
        execution.addParameter(addDirToUploadList(request, uploadedPaths, paramValue));
      }
      else {
        execution.addParameter(paramValue);
      }
    }
    // Workdir should also be uploaded
    var workDir = myWorkingDirectory;
    if (workDir != null) {
      execution.setWorkingDir(targetPath(Path.of(workDir)));
    }
    TargetEnvironment environment = request.prepareEnvironment(TargetProgressIndicator.EMPTY);

    setupPythonPath(request, execution);

    var commandLine = PythonScripts.buildTargetedCommandLine(execution, environment, mySdk, new ArrayList<>());

    for (var volume : environment.getUploadVolumes().values()) {
      try {
        volume.upload(".", TargetProgressIndicator.EMPTY);
      }
      catch (IOException e) {
        throw new ExecutionException(e);
      }
    }


    Runnable downloadVolumesAfterProcess = () -> {
      environment.shutdown();
      for (var localRemotePathMapping : uploadedPaths.entrySet()) {
        var targetPath = localRemotePathMapping.getValue().apply(environment);
        var root =
          new TargetEnvironment.DownloadRoot(localRemotePathMapping.getKey(), new TargetEnvironment.TargetPath.Persistent(targetPath));
        request.getDownloadVolumes().add(root);
      }
      try {
        // download paths after call
        var newEnvironment = request.prepareEnvironment(TargetProgressIndicator.EMPTY);
        for (var volume : newEnvironment.getDownloadVolumes().values()) {
          volume.download(".", new EmptyProgressIndicator());
        }
        newEnvironment.shutdown();
      }
      catch (ExecutionException | IOException ex) {
        throw new RuntimeException(ex);
      }
    };


    var handler = new CapturingProcessHandler(environment.createProcess(commandLine, new EmptyProgressIndicator()), StandardCharsets.UTF_8,
                                              commandLine.getCommandPresentation(environment));
    handler.addProcessListener(new OutputListener() {
      @Override
      public void processTerminated(@NotNull ProcessEvent event) {
        ProgressManager.getInstance()
          .runProcessWithProgressSynchronously(downloadVolumesAfterProcess, "...", false, myModule.getProject());
      }
    });
    return handler;
  }
private @NotNull ProcessHandler executeTargetBasedProcess(@NotNull PyTargetAwareAdditionalData data)