|
91 | 91 | " # To fix cached path finders\n",
|
92 | 92 | " sys.path_importer_cache.clear()"
|
93 | 93 | ]
|
94 |
| - }, |
95 |
| - { |
96 |
| - "cell_type": "markdown", |
97 |
| - "id": "6dd8802c-5265-4e1e-b520-c1fb5855bf26", |
98 |
| - "metadata": { |
99 |
| - "editable": true, |
100 |
| - "slideshow": { |
101 |
| - "slide_type": "" |
102 |
| - }, |
103 |
| - "tags": [] |
104 |
| - }, |
105 |
| - "source": [ |
106 |
| - "We will want to lazily load the notebook loader factory so that the Python startup is not adversely affected by importing nbconvert et al. However, IPyKernel puts the working directory on the `sys.path` by default, which causes problems if any notebooks shadow built-in packages. Although this also holds for regular Python files in the working directory, in practice this behaviour is not desirable, so we choose to (opt-out) remove the working directory from the path using a meta path finder." |
107 |
| - ] |
108 |
| - }, |
109 |
| - { |
110 |
| - "cell_type": "code", |
111 |
| - "execution_count": 4, |
112 |
| - "id": "ee0b40e3-cbea-4d11-9a32-75c7bc510844", |
113 |
| - "metadata": { |
114 |
| - "editable": true, |
115 |
| - "slideshow": { |
116 |
| - "slide_type": "" |
117 |
| - }, |
118 |
| - "tags": [ |
119 |
| - "export" |
120 |
| - ] |
121 |
| - }, |
122 |
| - "outputs": [], |
123 |
| - "source": [ |
124 |
| - "class IPyKernelPathRestrictor:\n", |
125 |
| - " ... " |
126 |
| - ] |
127 |
| - }, |
128 |
| - { |
129 |
| - "cell_type": "code", |
130 |
| - "execution_count": 5, |
131 |
| - "id": "daf09e61-74ff-4b3f-aaad-6994a8ff5460", |
132 |
| - "metadata": { |
133 |
| - "editable": true, |
134 |
| - "slideshow": { |
135 |
| - "slide_type": "" |
136 |
| - }, |
137 |
| - "tags": [ |
138 |
| - "export" |
139 |
| - ] |
140 |
| - }, |
141 |
| - "outputs": [], |
142 |
| - "source": [ |
143 |
| - "@patch(IPyKernelPathRestrictor)\n", |
144 |
| - "@classmethod\n", |
145 |
| - "def remove_cwd_from_sys_path(cls):\n", |
146 |
| - " cwd = os.path.realpath(os.getcwd())\n", |
147 |
| - " # TODO: should this only remove the first instance?\n", |
148 |
| - " sys.path = [p for p in sys.path if os.path.realpath(p) != cwd]" |
149 |
| - ] |
150 |
| - }, |
151 |
| - { |
152 |
| - "cell_type": "code", |
153 |
| - "execution_count": 6, |
154 |
| - "id": "2e493732-a88d-43fb-9d03-a291e3d5c1f4", |
155 |
| - "metadata": { |
156 |
| - "editable": true, |
157 |
| - "slideshow": { |
158 |
| - "slide_type": "" |
159 |
| - }, |
160 |
| - "tags": [ |
161 |
| - "export" |
162 |
| - ] |
163 |
| - }, |
164 |
| - "outputs": [], |
165 |
| - "source": [ |
166 |
| - "@patch(IPyKernelPathRestrictor)\n", |
167 |
| - "@classmethod\n", |
168 |
| - "def find_spec(cls, fullname, path=None, target=None):\n", |
169 |
| - " if \".\" in fullname:\n", |
170 |
| - " return None\n", |
171 |
| - "\n", |
172 |
| - " # IPython controls the kernel startup including its path\n", |
173 |
| - " # The user cannot easily modify this. \n", |
174 |
| - " # Instead, we wait for an ipykernel import event to trigger this logic to clean up \n", |
175 |
| - " # during initialisation, to avoid problems of name shadowing in the cwd\n", |
176 |
| - " name = fullname.split(\".\", 1)[0]\n", |
177 |
| - " if name == \"ipykernel\":\n", |
178 |
| - " cls.remove_cwd_from_sys_path()\n", |
179 |
| - "\n", |
180 |
| - " return None" |
181 |
| - ] |
182 |
| - }, |
183 |
| - { |
184 |
| - "cell_type": "markdown", |
185 |
| - "id": "24ff552e-f91a-4a96-b870-304e1008e648", |
186 |
| - "metadata": { |
187 |
| - "editable": true, |
188 |
| - "slideshow": { |
189 |
| - "slide_type": "" |
190 |
| - }, |
191 |
| - "tags": [] |
192 |
| - }, |
193 |
| - "source": [ |
194 |
| - "Let's make a dedicated installer for this" |
195 |
| - ] |
196 |
| - }, |
197 |
| - { |
198 |
| - "cell_type": "code", |
199 |
| - "execution_count": 7, |
200 |
| - "id": "731fec98-b411-4676-8975-a407e785d1d8", |
201 |
| - "metadata": { |
202 |
| - "tags": [ |
203 |
| - "export" |
204 |
| - ] |
205 |
| - }, |
206 |
| - "outputs": [], |
207 |
| - "source": [ |
208 |
| - "def install_ipykernel_restrictor():\n", |
209 |
| - " for i, finder in enumerate(sys.meta_path):\n", |
210 |
| - " if finder is PathFinder:\n", |
211 |
| - " break\n", |
212 |
| - " else:\n", |
213 |
| - " return\n", |
214 |
| - "\n", |
215 |
| - " sys.meta_path.insert(i, IPyKernelPathRestrictor)" |
216 |
| - ] |
217 | 94 | }
|
218 | 95 | ],
|
219 | 96 | "metadata": {
|
|
0 commit comments