Skip to content

Commit aeeaec0

Browse files
authored
Merge pull request #30 from janschulz/rkernel_improvements
Rkernel improvements
2 parents 19f1fdd + 1781be1 commit aeeaec0

File tree

4 files changed

+37
-23
lines changed

4 files changed

+37
-23
lines changed

environment_kernels/core.py

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ class EnvironmentKernelSpecManager(KernelSpecManager):
3333

3434
# Check for the CONDA_ENV_PATH variable and add it to the list if set.
3535
if os.environ.get('CONDA_ENV_PATH', False):
36-
_default_conda_dirs.append(os.environ['CONDA_ENV_PATH'].split('envs')[0])
36+
_default_conda_dirs.append(os.environ['CONDA_ENV_PATH'].split('envs')[0])
3737

3838
# If we are running inside the root conda env can get all the env dirs:
3939
if HAVE_CONDA:
@@ -106,13 +106,15 @@ class EnvironmentKernelSpecManager(KernelSpecManager):
106106
def __init__(self, *args, **kwargs):
107107
super(EnvironmentKernelSpecManager, self).__init__(*args, **kwargs)
108108
self.log.info("Using EnvironmentKernelSpecManager...")
109+
self._env_data_cache = {}
109110
if self.refresh_interval > 0:
110111
try:
111112
from tornado.ioloop import PeriodicCallback, IOLoop
112113
# Initial loading NOW
113-
IOLoop.current().call_later(0, callback=self._update_env_data)
114+
IOLoop.current().call_later(0, callback=self._update_env_data, initial=True)
114115
# Later updates
115-
updater = PeriodicCallback(callback=self._update_env_data, callback_time=1000 * 60 * self.refresh_interval)
116+
updater = PeriodicCallback(callback=self._update_env_data,
117+
callback_time=1000 * 60 * self.refresh_interval)
116118
updater.start()
117119
if not updater.is_running():
118120
raise Exception()
@@ -141,10 +143,13 @@ def validate_env(self, envname):
141143
else:
142144
return True
143145

144-
def _update_env_data(self):
145-
self.log.info("Starting periodic scan of virtual environments...")
146+
def _update_env_data(self, initial=False):
147+
if initial:
148+
self.log.info("Starting initial scan of virtual environments...")
149+
else:
150+
self.log.debug("Starting periodic scan of virtual environments...")
146151
self._get_env_data(reload=True)
147-
self.log.debug("done...")
152+
self.log.debug("done.")
148153

149154
def _get_env_data(self, reload=False):
150155
"""Get the data about the available environments.
@@ -153,16 +158,17 @@ def _get_env_data(self, reload=False):
153158
"""
154159

155160
# This is called much too often and finding-process is really expensive :-(
156-
if not reload and hasattr(self, "_env_data_cache"):
161+
if not reload and getattr(self, "_env_data_cache", {}):
157162
return getattr(self, "_env_data_cache")
158163

159164
env_data = {}
160165
for supplyer in ENV_SUPPLYER:
161166
env_data.update(supplyer(self))
162167

163168
env_data = {name: env_data[name] for name in env_data if self.validate_env(name)}
164-
self.log.info("Found the following kernels in environments: %s",
165-
", ".join(list(env_data)))
169+
new_kernels = env_data.keys() - self._env_data_cache.keys()
170+
if new_kernels:
171+
self.log.info("Found new kernels in environments: %s", ", ".join(new_kernels))
166172

167173
self._env_data_cache = env_data
168174
return env_data

environment_kernels/envs_common.py

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,9 @@ def convert_to_env_data(mgr, env_paths, validator_func, activate_func,
3333
kernel_name = name_template.format(name_prefix + venv_name)
3434
kernel_name = kernel_name.lower()
3535
if kernel_name in env_data:
36-
mgr.log.error(
37-
"Duplicate env kernels: %s would both point to %s and %s. Using the first!",
38-
kernel_name, env_data[kernel_name], venv_dir)
36+
mgr.log.debug(
37+
"Found duplicate env kernel: %s, which would again point to %s. Using the first!",
38+
kernel_name, venv_dir)
3939
continue
4040
argv, language, resource_dir = validator_func(venv_dir)
4141
if not argv:
@@ -52,7 +52,7 @@ def convert_to_env_data(mgr, env_paths, validator_func, activate_func,
5252
def loader(env_dir=venv_dir, activate_func=activate_func, mgr=mgr):
5353
mgr.log.debug("Loading env data for %s" % env_dir)
5454
res = activate_func(mgr, env_dir)
55-
#mgr.log.info("PATH: %s" % res['PATH'])
55+
# mgr.log.info("PATH: %s" % res['PATH'])
5656
return res
5757

5858
kspec = EnvironmentLoadingKernelSpec(loader, **kspec_dict)
@@ -100,19 +100,24 @@ def validate_IRkernel(venv_dir):
100100
Returns: tuple
101101
(ARGV, language, resource_dir)
102102
"""
103-
r_exe_name = find_exe(venv_dir, "r")
103+
r_exe_name = find_exe(venv_dir, "R")
104104
if r_exe_name is None:
105105
return [], None, None
106106

107-
# check if this is really an ipython **kernel**
107+
# check if this is really an IRkernel **kernel**
108108
import subprocess
109+
ressources_dir = None
109110
try:
110-
subprocess.check_call([r_exe_name, '--slave', '-e', 'library(IRkernel)'])
111+
print_resources = 'cat(as.character(system.file("kernelspec", package = "IRkernel")))'
112+
resources_dir_bytes = subprocess.check_output([r_exe_name, '--slave', '-e', print_resources])
113+
resources_dir = resources_dir_bytes.decode(errors='ignore')
111114
except:
112115
# not installed? -> not useable in any case...
113116
return [], None, None
114117
argv = [r_exe_name, "--slave", "-e", "IRkernel::main()", "--args", "{connection_file}"]
115-
resources_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), "logos", "r")
118+
if not os.path.exists(resources_dir.strip()):
119+
# Fallback to our own log, but don't get the nice js goodies...
120+
resources_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), "logos", "r")
116121
return argv, "r", resources_dir
117122

118123

environment_kernels/envs_conda.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,14 @@ def get_conda_env_data(mgr):
1515
if not mgr.find_conda_envs:
1616
return {}
1717

18-
mgr.log.info("Looking for conda environments (python)...")
18+
mgr.log.debug("Looking for conda environments in %s...", mgr.conda_env_dirs)
1919

2020
# find all potential env paths
2121
env_paths = find_env_paths_in_basedirs(mgr.conda_env_dirs)
2222
env_paths.extend(_find_conda_env_paths_from_conda(mgr))
2323
env_paths = list(set(env_paths)) # remove duplicates
2424

25+
mgr.log.debug("Scanning conda environments for python kernels...")
2526
env_data = convert_to_env_data(mgr=mgr,
2627
env_paths=env_paths,
2728
validator_func=validate_IPykernel,
@@ -30,7 +31,7 @@ def get_conda_env_data(mgr):
3031
display_name_template=mgr.display_name_template,
3132
name_prefix="") # lets keep the py kernels without a prefix...
3233
if mgr.find_r_envs:
33-
mgr.log.info("Looking for conda environments (R)...")
34+
mgr.log.debug("Scanning conda environments for R kernels...")
3435
env_data.update(convert_to_env_data(mgr=mgr,
3536
env_paths=env_paths,
3637
validator_func=validate_IRkernel,
@@ -66,7 +67,7 @@ def _find_conda_env_paths_from_conda(mgr):
6667
# this is expensive, so make it configureable...
6768
if not mgr.use_conda_directly:
6869
return []
69-
mgr.log.info("Looking for conda environments by calling conda directly...")
70+
mgr.log.debug("Looking for conda environments by calling conda directly...")
7071
import subprocess
7172
import json
7273
try:

environment_kernels/envs_virtualenv.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
from .activate_helper import source_env_vars_from_command
99
from .envs_common import find_env_paths_in_basedirs, convert_to_env_data, validate_IPykernel
1010

11+
1112
def get_virtualenv_env_data(mgr):
1213
"""Finds kernel specs from virtualenv environments
1314
@@ -17,19 +18,20 @@ def get_virtualenv_env_data(mgr):
1718
if not mgr.find_virtualenv_envs:
1819
return {}
1920

20-
mgr.log.info("Looking for virtualenv environments...")
21+
mgr.log.debug("Looking for virtualenv environments in %s...", mgr.virtualenv_env_dirs)
2122

2223
# find all potential env paths
2324
env_paths = find_env_paths_in_basedirs(mgr.virtualenv_env_dirs)
2425

26+
mgr.log.debug("Scanning virtualenv environments for python kernels...")
2527
env_data = convert_to_env_data(mgr=mgr,
2628
env_paths=env_paths,
2729
validator_func=validate_IPykernel,
2830
activate_func=_get_env_vars_for_virtualenv_env,
2931
name_template=mgr.conda_prefix_template,
3032
display_name_template=mgr.display_name_template,
3133
name_prefix="") # virtualenv has only python, so no need for a
32-
# prefix
34+
# prefix
3335
return env_data
3436

3537

@@ -40,7 +42,7 @@ def _get_env_vars_for_virtualenv_env(mgr, env_path):
4042
args = ['source', os.path.join(env_path, "bin", "activate")]
4143
try:
4244
envs = source_env_vars_from_command(args)
43-
#mgr.log.debug("Environment variables: %s", envs)
45+
# mgr.log.debug("Environment variables: %s", envs)
4446
return envs
4547
except:
4648
# as a fallback, don't activate...

0 commit comments

Comments
 (0)