promer
December 13, 2023, 11:02pm
1
On macOS, I found that a problem with jsonschema-4.20.0 can sometimes keep JupyterLab from starting.
This can happen after a new install if enough time pass for macOS to write a copy of ‘.DS_Store’ to one of the folders created when ‘jsonschema’ is installed. To replicate this issue, see the details here:
opened 10:38PM - 13 Dec 23 UTC
# Version
For 'jsonschema-4.20.0-py3-none-any.whl', there is a race condition … on macOS that can cause an import of the library to fail. I encountered this because JupyterLab depends on jsonschema and in some cases the failed import prevented JupyterLab from starting. I have not tested earlier versions of this library.
# To Replicate on macOS
1. Create a new virtual environment. (I used Python 3.11.7 and venv but these probably do not matter). Activate the virtual environment and update pip.
2. `python3 -m pip install jsonschema`
3. Change into `.venv/lib/python3.11/site-packages/jsonschema_specifications/schemas`
4. Wait until macOS writes `.DS_store` into this directory so a listing looks like:
```
-rw-r--r--@ 1 xxxxx staff 6.0K Dec 13 16:15 .DS_Store
drwxr-xr-x 4 xxxxx staff 128B Dec 13 16:15 draft201909
drwxr-xr-x 4 xxxxx staff 128B Dec 13 16:15 draft202012
drwxr-xr-x 3 xxxxx staff 96B Dec 13 16:15 draft3
drwxr-xr-x 3 xxxxx staff 96B Dec 13 16:15 draft4
drwxr-xr-x 3 xxxxx staff 96B Dec 13 16:15 draft6
drwxr-xr-x 3 xxxxx staff 96B Dec 13 16:15 draft7
```
5. Start the python interpreter and run the command `import jsonschema`.
6. Result:
```
>>> import jsonschema
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/Users/home/t/.venv/lib/python3.11/site-packages/jsonschema/__init__.py", line 16, in <module>
from jsonschema.validators import (
File "/Users/home/t/.venv/lib/python3.11/site-packages/jsonschema/validators.py", line 19, in <module>
from jsonschema_specifications import REGISTRY as SPECIFICATIONS
File "/Users/home/t/.venv/lib/python3.11/site-packages/jsonschema_specifications/__init__.py", line 10, in <module>
REGISTRY = (_schemas() @ _EMPTY_REGISTRY).crawl()
~~~~~~~~~~~^~~~~~~~~~~~~~~~~
File "/Users/home/t/.venv/lib/python3.11/site-packages/referencing/_core.py", line 379, in __rmatmul__
for resource in new:
File "/Users/home/t/.venv/lib/python3.11/site-packages/jsonschema_specifications/_core.py", line 28, in _schemas
for child in version.iterdir():
File "/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/pathlib.py", line 931, in iterdir
for name in os.listdir(self):
^^^^^^^^^^^^^^^^
NotADirectoryError: [Errno 20] Not a directory: '/Users/home/t/.venv/lib/python3.11/site-packages/jsonschema_specifications/schemas/.DS_Store'
```
# Likely Cause
Line 28 in `_schemas` from 'jsonschema_specifications/_core.py' uses the pathlib method `.iterdir()`. It treats '.DS_Store' as a file just like any other. The surrounding code assumes that all the files in this directory are schemas, which will be true on any other operating system so no error will show up on any other OS.
Even on macOS, the code will work just fine if it is tested so soon after the installation of the package that macOS has not yet created the '.DS_Store' file for the folder. In effect, macOS has a built in race condition that makes it difficult to test for the issue that shows up here, which is failing to handle the case that can only happen on macOS where `.iterdir()` returns a file 'DS_Store' that the OS has written into a directory.
People who write code on other operating systems might reasonably ask why they have to remember to handle a case that they will never see and cannot reproduce. From their perspective, it might be more reasonable to change pathlib so that the new default is to have `.iterdir()` not return '.DS.Store' on macOS unless some visible new parameter is set to force it to do so.
One work-around might be to delete the ‘.DS_Store’ file from the schema folder where it generates the error and start Jupyter Lab quickly. I confirmed that it is sufficient to delete all of the '.DS_Store` files from the site-packages folder and then start soon thereafter.
Once JupyterLab starts successfully, caching (perhaps of imports) seems to prevent the problem even after macOS creates a new version of ‘DS.Store’ in the folder.
1 Like