Editable install fails in Jupyter notebook
It appears that editable install fails when trying to import the package in Jupyter notebook.
Here is an example:
In my current project, I have a native package (parselmouth) built with the scikit build core (as git submodule) so I can troubleshoot/enhance the custom features that I'd like to have for this project.
In this project's venv, I installed parselmouth by
pip install --no-build-isolation --config-settings=editable.rebuild=true -Cbuild-dir=./build -ve ./parselmouth
Then, in a Python script, I confirm the expected behavior:
import parselmouth
triggers cmake --build and cmake --install at run-time.
In a Jupyter notebook, however, import parselmouth prints
Running cmake --build & --install in [...snipped path...]\parselmouth\build
then leaves the following error:
{
"name": "UnsupportedOperation",
"message": "fileno",
"stack": "---------------------------------------------------------------------------
UnsupportedOperation Traceback (most recent call last)
Cell In[1], line 1
----> 1 import parselmouth
File <frozen importlib._bootstrap>:1176, in _find_and_load(name, import_)
File <frozen importlib._bootstrap>:1138, in _find_and_load_unlocked(name, import_)
File <frozen importlib._bootstrap>:1078, in _find_spec(name, path, target)
File [...snipped path...]\\.venv\\Lib\\site-packages\\_praat_parselmouth_editable.py:94, in ScikitBuildRedirectingFinder.find_spec(self, fullname, path, target)
92 redir = self.known_wheel_files[fullname]
93 if self.rebuild_flag:
---> 94 self.rebuild()
95 return importlib.util.spec_from_file_location(
96 fullname,
97 os.path.join(self.dir, redir),
(...)
100 else None,
101 )
102 if fullname in self.known_source_files:
File [...snipped path...]\\.venv\\Lib\\site-packages\\_praat_parselmouth_editable.py:131, in ScikitBuildRedirectingFinder.rebuild(self)
128 if verbose:
129 print(f\"Running cmake --build & --install in {self.path}\") # noqa: T201
--> 131 result = subprocess.run(
132 [\"cmake\", \"--build\", \".\", *self.build_options],
133 cwd=self.path,
134 stdout=sys.stderr if verbose else subprocess.PIPE,
135 env=env,
136 check=False,
137 text=True,
138 )
139 if result.returncode and verbose:
140 print( # noqa: T201
141 f\"ERROR: {result.stdout}\",
142 file=sys.stderr,
143 )
File ~\\AppData\\Local\\Programs\\Python\\Python311\\Lib\\subprocess.py:548, in run(input, capture_output, timeout, check, *popenargs, **kwargs)
545 kwargs['stdout'] = PIPE
546 kwargs['stderr'] = PIPE
--> 548 with Popen(*popenargs, **kwargs) as process:
549 try:
550 stdout, stderr = process.communicate(input, timeout=timeout)
File ~\\AppData\\Local\\Programs\\Python\\Python311\\Lib\\subprocess.py:992, in Popen.__init__(self, args, bufsize, executable, stdin, stdout, stderr, preexec_fn, close_fds, shell, cwd, env, universal_newlines, startupinfo, creationflags, restore_signals, start_new_session, pass_fds, user, group, extra_groups, encoding, errors, text, umask, pipesize, process_group)
973 raise ValueError(f\"User ID cannot be negative, got {uid}\")
975 # Input and output objects. The general principle is like
976 # this:
977 #
(...)
987 # are -1 when not using PIPEs. The child objects are -1
988 # when not redirecting.
990 (p2cread, p2cwrite,
991 c2pread, c2pwrite,
--> 992 errread, errwrite) = self._get_handles(stdin, stdout, stderr)
994 # From here on, raising exceptions may cause file descriptor leakage
995
996 # We wrap OS handles *before* launching the child, otherwise a
997 # quickly terminating child could make our fds unwrappable
998 # (see #8458).
1000 if _mswindows:
File ~\\AppData\\Local\\Programs\\Python\\Python311\\Lib\\subprocess.py:1384, in Popen._get_handles(self, stdin, stdout, stderr)
1381 c2pwrite = msvcrt.get_osfhandle(stdout)
1382 else:
1383 # Assuming file-like object
-> 1384 c2pwrite = msvcrt.get_osfhandle(stdout.fileno())
1385 c2pwrite = self._make_inheritable(c2pwrite)
1387 if stderr is None:
File [...snipped path...]\\.venv\\Lib\\site-packages\\ipykernel\\iostream.py:371, in OutStream.fileno(self)
369 return self._original_stdstream_copy
370 msg = \"fileno\"
--> 371 raise io.UnsupportedOperation(msg)
UnsupportedOperation: fileno"
}
I'd be happy to provide additional information.
Can you try editable.verbose = false? Looks like iPython is taking over the output streams and not handling them correctly.
Yes, this worked:
pip install --no-build-isolation --config-settings=editable.rebuild=true --config-settings=editable.verbose=false -Cbuild-dir=./build -ve ./parselmouth
Thanks!