diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b4515ae..32e8f31 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -8,8 +8,8 @@ on: branches: - main pull_request: - types: - - synchronize + branches: + - main # Only cancel in-progress jobs or runs for the current workflow diff --git a/notebooks/Your_first_ASDF_converter.ipynb b/notebooks/Your_first_ASDF_converter.ipynb index dfdf935..0da5ce0 100644 --- a/notebooks/Your_first_ASDF_converter.ipynb +++ b/notebooks/Your_first_ASDF_converter.ipynb @@ -29,7 +29,7 @@ "a Python object equivalent to the one it started out as.\n", "\n", "Note: The object to be serialized to ASDF must consist\n", - "of only elements that ADSF knows how to serialize. ASDF does\n", + "of only elements that asdf knows how to serialize. asdf does\n", "know how to serialize numpy arrays and all standard \n", "Python primative types (e.g., strings, numbers, booleans,\n", "lists and dictionaries), as well as objects that have \n", @@ -54,18 +54,15 @@ "--------------\n", "\n", "For ASDF to be aware of the converters, it is necessary \n", - "to include in the setup.cfg file information for an entry\n", + "to configure an entry\n", "point for ASDF. Entry points are\n", - "a very useful Python tool for making plug-ins for packages\n", - "easy for users of the plug-in to use, both in the installation\n", + "a useful Python tool for making plug-ins easy for users, both in the installation\n", "and usage aspect.\n", "Entry points remove the need for the core package to be continually \n", "updated with new extension packages that it has to be aware of.\n", "\n", "This information is provided in the converter package's\n", - "setup.cfg (it could be in\n", - "setup.py, but the .cfg file is the usual place to put this\n", - "information). What happens when the package is installed is\n", + "configuration. What happens when the package is installed is\n", "that information about entry points is saved by Python. Python\n", "provides an API to the core package for it to discover what \n", "entry points have been designated for that package so that it can\n", @@ -80,99 +77,7 @@ "We will name the converter package mfconverter (for My First\n", "Converter) so this will create a package of that name in\n", "the current directory. This tutorial will have the bare bones\n", - "files needed for that. The following will generate\n", - "such a barebones directory structure.\n", - "\n", - "Since this tutorial effectively is editing files and needs\n", - "to move between different directories, it is more awkward than\n", - "usual for a notebook\n", - "\n", - "Required Software\n", - "----------------------\n", - "\n", - "- numpy\n", - "- asdf v2.8 or higher\n", - "\n", - "Let's begin\n", - "-------------\n", - "\n", - "This will create a converter_tutorial directory in your home directory.\n", - "If you wish it to be elsewhere, make the appropriate changes to the\n", - "dependent commands, but if there is no strong reason to change it,\n", - "leave it be." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "5fec10da", - "metadata": {}, - "outputs": [], - "source": [ - "mkdir ~/converter_tutorial" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "3b1e163f", - "metadata": {}, - "outputs": [], - "source": [ - "cd ~/converter_tutorial" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "06a42933", - "metadata": {}, - "outputs": [], - "source": [ - "# Record current directory for restarts\n", - "import os\n", - "curdir = os.getcwd()\n", - "print(curdir)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "0ae4a184", - "metadata": {}, - "outputs": [], - "source": [ - "mkdir mfconverter" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "46d22a46", - "metadata": {}, - "outputs": [], - "source": [ - "cd mfconverter" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "a980c3f9", - "metadata": {}, - "outputs": [], - "source": [ - "mkdir src" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "8dbb76d3", - "metadata": {}, - "outputs": [], - "source": [ - "mkdir src/mfconverter" + "files needed for that." ] }, { @@ -180,81 +85,7 @@ "id": "ede348bd", "metadata": {}, "source": [ - "And now we will create a module that has a very, very simple photo ID class and add a package `__init__.py`" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "f045f111", - "metadata": {}, - "outputs": [], - "source": [ - "%%writefile src/mfconverter/photo_id.py\n", - "class PhotoID:\n", - " \"Holds Photo ID information\"\n", - "\n", - " def __init__(self, last_name, first_name, photo):\n", - " \"expects a monochromatic numpy array for photo\"\n", - " self.last_name = last_name\n", - " self.first_name = first_name\n", - " self.photo = photo\n", - " \n", - " def name(self):\n", - " return self.last_name + ', ' + self.first_name" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "ad205d2e", - "metadata": {}, - "outputs": [], - "source": [ - "%%writefile src/__init__.py\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "id": "09ee1385", - "metadata": {}, - "source": [ - "Next we create the file that contains the converter code" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "aa345e79", - "metadata": {}, - "outputs": [], - "source": [ - "%%writefile src/mfconverter/converter.py\n", - "from asdf.extension import Converter\n", - "\n", - "class PhotoIDConverter(Converter):\n", - " tags = [\"asdf://stsci.edu/example-project/tags/photo_id-*\"]\n", - " types = [\"mfconverter.photo_id.PhotoID\"]\n", - " # The above registers the tag that the converter is used for, as well as\n", - " # associating the class that the converter is used for.\n", - " \n", - " # This method converts from the Python object to yaml\n", - " def to_yaml_tree(self, obj, tags, ctx):\n", - " # The yaml conversion expects a dictionary returned\n", - " node = {}\n", - " node['first_name'] = obj.first_name\n", - " node['last_name'] = obj.last_name\n", - " node['photo'] = obj.photo\n", - " return node\n", - " \n", - " # This method converts from yaml to the Python object\n", - " def from_yaml_tree(self, node, tag, ctx):\n", - " from .photo_id import PhotoID # Deferred import to avoid always importing \n", - " # when ASDF gets entry points.\n", - " return PhotoID(node['last_name'],\n", - " node['first_name'],\n", - " node['photo'])" + "The files for `mfconverter` are located in the `Your_first_ASDF_converter` directory alongside this notebook. Please review the files. A few specific details will be highlighted below." ] }, { @@ -262,41 +93,18 @@ "id": "55ca30cd", "metadata": {}, "source": [ - "In the above example, the class attribute `types` is a list since it is\n", + "In `PhotoIDConverter` defined in `converter.py`, the class attribute `types` is a list since it is\n", "possible for multiple types to use the same converter. Secondly, it is\n", "possible to supply the type as either a string (as done above) as the \n", "actual class itself. The former is preferred for peformance reasons as\n", "using the actual class itself forces the ASDF package to import the\n", "module containing the class, even if it is never used in the program\n", - "using ASDF.\n", + "using asdf.\n", "\n", "The wildcard for the tag entry indicates that this converter will work\n", "with all versions of the tag. It isn't strictly needed here, but generally \n", "a good practice if one wants the converter code to handle multiple versions.\n", - "(How to handle versioning is a topic in its own right and not covered here)\n", - "\n", - "We need to create a module for the entry point handling" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "f9c03910", - "metadata": {}, - "outputs": [], - "source": [ - "%%writefile src/mfconverter/extensions.py\n", - "from asdf.extension import Extension\n", - "from .converter import PhotoIDConverter\n", - "\n", - "class MFExtension(Extension):\n", - " extension_uri = \"asdf://stsci.edu/example-project/photo_id-1.0.0\"\n", - " tags = [\"asdf://stsci.edu/example-project/tags/photo_id-1.0.0\"]\n", - " converters = [PhotoIDConverter()]\n", - "\n", - "# The following will be called by ASDF when looking for ASDF entry points \n", - "def get_extensions():\n", - " return [MFExtension()]" + "(How to handle versioning is a topic in its own right and not covered here)" ] }, { @@ -304,63 +112,10 @@ "id": "412c3e4f", "metadata": {}, "source": [ - "And finally, the entry point reference in setup.cfg, provided here as a whole file." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "feb206d7", - "metadata": {}, - "outputs": [], - "source": [ - "%%writefile pyproject.toml\n", - "[project]\n", - "name = \"mfconverter\"\n", - "description = \"TODO\"\n", - "version='0.1.0'\n", - "requires-python = \">=3.9\"\n", - "dependencies = [\n", - " \"jsonschema >=3.0.2\",\n", - " \"asdf >=2.8\",\n", - " \"psutil >=5.7.2\",\n", - " \"numpy>=1.16\",\n", - "]\n", - "\n", - "[build-system]\n", - "requires = [\"setuptools >=61\", \"setuptools_scm[toml] >=3.4\"]\n", - "build-backend = \"setuptools.build_meta\"\n", + "As mentioned above `mfconverter` defines an entry point in the `pyproject.toml` configurate file that is used to register `PhotoIDConverter` with asdf.\n", "\n", - "[project.entry-points.\"asdf.extensions\"]\n", - "mfconverter = \"mfconverter.extensions:get_extensions\"\n", - "\n", - "[tool.setuptools.packages.find]\n", - "where = [\"src\"]" - ] - }, - { - "cell_type": "markdown", - "id": "8d0e3882", - "metadata": {}, - "source": [ "If you wish to learn more about entry points, see:\n", - "https://packaging.python.org/guides/creating-and-discovering-plugins/\n", - "\n", - "We need the setup.py file too" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "3ffb22d6", - "metadata": {}, - "outputs": [], - "source": [ - "%%writefile setup.py\n", - "#!/usr/bin/env python3\n", - "from setuptools import setup\n", - "\n", - "setup()" + "https://packaging.python.org/guides/creating-and-discovering-plugins/" ] }, { @@ -369,13 +124,7 @@ "metadata": {}, "source": [ "Install package\n", - "------------------\n", - "\n", - "This is best done from a terminal window using the command\n", - "\n", - "`pip install --editable .`\n", - "\n", - "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." + "------------------" ] }, { @@ -385,7 +134,7 @@ "metadata": {}, "outputs": [], "source": [ - "!pip install --editable ." + "!pip install ./Your_first_ASDF_converter" ] }, { @@ -539,7 +288,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.10" + "version": "3.13.4" } }, "nbformat": 4, diff --git a/notebooks/Your_first_ASDF_converter/pyproject.toml b/notebooks/Your_first_ASDF_converter/pyproject.toml new file mode 100644 index 0000000..53d2aec --- /dev/null +++ b/notebooks/Your_first_ASDF_converter/pyproject.toml @@ -0,0 +1,18 @@ +[project] +name = "mfconverter" +description = "TODO" +version='0.1.0' +requires-python = ">=3.9" +dependencies = [ + "asdf >=2.8", +] + +[build-system] +requires = ["setuptools >=61", "setuptools_scm[toml] >=3.4"] +build-backend = "setuptools.build_meta" + +[project.entry-points."asdf.extensions"] +mfconverter = "mfconverter.extensions:get_extensions" + +[tool.setuptools.packages.find] +where = ["src"] diff --git a/notebooks/Your_first_ASDF_converter/src/mfconverter/__init__.py b/notebooks/Your_first_ASDF_converter/src/mfconverter/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/notebooks/Your_first_ASDF_converter/src/mfconverter/converter.py b/notebooks/Your_first_ASDF_converter/src/mfconverter/converter.py new file mode 100644 index 0000000..792085f --- /dev/null +++ b/notebooks/Your_first_ASDF_converter/src/mfconverter/converter.py @@ -0,0 +1,24 @@ +from asdf.extension import Converter + +class PhotoIDConverter(Converter): + tags = ["asdf://stsci.edu/example-project/tags/photo_id-*"] + types = ["mfconverter.photo_id.PhotoID"] + # The above registers the tag that the converter is used for, as well as + # associating the class that the converter is used for. + + # This method converts from the Python object to yaml + def to_yaml_tree(self, obj, tags, ctx): + # The yaml conversion expects a dictionary returned + node = {} + node['first_name'] = obj.first_name + node['last_name'] = obj.last_name + node['photo'] = obj.photo + return node + + # This method converts from yaml to the Python object + def from_yaml_tree(self, node, tag, ctx): + from .photo_id import PhotoID # Deferred import to avoid always importing + # when ASDF gets entry points. + return PhotoID(node['last_name'], + node['first_name'], + node['photo']) diff --git a/notebooks/Your_first_ASDF_converter/src/mfconverter/extensions.py b/notebooks/Your_first_ASDF_converter/src/mfconverter/extensions.py new file mode 100644 index 0000000..398f111 --- /dev/null +++ b/notebooks/Your_first_ASDF_converter/src/mfconverter/extensions.py @@ -0,0 +1,11 @@ +from asdf.extension import Extension +from .converter import PhotoIDConverter + +class MFExtension(Extension): + extension_uri = "asdf://stsci.edu/example-project/photo_id-1.0.0" + tags = ["asdf://stsci.edu/example-project/tags/photo_id-1.0.0"] + converters = [PhotoIDConverter()] + +# The following will be called by ASDF when looking for ASDF entry points +def get_extensions(): + return [MFExtension()] diff --git a/notebooks/Your_first_ASDF_converter/src/mfconverter/photo_id.py b/notebooks/Your_first_ASDF_converter/src/mfconverter/photo_id.py new file mode 100644 index 0000000..e6d28d3 --- /dev/null +++ b/notebooks/Your_first_ASDF_converter/src/mfconverter/photo_id.py @@ -0,0 +1,11 @@ +class PhotoID: + "Holds Photo ID information" + + def __init__(self, last_name, first_name, photo): + "expects a monochromatic numpy array for photo" + self.last_name = last_name + self.first_name = first_name + self.photo = photo + + def name(self): + return self.last_name + ', ' + self.first_name diff --git a/notebooks/Your_second_ASDF_converter.ipynb b/notebooks/Your_second_ASDF_converter.ipynb index b3c445e..fe5a84c 100644 --- a/notebooks/Your_second_ASDF_converter.ipynb +++ b/notebooks/Your_second_ASDF_converter.ipynb @@ -44,9 +44,7 @@ "that are not in Python). Doing so adds some added complexity,\n", "so this tutorial is aimed mostly at those that will be writing\n", "schemas for pipeline code that generate products that should\n", - "not intrinsically require Python to read. (A separate tutorial\n", - "may be written for cases where schemas are desired, but only \n", - "for Python).\n", + "not intrinsically require Python to read.\n", "\n", "It takes a bit of effort to understand how to write schemas. \n", "If they seem odd and a bit confusing, that is normal. They \n", @@ -69,117 +67,7 @@ "the schemas are not tied directly to Python; but note there\n", "will be a small amount of code in the schema package for Python,\n", "and we expect that if other languages are used, code for those\n", - "may appear there as well).\n", - "\n", - "A utility has been developed so that the schema package is \n", - "fairly easily generated and this tutorial will use that utility.\n", - "The structure of the converter package will be very similar to\n", - "that of the first tutorial.\n", - "\n", - "Required Software\n", - "---------------------\n", - "\n", - "- numpy\n", - "- asdf v2.8 or higher\n", - "\n", - "The following is recommended when creating your own package but \n", - "not directly needed for this tutorial\n", - "\n", - "- cookiecutter (do a `pip install cookiecutter`)\n", - "\n", - "Software uninstall\n", - "---------------------\n", - "\n", - "If you did the first tutorial (Your_first_ASDF_converter), in a terminal window \n", - "type `pip uninstall mfconverter` since this tutorial will reuse the same \n", - "photoID class and we don't want confusion between the two converters.\n", - "\n", - "Create schema package\n", - "----------------------------\n", - "\n", - "First ensure you are in the directory that you want to create both packages in, by default it will be your home directory below, but change it to what you want before executing." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "bb0c1b6e", - "metadata": {}, - "outputs": [], - "source": [ - "cd ~/converter_tutorial\n" - ] - }, - { - "cell_type": "markdown", - "id": "067eed9a", - "metadata": {}, - "source": [ - "The following utility will build a schema package. It will\n", - "prompt for answers to a series of questions. Here is an \n", - "explanation of what is expected for these questions. **You must\n", - "run this utility from a terminal window.** Type the command as\n", - "shown in this directory and provide the answers as shown below.\n", - "If this is rerun you may get an initial prompt mentioning the\n", - "template has been downloaded before; just type return to accept\n", - "the default `yes`\n", - "\n", - "`\n", - "cookiecutter gh:asdf-format/schemas-package-template\n", - "`\n", - "\n", - "`\n", - "package_name [asdf-example-schemas]: myschemas\n", - "`\n", - "\n", - "This will be the directory name it will go in.\n", - "\n", - "`\n", - "module_name [myschemas]: \n", - "`\n", - "\n", - "Accept the default (providing a different answer will create a\n", - "different module name within the package\n", - "\n", - "`\n", - "Short_description [mfconverter]: my first schemas\n", - "`\n", - "\n", - "Self evident\n", - "\n", - "`\n", - "author_name [Author Name]: Bullwinkle Moose\n", - "`\n", - "\n", - "Provide a phony answer. You don't really want people to know who \n", - "wrote this, do you?\n", - "\n", - "`\n", - "author_email [author@example.com]: bullwinkle@stsci.edu\n", - "`\n", - "\n", - "`\n", - "github_project [github-org/myschemas]: [bullwinkle/myschemas]\n", - "`\n", - "\n", - "This won't actually create a repository on github, but is useful\n", - "if you will add it to github\n", - "\n", - "`\n", - "project_url [https://github.com/bullwinkle/myschemas]]: \n", - "`\n", - "\n", - "`\n", - "uri_authority [example.com]: stsci.edu \n", - "`\n", - "\n", - "`\n", - "uri_project [example-project]:\n", - "`\n", - "\n", - "But since this is jupyter-based, we will do part of what it does\n", - "manually later, partly because editing files within jupyter is \n", - "not simple within the notebook for a tutorial." + "may appear there as well)." ] }, { @@ -192,316 +80,12 @@ "\n", "This will be similar to the first tutorial, but with some changes\n", "the structure. There will be two converters to illustrate how to\n", - "handle multiple converters." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "8564c41d", - "metadata": {}, - "outputs": [], - "source": [ - "mkdir ~/converter_tutorial" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "7e93474e", - "metadata": {}, - "outputs": [], - "source": [ - "cd ~/converter_tutorial" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "7f25df85", - "metadata": {}, - "outputs": [], - "source": [ - "mkdir myconverters" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "e931f085", - "metadata": {}, - "outputs": [], - "source": [ - "pwd" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "3bbc846f", - "metadata": {}, - "outputs": [], - "source": [ - "mkdir myconverters/src" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "a1ca1d34", - "metadata": {}, - "outputs": [], - "source": [ - "mkdir myconverters/src/myconverters" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "978d413d", - "metadata": {}, - "outputs": [], - "source": [ - "cd myconverters" - ] - }, - { - "cell_type": "markdown", - "id": "e94f6849", - "metadata": {}, - "source": [ - "Add the usual files" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "61da8bca", - "metadata": {}, - "outputs": [], - "source": [ - "%%writefile src/myconverters/photo_id.py\n", - "class PhotoID:\n", - " \"Holds Phot ID information\"\n", + "handle multiple converters.\n", "\n", - " def __init__(self, last_name, first_name, image):\n", - " \"expects a monochromatic numpy array for image\"\n", - " self.last_name = last_name\n", - " self.first_name = first_name\n", - " self.photo = image\n", - " \n", - " def name(self):\n", - " return self.last_name + ', ' + self.first_name" - ] - }, - { - "cell_type": "markdown", - "id": "e318f5c2", - "metadata": {}, - "source": [ - "Add a second class that references the first." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "ff6bd411", - "metadata": {}, - "outputs": [], - "source": [ - "%%writefile src/myconverters/traffic_citation.py\n", - "from .photo_id import PhotoID\n", - "\n", - "\n", - "class TrafficCitation:\n", - " \"Record of a traffic violation\"\n", - "\n", - " def __init__(self, ociffer, violation, date, time, photo_id):\n", - " self.ociffer = ociffer\n", - " self.violation = violation\n", - " self.date = date\n", - " self.time = time\n", - " self.photo_id = photo_id" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "482ba07e", - "metadata": {}, - "outputs": [], - "source": [ - "%%writefile src/myconverters/converters.py\n", - "from asdf.extension import Converter\n", - "from .photo_id import PhotoID\n", - "from .traffic_citation import TrafficCitation\n", - "\n", - "\n", - "class PhotoIDConverter(Converter):\n", - " tags = [\"asdf://stsci.edu/example-project/tags/photo_id-*\"]\n", - " types = [\"myconverters.photo_id.PhotoID\"]\n", - " # The above registers the tag that the converter is used for, as well as\n", - " # associating the class that the converter is used for.\n", - "\n", - " # This method converts from the Python object to yaml\n", - " def to_yaml_tree(self, obj, tags, ctx):\n", - " # The yaml conversion expects a dictionary returned\n", - " node = {}\n", - " node['first_name'] = obj.first_name\n", - " node['last_name'] = obj.last_name\n", - " node['photo'] = obj.photo\n", - " return node\n", - "\n", - " # This method converts from yaml to the Python object\n", - " def from_yaml_tree(self, node, tag, ctx):\n", - " return PhotoID(node['last_name'],\n", - " node['first_name'],\n", - " node['photo'])\n", - "\n", - "\n", - "class TrafficCitationConverter(Converter):\n", - " tags = [\"asdf://stsci.edu/example-project/tags/traffic_citation-1.0.0\"]\n", - " types = [\"myconverters.traffic_citation.TrafficCitation\"]\n", - "\n", - " def to_yaml_tree(self, obj, tags, ctx):\n", - " node = {}\n", - " node['ociffer'] = obj.ociffer\n", - " node['violation'] = obj.violation\n", - " node['date'] = obj.date\n", - " node['time'] = obj.time\n", - " node['photo_id'] = obj.photo_id\n", - " return node\n", - "\n", - " def from_yaml_tree(self, node, tag, ctx):\n", - " return TrafficCitation(node['ociffer'],\n", - " node['violation'],\n", - " node['date'],\n", - " node['time'],\n", - " node['photo_id'])" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "6d5ff931", - "metadata": {}, - "outputs": [], - "source": [ - "%%writefile src/myconverters/extensions.py\n", - "from asdf.extension import ManifestExtension\n", - "from .converters import (\n", - " PhotoIDConverter,\n", - " TrafficCitationConverter,)\n", - "\n", - "MY_CONVERTERS = [\n", - " PhotoIDConverter(),\n", - " TrafficCitationConverter(),\n", - "]\n", - "\n", - "MY_EXTENSIONS = [\n", - " ManifestExtension.from_uri(\n", - " \"asdf://stsci.edu/example-project/manifests/allmyschemas-1.0\",\n", - " converters=MY_CONVERTERS)\n", - "]" - ] - }, - { - "cell_type": "markdown", - "id": "fa724a37", - "metadata": {}, - "source": [ - "Notice the changes to the last file as compared to the first tutorial.\n", - "Now it references a manifest that is elsewhere and provides a list\n", - "of converter instances instead. This manifest will be located in the\n", - "schema package and is used to associate schemas with tags.\n", - "\n", - "In addition, an additional file is created for the purposes of this\n", - "module's entry point." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "1d09bd82", - "metadata": {}, - "outputs": [], - "source": [ - "%%writefile src/myconverters/integration.py\n", - "def get_extensions():\n", - " from . import extensions\n", - " return extensions.MY_EXTENSIONS" - ] - }, - { - "cell_type": "markdown", - "id": "4577bcd7", - "metadata": {}, - "source": [ - "Add the `__init__.py`" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "99753484", - "metadata": {}, - "outputs": [], - "source": [ - "%%writefile src/myconverters/__init__.py\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "id": "799981ad", - "metadata": {}, - "source": [ - "And now to add the setup files. Note the change to integrations.py for get_extensions" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "b82c5f58", - "metadata": {}, - "outputs": [], - "source": [ - "%%writefile pyproject.toml\n", - "[project]\n", - "name = \"myconverters\"\n", - "description = \"TODO\"\n", - "version='0.1.0'\n", - "requires-python = \">=3.9\"\n", - "dependencies = [\n", - " \"jsonschema >=3.0.2\",\n", - " \"asdf >=2.8\",\n", - " \"psutil >=5.7.2\",\n", - " \"numpy>=1.16\",\n", - "]\n", - "\n", - "[build-system]\n", - "requires = [\"setuptools >=61\", \"setuptools_scm[toml] >=3.4\"]\n", - "build-backend = \"setuptools.build_meta\"\n", - "\n", - "[project.entry-points.\"asdf.extensions\"]\n", - "myconverters = \"myconverters.integration:get_extensions\"\n", - "\n", - "[tool.setuptools.packages.find]\n", - "where = [\"src\"]" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "1ebbffa3", - "metadata": {}, - "outputs": [], - "source": [ - "%%writefile setup.py\n", - "#!/usr/bin/env python3\n", - "from setuptools import setup\n", - "\n", - "setup()" + "The files for this tutorial are located in `Your_second_ASDF_converter`. The `myconverters` package is similar to the one covered in `Your_first_ASDF_converter` with some notable changes:\n", + "- The extension is registered using the manifest (covered below) see `myconverters/extensions.py`\n", + "- `myconveters/converters.py` contains 2 converters\n", + "- `myconverters.integration.get_extensions` is registered via the `asdf.extensions` entry point" ] }, { @@ -511,237 +95,12 @@ "source": [ "Dealing with the Schemas\n", "------------------------------\n", - "The utility previously mentioned would have contructed a directory tree for us with many files populated\n", "\n", - "Only the strictly necessary parts will be done manually, partly to minimize what has to be done, but also it isn't easy to edit files in a tutorial notebook." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "02fb0e4b", - "metadata": {}, - "outputs": [], - "source": [ - "cd .." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "28402214", - "metadata": {}, - "outputs": [], - "source": [ - "mkdir myschemas" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "308c46c1", - "metadata": {}, - "outputs": [], - "source": [ - "cd myschemas" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "a36535a5", - "metadata": {}, - "outputs": [], - "source": [ - "mkdir src" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "fd3a8d6b", - "metadata": {}, - "outputs": [], - "source": [ - "mkdir src/myschemas" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "886f2ccc", - "metadata": {}, - "outputs": [], - "source": [ - "mkdir src/myschemas/resources" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "0009d892", - "metadata": {}, - "outputs": [], - "source": [ - "mkdir src/myschemas/resources/manifests" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "146a9a4c", - "metadata": {}, - "outputs": [], - "source": [ - "mkdir src/myschemas/resources/schemas" - ] - }, - { - "cell_type": "markdown", - "id": "90720a6a", - "metadata": {}, - "source": [ - "Create the setup files" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "32e10f16", - "metadata": {}, - "outputs": [], - "source": [ - "%%writefile setup.py\n", - "#!/usr/bin/env python3\n", - "from setuptools import setup\n", + "The schemas for this notebook are provided through the `myschemas` package in the `Your_second_ASDF_converter` directory.\n", "\n", - "setup()" - ] - }, - { - "cell_type": "markdown", - "id": "2e0e88f6", - "metadata": {}, - "source": [ "Note that the form of the entry points is different now that schemas are involved.\n", "Also there is a need to add an indication that the schema and manefits files must\n", - "installed along with the software.\n", - "\n", - "Now create the two needed schema files. The explanation of how the schema works\n", - "will follow the creation of the schemas." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "973a0a41-9639-4a21-8465-0d76c656dc3d", - "metadata": {}, - "outputs": [], - "source": [ - "%%writefile pyproject.toml\n", - "[project]\n", - "name = \"myschemas\"\n", - "description = \"Schemas for second converter tutorial\"\n", - "version='0.1.0'\n", - "requires-python = \">=3.9\"\n", - "dependencies = [\n", - " \"jsonschema >=3.0.2\",\n", - " \"asdf >=2.8\",\n", - " \"psutil >=5.7.2\",\n", - " \"numpy >=1.16\",\n", - "]\n", - "\n", - "[build-system]\n", - "requires = [\"setuptools >=61\", \"setuptools_scm[toml] >=3.4\"]\n", - "build-backend = \"setuptools.build_meta\"\n", - "\n", - "[project.entry-points.\"asdf.resource_mappings\"]\n", - "myschema = \"myschemas.integration:get_resource_mappings\"\n", - "\n", - "[project.entry-points.\"asdf.extensions\"]\n", - "myconverter = \"myconverters.integration:get_extensions\"\n", - "\n", - "[tool.package-data]\n", - "\"myschema.resources\" = [\n", - " \"manifests/*.yaml\",\n", - " \"schemas/*.yaml\",\n", - "]\n", - "\n", - "[tool.setuptools.packages.find]\n", - "where = [\"src\"]" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "4b53eac2", - "metadata": {}, - "outputs": [], - "source": [ - "%%writefile src/myschemas/resources/schemas/photo_id-1.0.0.yaml\n", - "%YAML 1.1\n", - "---\n", - "$schema: \"http://stsci.edu/schemas/yaml-schema/draft-01\"\n", - "id: asdf://stsci.edu/example-project/schemas/photo_id-1.0.0\n", - "\n", - "title: Photo ID information\n", - "type: object\n", - "properties:\n", - " last_name:\n", - " title: Last name of the ID holder\n", - " type: string\n", - " first_name:\n", - " title: First name of ID holder\n", - " type: string\n", - " photo:\n", - " title: Monochromatic photo of ID holder\n", - " tag: tag:stsci.edu:asdf/core/ndarray-1.0.0\n", - " datatype: int8\n", - " ndim: 2\n", - "\n", - "propertyOrder: [last_name, first_name, photo]\n", - "flowStyle: block\n", - "required: [last_name, first_name, photo]\n", - "...\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "ee0ecaff", - "metadata": {}, - "outputs": [], - "source": [ - "%%writefile src/myschemas/resources/schemas/traffic_citation-1.0.0.yaml\n", - "%YAML 1.1\n", - "---\n", - "$schema: \"http://stsci.edu/schemas/yaml-schema/draft-01\"\n", - "id: asdf://stsci.edu/example-project/schemas/traffic_citation-1.0.0\n", - "\n", - "title: Traffic Citation Information\n", - "type: object\n", - "properties:\n", - " ociffer:\n", - " title: Name of ociffer issuing citation\n", - " type: string\n", - " violation:\n", - " title: Type of traffic violation\n", - " type: string\n", - " enum: [\"speeding\", \"DWI\", \"Failure to Signal\", \"Driving like a jerk\"]\n", - " date:\n", - " title: Date of violation\n", - " type: string \n", - " time:\n", - " title: Time of day of violation\n", - " type: string\n", - " photo_id:\n", - " title: photo_id of the driver committing violation\n", - " tag: asdf://stsci.edu/example-project/tags/photo_id-1.0.0\n", - "\n", - "propertyOrder: [ociffer, violation, date, time, photo_id]\n", - "flowStyle: block\n", - "required: [ociffer, violation, date, time, photo_id]\n", - "...\n" + "installed along with the software." ] }, { @@ -839,47 +198,7 @@ " # only have four allowed values, those listed for enum. Any other \n", " # value will cause a validation error.\n", " enum: [\"speeding\", \"DWI\", \"Failure to Signal\", \"Driving like a jerk\"]\n", - "```\n", - "\n", - "The rest of the content of this package involves making the necessary\n", - "connections to ASDF and to the associated tags.\n", - "\n", - "We will start with the manifest file. This file makes it simpler to \n", - "put all the connections in one place, and it allows sharing schemas\n", - "between different types." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "bac28bcc", - "metadata": {}, - "outputs": [], - "source": [ - "%%writefile src/myschemas/resources/manifests/allmyschemas-1.0.yaml\n", - "%YAML 1.1\n", - "---\n", - "id: asdf://stsci.edu/example-project/manifests/allmyschemas-1.0\n", - "extension_uri: asdf://stsci.edu/example-project/extensions/allmyschemas-1.0\n", - "title: All my schemas 1.0\n", - "description: |-\n", - " A set of tags for serializing all my schemas.\n", - "asdf_standard_requirement:\n", - " gte: 1.1.0\n", - "tags:\n", - "# Object Modules\n", - "- tag_uri: asdf://stsci.edu/example-project/tags/photo_id-1.0.0\n", - " schema_uri: asdf://stsci.edu/example-project/schemas/photo_id-1.0.0\n", - " title: Photo ID information\n", - " description: |-\n", - " Name on Photo ID and the photo from the Photo ID\n", - "- tag_uri: asdf://stsci.edu/example-project/tags/traffic_citation-1.0.0\n", - " schema_uri: asdf://stsci.edu/example-project/schemas/traffic_citation-1.0.0\n", - " title: Information about an issued traffic citation\n", - " description: |-\n", - " Information about an issued traffic citation including ociffer name, type of violation,\n", - " date, time, and photo ID.\n", - "...\n" + "```" ] }, { @@ -887,59 +206,12 @@ "id": "81338de6", "metadata": {}, "source": [ + "The rest of the content of `myschemas` involves making the necessary\n", + "connections to asdf and to the associated tags. This is primarily defined\n", + "in the manifest file (which maps tags and schemas).\n", "\n", + "The manifests and schemas are registered with asdf using `DirectoryResourceMapping` instances defined in `integration.py`.\n", "\n", - "Note that the manifest associates a tag with a schema, and ASDF will use\n", - "that to map from one to the other.\n", - "\n", - "The last file to add is the Python code used for entry points to do just\n", - "that." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "6c3c2d92", - "metadata": {}, - "outputs": [], - "source": [ - "%%writefile src/myschemas/integration.py\n", - "import sys\n", - "\n", - "from asdf.resource import DirectoryResourceMapping\n", - "\n", - "if sys.version_info < (3, 9):\n", - " import importlib_resources\n", - "else:\n", - " import importlib.resources as importlib_resources\n", - "\n", - "\n", - "def get_resource_mappings():\n", - " \"\"\"\n", - " Get the resource mapping instances for myschemas\n", - " and manifests. This method is registered with the\n", - " asdf.resource_mappings entry point.\n", - "\n", - " Returns\n", - " -------\n", - " list of collections.abc.Mapping\n", - " \"\"\"\n", - " from . import resources\n", - " resources_root = importlib_resources.files(resources)\n", - "\n", - " return [\n", - " DirectoryResourceMapping(\n", - " resources_root / \"schemas\", \"asdf://stsci.edu/example-project/schemas/\"),\n", - " DirectoryResourceMapping(\n", - " resources_root / \"manifests\", \"asdf://stsci.edu/example-project/manifests/\"),\n", - " ]\n" - ] - }, - { - "cell_type": "markdown", - "id": "2f70eef1", - "metadata": {}, - "source": [ "The key element in this file are the last few lines. What this is \n", "indicating is that when a schema id is encountered and the beginning\n", "of that schema_id matches the last string, the remainder of that\n", @@ -950,32 +222,7 @@ "Likewise for the manifest, where the manifest id is located in the \n", "extensions.py file for the converter package. Basically, it tells the\n", "converter package, where the manifest file may be found on the filesystem,\n", - "and from that, where the schemas may be found on the local filesystem.\n", - "\n", - "Did we say last file? Not quite. We need an empty `__init__.py` to make\n", - "this a package." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "d47a1b5e", - "metadata": {}, - "outputs": [], - "source": [ - "%%writefile src/myschemas/__init__.py\n", - "\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "ebb6630a", - "metadata": {}, - "outputs": [], - "source": [ - "%%writefile src/myschemas/resources/__init__.py\n", - "\n" + "and from that, where the schemas may be found on the local filesystem." ] }, { @@ -987,26 +234,6 @@ "---------------------------" ] }, - { - "cell_type": "code", - "execution_count": null, - "id": "4a67e777", - "metadata": {}, - "outputs": [], - "source": [ - "pip install --editable ." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "8261435e", - "metadata": {}, - "outputs": [], - "source": [ - "cd ../myconverters" - ] - }, { "cell_type": "code", "execution_count": null, @@ -1014,7 +241,7 @@ "metadata": {}, "outputs": [], "source": [ - "pip install --editable ." + "pip install ./Your_second_ASDF_converter" ] }, { @@ -1023,20 +250,7 @@ "metadata": {}, "source": [ "Testing the converters\n", - "--------------------------\n", - "\n", - "**Now restart the kernel as was done in the first converter tutorial**\n", - "----------------------------------------------------------------------" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "d89252f0", - "metadata": {}, - "outputs": [], - "source": [ - "cd ~" + "--------------------------" ] }, { @@ -1143,6 +357,7 @@ "metadata": {}, "outputs": [], "source": [ + "# NBVAL_RAISES_EXCEPTION\n", "af2.write_to('test2.asdf')" ] }, @@ -1181,7 +396,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.10" + "version": "3.13.4" } }, "nbformat": 4, diff --git a/notebooks/Your_second_ASDF_converter/pyproject.toml b/notebooks/Your_second_ASDF_converter/pyproject.toml new file mode 100644 index 0000000..358d98c --- /dev/null +++ b/notebooks/Your_second_ASDF_converter/pyproject.toml @@ -0,0 +1,18 @@ +[project] +name = "myconverters" +description = "TODO" +version='0.1.0' +requires-python = ">=3.9" +dependencies = [ + "asdf >=2.8", +] + +[build-system] +requires = ["setuptools >=61", "setuptools_scm[toml] >=3.4"] +build-backend = "setuptools.build_meta" + +[project.entry-points."asdf.resource_mappings"] +myschema = "myschemas.integration:get_resource_mappings" + +[project.entry-points."asdf.extensions"] +myconverters = "myconverters.integration:get_extensions" diff --git a/notebooks/Your_second_ASDF_converter/src/myconverters/__init__.py b/notebooks/Your_second_ASDF_converter/src/myconverters/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/notebooks/Your_second_ASDF_converter/src/myconverters/converters.py b/notebooks/Your_second_ASDF_converter/src/myconverters/converters.py new file mode 100644 index 0000000..2012e07 --- /dev/null +++ b/notebooks/Your_second_ASDF_converter/src/myconverters/converters.py @@ -0,0 +1,46 @@ +from asdf.extension import Converter +from .photo_id import PhotoID +from .traffic_citation import TrafficCitation + + +class PhotoIDConverter(Converter): + tags = ["asdf://stsci.edu/example-project/tags/photo_id-*"] + types = ["myconverters.photo_id.PhotoID"] + # The above registers the tag that the converter is used for, as well as + # associating the class that the converter is used for. + + # This method converts from the Python object to yaml + def to_yaml_tree(self, obj, tags, ctx): + # The yaml conversion expects a dictionary returned + node = {} + node['first_name'] = obj.first_name + node['last_name'] = obj.last_name + node['photo'] = obj.photo + return node + + # This method converts from yaml to the Python object + def from_yaml_tree(self, node, tag, ctx): + return PhotoID(node['last_name'], + node['first_name'], + node['photo']) + + +class TrafficCitationConverter(Converter): + tags = ["asdf://stsci.edu/example-project/tags/traffic_citation-1.0.0"] + types = ["myconverters.traffic_citation.TrafficCitation"] + + def to_yaml_tree(self, obj, tags, ctx): + node = {} + node['ociffer'] = obj.ociffer + node['violation'] = obj.violation + node['date'] = obj.date + node['time'] = obj.time + node['photo_id'] = obj.photo_id + return node + + def from_yaml_tree(self, node, tag, ctx): + return TrafficCitation(node['ociffer'], + node['violation'], + node['date'], + node['time'], + node['photo_id']) diff --git a/notebooks/Your_second_ASDF_converter/src/myconverters/extensions.py b/notebooks/Your_second_ASDF_converter/src/myconverters/extensions.py new file mode 100644 index 0000000..9b81058 --- /dev/null +++ b/notebooks/Your_second_ASDF_converter/src/myconverters/extensions.py @@ -0,0 +1,15 @@ +from asdf.extension import ManifestExtension +from .converters import ( + PhotoIDConverter, + TrafficCitationConverter,) + +MY_CONVERTERS = [ + PhotoIDConverter(), + TrafficCitationConverter(), +] + +MY_EXTENSIONS = [ + ManifestExtension.from_uri( + "asdf://stsci.edu/example-project/manifests/allmyschemas-1.0", + converters=MY_CONVERTERS) +] diff --git a/notebooks/Your_second_ASDF_converter/src/myconverters/integration.py b/notebooks/Your_second_ASDF_converter/src/myconverters/integration.py new file mode 100644 index 0000000..2745dcb --- /dev/null +++ b/notebooks/Your_second_ASDF_converter/src/myconverters/integration.py @@ -0,0 +1,3 @@ +def get_extensions(): + from . import extensions + return extensions.MY_EXTENSIONS diff --git a/notebooks/Your_second_ASDF_converter/src/myconverters/photo_id.py b/notebooks/Your_second_ASDF_converter/src/myconverters/photo_id.py new file mode 100644 index 0000000..3fe621e --- /dev/null +++ b/notebooks/Your_second_ASDF_converter/src/myconverters/photo_id.py @@ -0,0 +1,11 @@ +class PhotoID: + "Holds Phot ID information" + + def __init__(self, last_name, first_name, image): + "expects a monochromatic numpy array for image" + self.last_name = last_name + self.first_name = first_name + self.photo = image + + def name(self): + return self.last_name + ', ' + self.first_name diff --git a/notebooks/Your_second_ASDF_converter/src/myconverters/traffic_citation.py b/notebooks/Your_second_ASDF_converter/src/myconverters/traffic_citation.py new file mode 100644 index 0000000..b61cee9 --- /dev/null +++ b/notebooks/Your_second_ASDF_converter/src/myconverters/traffic_citation.py @@ -0,0 +1,12 @@ +from .photo_id import PhotoID + + +class TrafficCitation: + "Record of a traffic violation" + + def __init__(self, ociffer, violation, date, time, photo_id): + self.ociffer = ociffer + self.violation = violation + self.date = date + self.time = time + self.photo_id = photo_id diff --git a/notebooks/Your_second_ASDF_converter/src/myschemas/__init__.py b/notebooks/Your_second_ASDF_converter/src/myschemas/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/notebooks/Your_second_ASDF_converter/src/myschemas/integration.py b/notebooks/Your_second_ASDF_converter/src/myschemas/integration.py new file mode 100644 index 0000000..25f3a6c --- /dev/null +++ b/notebooks/Your_second_ASDF_converter/src/myschemas/integration.py @@ -0,0 +1,26 @@ +import sys + +from asdf.resource import DirectoryResourceMapping + +import importlib.resources as importlib_resources + + +def get_resource_mappings(): + """ + Get the resource mapping instances for myschemas + and manifests. This method is registered with the + asdf.resource_mappings entry point. + + Returns + ------- + list of collections.abc.Mapping + """ + from . import resources + resources_root = importlib_resources.files(resources) + + return [ + DirectoryResourceMapping( + resources_root / "schemas", "asdf://stsci.edu/example-project/schemas/"), + DirectoryResourceMapping( + resources_root / "manifests", "asdf://stsci.edu/example-project/manifests/"), + ] diff --git a/notebooks/Your_second_ASDF_converter/src/myschemas/resources/__init__.py b/notebooks/Your_second_ASDF_converter/src/myschemas/resources/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/notebooks/Your_second_ASDF_converter/src/myschemas/resources/manifests/allmyschemas-1.0.yaml b/notebooks/Your_second_ASDF_converter/src/myschemas/resources/manifests/allmyschemas-1.0.yaml new file mode 100644 index 0000000..731d84d --- /dev/null +++ b/notebooks/Your_second_ASDF_converter/src/myschemas/resources/manifests/allmyschemas-1.0.yaml @@ -0,0 +1,23 @@ +%YAML 1.1 +--- +id: asdf://stsci.edu/example-project/manifests/allmyschemas-1.0 +extension_uri: asdf://stsci.edu/example-project/extensions/allmyschemas-1.0 +title: All my schemas 1.0 +description: |- + A set of tags for serializing all my schemas. +asdf_standard_requirement: + gte: 1.1.0 +tags: +# Object Modules +- tag_uri: asdf://stsci.edu/example-project/tags/photo_id-1.0.0 + schema_uri: asdf://stsci.edu/example-project/schemas/photo_id-1.0.0 + title: Photo ID information + description: |- + Name on Photo ID and the photo from the Photo ID +- tag_uri: asdf://stsci.edu/example-project/tags/traffic_citation-1.0.0 + schema_uri: asdf://stsci.edu/example-project/schemas/traffic_citation-1.0.0 + title: Information about an issued traffic citation + description: |- + Information about an issued traffic citation including ociffer name, type of violation, + date, time, and photo ID. +... diff --git a/notebooks/Your_second_ASDF_converter/src/myschemas/resources/schemas/photo_id-1.0.0.yaml b/notebooks/Your_second_ASDF_converter/src/myschemas/resources/schemas/photo_id-1.0.0.yaml new file mode 100644 index 0000000..b554024 --- /dev/null +++ b/notebooks/Your_second_ASDF_converter/src/myschemas/resources/schemas/photo_id-1.0.0.yaml @@ -0,0 +1,24 @@ +%YAML 1.1 +--- +$schema: "http://stsci.edu/schemas/yaml-schema/draft-01" +id: asdf://stsci.edu/example-project/schemas/photo_id-1.0.0 + +title: Photo ID information +type: object +properties: + last_name: + title: Last name of the ID holder + type: string + first_name: + title: First name of ID holder + type: string + photo: + title: Monochromatic photo of ID holder + tag: tag:stsci.edu:asdf/core/ndarray-1.0.0 + datatype: int8 + ndim: 2 + +propertyOrder: [last_name, first_name, photo] +flowStyle: block +required: [last_name, first_name, photo] +... diff --git a/notebooks/Your_second_ASDF_converter/src/myschemas/resources/schemas/traffic_citation-1.0.0.yaml b/notebooks/Your_second_ASDF_converter/src/myschemas/resources/schemas/traffic_citation-1.0.0.yaml new file mode 100644 index 0000000..98bee7c --- /dev/null +++ b/notebooks/Your_second_ASDF_converter/src/myschemas/resources/schemas/traffic_citation-1.0.0.yaml @@ -0,0 +1,29 @@ +%YAML 1.1 +--- +$schema: "http://stsci.edu/schemas/yaml-schema/draft-01" +id: asdf://stsci.edu/example-project/schemas/traffic_citation-1.0.0 + +title: Traffic Citation Information +type: object +properties: + ociffer: + title: Name of ociffer issuing citation + type: string + violation: + title: Type of traffic violation + type: string + enum: ["speeding", "DWI", "Failure to Signal", "Driving like a jerk"] + date: + title: Date of violation + type: string + time: + title: Time of day of violation + type: string + photo_id: + title: photo_id of the driver committing violation + tag: asdf://stsci.edu/example-project/tags/photo_id-1.0.0 + +propertyOrder: [ociffer, violation, date, time, photo_id] +flowStyle: block +required: [ociffer, violation, date, time, photo_id] +... diff --git a/tox.ini b/tox.ini index c988e5e..8e256ff 100644 --- a/tox.ini +++ b/tox.ini @@ -7,7 +7,5 @@ deps = -rrequirements.txt pytest nbval -# don't install a package -install_command = commands = pytest --nbval