Skip to content

Commit e95028b

Browse files
committed
addon: Install with conda (if possible)
1 parent dcc5826 commit e95028b

File tree

1 file changed

+57
-13
lines changed

1 file changed

+57
-13
lines changed

Orange/canvas/application/addons.py

Lines changed: 57 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -756,6 +756,7 @@ def __init__(self, parent=None, steps=[], user_install=False):
756756
self.__interupt = False
757757
self.__queue = deque(steps)
758758
self.pip = PipInstaller(user_install)
759+
self.conda = CondaInstaller()
759760

760761
def start(self):
761762
QTimer.singleShot(0, self._next)
@@ -774,14 +775,20 @@ def _next(self):
774775
if command == Install:
775776
self.setStatusMessage(
776777
"Installing {}".format(pkg.installable.name))
778+
if self.conda:
779+
self.conda.install(pkg.installable)
777780
self.pip.install(pkg.installable)
778781
elif command == Upgrade:
779782
self.setStatusMessage(
780783
"Upgrading {}".format(pkg.installable.name))
784+
if self.conda:
785+
self.conda.upgrade(pkg.installable)
781786
self.pip.upgrade(pkg.installable)
782787
elif command == Uninstall:
783788
self.setStatusMessage(
784789
"Uninstalling {}".format(pkg.local.project_name))
790+
if self.conda:
791+
self.conda.uninstall(pkg.local)
785792
self.pip.uninstall(pkg.local)
786793
except CommandFailed as ex:
787794
self.error.emit(
@@ -801,7 +808,7 @@ def __init__(self, user_install=False):
801808
self.user_install = user_install
802809

803810
def install(self, pkg):
804-
cmd = ["-m", "pip", "install"]
811+
cmd = ["python", "-m", "pip", "install"]
805812
if self.user_install:
806813
cmd.append("--user")
807814
cmd.append(pkg.name)
@@ -815,15 +822,15 @@ def upgrade(self, package):
815822
self.install(package)
816823

817824
def upgrade_no_deps(self, package):
818-
cmd = ["-m", "pip", "install", "--upgrade", "--no-deps"]
825+
cmd = ["python", "-m", "pip", "install", "--upgrade", "--no-deps"]
819826
if self.user_install:
820827
cmd.append("--user")
821828
cmd.append(package.name)
822829

823830
run_command(cmd)
824831

825832
def uninstall(self, dist):
826-
cmd = ["-m", "pip", "uninstall", "--yes", dist.project_name]
833+
cmd = ["python", "-m", "pip", "uninstall", "--yes", dist.project_name]
827834
run_command(cmd)
828835

829836
if self.user_install:
@@ -852,13 +859,40 @@ def manual_uninstall(self, dist):
852859
os.unlink(match)
853860

854861

862+
class CondaInstaller:
863+
def __init__(self):
864+
executable = sys.executable
865+
bin = os.path.dirname(executable)
866+
conda = os.path.join(bin, "conda")
867+
self.conda = conda if os.path.exists(conda) else None
868+
869+
def install(self, pkg):
870+
cmd = ["conda", "install", "--yes", pkg.name]
871+
run_command(cmd, raise_on_fail=False)
872+
873+
def upgrade(self, pkg):
874+
cmd = ["conda", "upgrade", "--yes", pkg.name]
875+
run_command(cmd, raise_on_fail=False)
876+
877+
def uninstall(self, dist):
878+
cmd = ["conda", "uninstall", "--yes", dist.project_name]
879+
run_command(cmd, raise_on_fail=False)
880+
881+
def __bool__(self):
882+
return bool(self.conda)
883+
884+
855885
def run_command(command, raise_on_fail=True):
856886
"""Run command in a subprocess.
857887
858888
Return `process` return code and output once it completes.
859889
"""
860-
process = python_process(command, bufsize=-1, universal_newlines=True,
861-
env=_env_with_proxies())
890+
log.info("Running %s", " ".join(command))
891+
892+
if command[0] == "python":
893+
process = python_process(command[1:])
894+
else:
895+
process = create_process(command)
862896

863897
output = []
864898
while process.poll() is None:
@@ -876,13 +910,16 @@ def run_command(command, raise_on_fail=True):
876910
output.append(line)
877911
print(line, end="")
878912

879-
if raise_on_fail and process.returncode != 0:
880-
raise CommandFailed(command, process.returncode, output)
913+
if process.returncode != 0:
914+
log.info("Command %s failed with %s",
915+
" ".join(command), process.returncode)
916+
if raise_on_fail:
917+
raise CommandFailed(command, process.returncode, output)
881918

882919
return process.returncode, output
883920

884921

885-
def python_process(args, script_name=None, cwd=None, env=None, **kwargs):
922+
def python_process(args, script_name=None, **kwargs):
886923
"""
887924
Run a `sys.executable` in a subprocess with `args`.
888925
"""
@@ -907,14 +944,21 @@ def python_process(args, script_name=None, cwd=None, env=None, **kwargs):
907944
else:
908945
script = executable
909946

910-
process = subprocess.Popen(
947+
return create_process(
911948
[script] + args,
949+
executable=executable
950+
)
951+
952+
953+
def create_process(cmd, executable=None, **kwargs):
954+
return subprocess.Popen(
955+
cmd,
912956
executable=executable,
913-
cwd=cwd,
914-
env=env,
957+
cwd=None,
958+
env=_env_with_proxies(),
915959
stderr=subprocess.STDOUT,
916960
stdout=subprocess.PIPE,
961+
bufsize=-1,
962+
universal_newlines=True,
917963
**kwargs
918964
)
919-
920-
return process

0 commit comments

Comments
 (0)