@Override
    public void run(@NotNull ProgressIndicator indicator) {
      if (myProject.isDisposed()) {
        return;
      }
      if (isSdkDisposed()) {
        return;
      }
      // This explicit cancellation should become unnecessary on migrating PythonSdkUpdater to coroutines and withBackgroundProgress
      Disposable indicatorDisposable = getIndicatorDisposable(indicator);
      Disposer.register(PythonPluginDisposable.getInstance(myProject), indicatorDisposable);
      if (Trigger.LOG.isDebugEnabled()) {
        Trigger.LOG.debug(
          "Starting SDK refresh for '" + mySdk.getName() + "' triggered by " + Trigger.getCauseByTrace(myRequestData.myTraceback));
      }
      try {
        if (Registry.get("python.use.targets.api").asBoolean()) {
          PyTargetsIntrospectionFacade targetsFacade = new PyTargetsIntrospectionFacade(mySdk, myProject);
          String version = targetsFacade.getInterpreterVersion(indicator);
          commitSdkVersionIfChanged(mySdk, version);
          if (targetsFacade.isLocalTarget()) {
            List<String> paths = targetsFacade.getInterpreterPaths(indicator);
            updateSdkPaths(mySdk, paths, myProject);
          }
          else {
            targetsFacade.synchronizeRemoteSourcesAndSetupMappings(indicator);
          }
        }
        else {
          updateLocalSdkVersionAndPaths(mySdk, myProject);
        }
        // This step also includes setting mapped interpreter paths
        generateSkeletons(mySdk, indicator);
        refreshPackages(mySdk, indicator);
      }
      catch (InvalidSdkException | ExecutionException e) {
        LOG.warn("Update for SDK " + mySdk.getName() + " failed", e);
      }
      finally {
        ApplicationManager.getApplication().invokeLater(() -> {
          Disposer.dispose(indicatorDisposable);
          // restart code analysis
          DaemonCodeAnalyzer.getInstance(myProject).restart();
        }, myProject.getDisposed());
      }
    }
@Override
    public void run(@NotNull ProgressIndicator indicator)