|
102 | 102 | "leave it be." |
103 | 103 | ] |
104 | 104 | }, |
105 | | - { |
106 | | - "cell_type": "code", |
107 | | - "execution_count": null, |
108 | | - "id": "5fec10da", |
109 | | - "metadata": {}, |
110 | | - "outputs": [], |
111 | | - "source": [ |
112 | | - "mkdir ~/converter_tutorial" |
113 | | - ] |
114 | | - }, |
115 | | - { |
116 | | - "cell_type": "code", |
117 | | - "execution_count": null, |
118 | | - "id": "3b1e163f", |
119 | | - "metadata": {}, |
120 | | - "outputs": [], |
121 | | - "source": [ |
122 | | - "cd ~/converter_tutorial" |
123 | | - ] |
124 | | - }, |
125 | | - { |
126 | | - "cell_type": "code", |
127 | | - "execution_count": null, |
128 | | - "id": "06a42933", |
129 | | - "metadata": {}, |
130 | | - "outputs": [], |
131 | | - "source": [ |
132 | | - "# Record current directory for restarts\n", |
133 | | - "import os\n", |
134 | | - "curdir = os.getcwd()\n", |
135 | | - "print(curdir)" |
136 | | - ] |
137 | | - }, |
138 | | - { |
139 | | - "cell_type": "code", |
140 | | - "execution_count": null, |
141 | | - "id": "0ae4a184", |
142 | | - "metadata": {}, |
143 | | - "outputs": [], |
144 | | - "source": [ |
145 | | - "mkdir mfconverter" |
146 | | - ] |
147 | | - }, |
148 | | - { |
149 | | - "cell_type": "code", |
150 | | - "execution_count": null, |
151 | | - "id": "46d22a46", |
152 | | - "metadata": {}, |
153 | | - "outputs": [], |
154 | | - "source": [ |
155 | | - "cd mfconverter" |
156 | | - ] |
157 | | - }, |
158 | | - { |
159 | | - "cell_type": "code", |
160 | | - "execution_count": null, |
161 | | - "id": "a980c3f9", |
162 | | - "metadata": {}, |
163 | | - "outputs": [], |
164 | | - "source": [ |
165 | | - "mkdir src" |
166 | | - ] |
167 | | - }, |
168 | | - { |
169 | | - "cell_type": "code", |
170 | | - "execution_count": null, |
171 | | - "id": "8dbb76d3", |
172 | | - "metadata": {}, |
173 | | - "outputs": [], |
174 | | - "source": [ |
175 | | - "mkdir src/mfconverter" |
176 | | - ] |
177 | | - }, |
178 | 105 | { |
179 | 106 | "cell_type": "markdown", |
180 | 107 | "id": "ede348bd", |
|
183 | 110 | "And now we will create a module that has a very, very simple photo ID class and add a package `__init__.py`" |
184 | 111 | ] |
185 | 112 | }, |
186 | | - { |
187 | | - "cell_type": "code", |
188 | | - "execution_count": null, |
189 | | - "id": "f045f111", |
190 | | - "metadata": {}, |
191 | | - "outputs": [], |
192 | | - "source": [ |
193 | | - "%%writefile src/mfconverter/photo_id.py\n", |
194 | | - "class PhotoID:\n", |
195 | | - " \"Holds Photo ID information\"\n", |
196 | | - "\n", |
197 | | - " def __init__(self, last_name, first_name, photo):\n", |
198 | | - " \"expects a monochromatic numpy array for photo\"\n", |
199 | | - " self.last_name = last_name\n", |
200 | | - " self.first_name = first_name\n", |
201 | | - " self.photo = photo\n", |
202 | | - " \n", |
203 | | - " def name(self):\n", |
204 | | - " return self.last_name + ', ' + self.first_name" |
205 | | - ] |
206 | | - }, |
207 | | - { |
208 | | - "cell_type": "code", |
209 | | - "execution_count": null, |
210 | | - "id": "ad205d2e", |
211 | | - "metadata": {}, |
212 | | - "outputs": [], |
213 | | - "source": [ |
214 | | - "%%writefile src/__init__.py\n", |
215 | | - "\n" |
216 | | - ] |
217 | | - }, |
218 | 113 | { |
219 | 114 | "cell_type": "markdown", |
220 | 115 | "id": "09ee1385", |
|
223 | 118 | "Next we create the file that contains the converter code" |
224 | 119 | ] |
225 | 120 | }, |
226 | | - { |
227 | | - "cell_type": "code", |
228 | | - "execution_count": null, |
229 | | - "id": "aa345e79", |
230 | | - "metadata": {}, |
231 | | - "outputs": [], |
232 | | - "source": [ |
233 | | - "%%writefile src/mfconverter/converter.py\n", |
234 | | - "from asdf.extension import Converter\n", |
235 | | - "\n", |
236 | | - "class PhotoIDConverter(Converter):\n", |
237 | | - " tags = [\"asdf://stsci.edu/example-project/tags/photo_id-*\"]\n", |
238 | | - " types = [\"mfconverter.photo_id.PhotoID\"]\n", |
239 | | - " # The above registers the tag that the converter is used for, as well as\n", |
240 | | - " # associating the class that the converter is used for.\n", |
241 | | - " \n", |
242 | | - " # This method converts from the Python object to yaml\n", |
243 | | - " def to_yaml_tree(self, obj, tags, ctx):\n", |
244 | | - " # The yaml conversion expects a dictionary returned\n", |
245 | | - " node = {}\n", |
246 | | - " node['first_name'] = obj.first_name\n", |
247 | | - " node['last_name'] = obj.last_name\n", |
248 | | - " node['photo'] = obj.photo\n", |
249 | | - " return node\n", |
250 | | - " \n", |
251 | | - " # This method converts from yaml to the Python object\n", |
252 | | - " def from_yaml_tree(self, node, tag, ctx):\n", |
253 | | - " from .photo_id import PhotoID # Deferred import to avoid always importing \n", |
254 | | - " # when ASDF gets entry points.\n", |
255 | | - " return PhotoID(node['last_name'],\n", |
256 | | - " node['first_name'],\n", |
257 | | - " node['photo'])" |
258 | | - ] |
259 | | - }, |
260 | 121 | { |
261 | 122 | "cell_type": "markdown", |
262 | 123 | "id": "55ca30cd", |
|
278 | 139 | "We need to create a module for the entry point handling" |
279 | 140 | ] |
280 | 141 | }, |
281 | | - { |
282 | | - "cell_type": "code", |
283 | | - "execution_count": null, |
284 | | - "id": "f9c03910", |
285 | | - "metadata": {}, |
286 | | - "outputs": [], |
287 | | - "source": [ |
288 | | - "%%writefile src/mfconverter/extensions.py\n", |
289 | | - "from asdf.extension import Extension\n", |
290 | | - "from .converter import PhotoIDConverter\n", |
291 | | - "\n", |
292 | | - "class MFExtension(Extension):\n", |
293 | | - " extension_uri = \"asdf://stsci.edu/example-project/photo_id-1.0.0\"\n", |
294 | | - " tags = [\"asdf://stsci.edu/example-project/tags/photo_id-1.0.0\"]\n", |
295 | | - " converters = [PhotoIDConverter()]\n", |
296 | | - "\n", |
297 | | - "# The following will be called by ASDF when looking for ASDF entry points \n", |
298 | | - "def get_extensions():\n", |
299 | | - " return [MFExtension()]" |
300 | | - ] |
301 | | - }, |
302 | 142 | { |
303 | 143 | "cell_type": "markdown", |
304 | 144 | "id": "412c3e4f", |
|
307 | 147 | "And finally, the entry point reference in setup.cfg, provided here as a whole file." |
308 | 148 | ] |
309 | 149 | }, |
310 | | - { |
311 | | - "cell_type": "code", |
312 | | - "execution_count": null, |
313 | | - "id": "feb206d7", |
314 | | - "metadata": {}, |
315 | | - "outputs": [], |
316 | | - "source": [ |
317 | | - "%%writefile pyproject.toml\n", |
318 | | - "[project]\n", |
319 | | - "name = \"mfconverter\"\n", |
320 | | - "description = \"TODO\"\n", |
321 | | - "version='0.1.0'\n", |
322 | | - "requires-python = \">=3.9\"\n", |
323 | | - "dependencies = [\n", |
324 | | - " \"jsonschema >=3.0.2\",\n", |
325 | | - " \"asdf >=2.8\",\n", |
326 | | - " \"psutil >=5.7.2\",\n", |
327 | | - " \"numpy>=1.16\",\n", |
328 | | - "]\n", |
329 | | - "\n", |
330 | | - "[build-system]\n", |
331 | | - "requires = [\"setuptools >=61\", \"setuptools_scm[toml] >=3.4\"]\n", |
332 | | - "build-backend = \"setuptools.build_meta\"\n", |
333 | | - "\n", |
334 | | - "[project.entry-points.\"asdf.extensions\"]\n", |
335 | | - "mfconverter = \"mfconverter.extensions:get_extensions\"\n", |
336 | | - "\n", |
337 | | - "[tool.setuptools.packages.find]\n", |
338 | | - "where = [\"src\"]" |
339 | | - ] |
340 | | - }, |
341 | 150 | { |
342 | 151 | "cell_type": "markdown", |
343 | 152 | "id": "8d0e3882", |
|
349 | 158 | "We need the setup.py file too" |
350 | 159 | ] |
351 | 160 | }, |
352 | | - { |
353 | | - "cell_type": "code", |
354 | | - "execution_count": null, |
355 | | - "id": "3ffb22d6", |
356 | | - "metadata": {}, |
357 | | - "outputs": [], |
358 | | - "source": [ |
359 | | - "%%writefile setup.py\n", |
360 | | - "#!/usr/bin/env python3\n", |
361 | | - "from setuptools import setup\n", |
362 | | - "\n", |
363 | | - "setup()" |
364 | | - ] |
365 | | - }, |
366 | 161 | { |
367 | 162 | "cell_type": "markdown", |
368 | 163 | "id": "b7628aaa", |
369 | 164 | "metadata": {}, |
370 | 165 | "source": [ |
371 | 166 | "Install package\n", |
372 | | - "------------------\n", |
373 | | - "\n", |
374 | | - "This is best done from a terminal window using the command\n", |
375 | | - "\n", |
376 | | - "`pip install --editable .`\n", |
377 | | - "\n", |
378 | | - "But this notebook will do that, but a consequence is that if the reinstallation must be done, the Jupyter kernel must be restarted to pick up the new installation." |
| 167 | + "------------------" |
379 | 168 | ] |
380 | 169 | }, |
381 | 170 | { |
|
385 | 174 | "metadata": {}, |
386 | 175 | "outputs": [], |
387 | 176 | "source": [ |
388 | | - "!pip install --editable ." |
| 177 | + "!pip install ./Your_first_ASDF_converter" |
389 | 178 | ] |
390 | 179 | }, |
391 | 180 | { |
|
539 | 328 | "name": "python", |
540 | 329 | "nbconvert_exporter": "python", |
541 | 330 | "pygments_lexer": "ipython3", |
542 | | - "version": "3.10.10" |
| 331 | + "version": "3.13.4" |
543 | 332 | } |
544 | 333 | }, |
545 | 334 | "nbformat": 4, |
|
0 commit comments