From 616536e9dc9ff580e16891ece975ae3f041c7acc Mon Sep 17 00:00:00 2001 From: Simon Willison Date: Thu, 2 Apr 2020 11:35:25 -0700 Subject: [PATCH] --metadata accepts YAML as well as JSON, refs #713 --- datasette/cli.py | 7 ++++--- datasette/publish/common.py | 2 +- datasette/publish/heroku.py | 4 ++-- datasette/utils/__init__.py | 18 +++++++++++++++++- setup.py | 1 + 5 files changed, 25 insertions(+), 7 deletions(-) diff --git a/datasette/cli.py b/datasette/cli.py index 94da6ee4..9328ec08 100644 --- a/datasette/cli.py +++ b/datasette/cli.py @@ -11,6 +11,7 @@ import sys from .app import Datasette, DEFAULT_CONFIG, CONFIG_OPTIONS, pm from .utils import ( check_connection, + parse_metadata, ConnectionProblem, SpatialiteConnectionProblem, temporary_docker_directory, @@ -147,7 +148,7 @@ def plugins(all, plugins_dir): "-m", "--metadata", type=click.File(mode="r"), - help="Path to JSON file containing metadata to publish", + help="Path to JSON/YAML file containing metadata to publish", ) @click.option("--extra-options", help="Extra options to pass to datasette serve") @click.option("--branch", help="Install datasette from a GitHub branch e.g. master") @@ -281,7 +282,7 @@ def package( "-m", "--metadata", type=click.File(mode="r"), - help="Path to JSON file containing license/source metadata", + help="Path to JSON/YAML file containing license/source metadata", ) @click.option( "--template-dir", @@ -354,7 +355,7 @@ def serve( metadata_data = None if metadata: - metadata_data = json.loads(metadata.read()) + metadata_data = parse_metadata(metadata.read()) click.echo( "Serve! files={} (immutables={}) on port {}".format(files, immutable, port) diff --git a/datasette/publish/common.py b/datasette/publish/common.py index ac4e2821..2911029d 100644 --- a/datasette/publish/common.py +++ b/datasette/publish/common.py @@ -12,7 +12,7 @@ def add_common_publish_arguments_and_options(subcommand): "-m", "--metadata", type=click.File(mode="r"), - help="Path to JSON file containing metadata to publish", + help="Path to JSON/YAML file containing metadata to publish", ), click.option( "--extra-options", help="Extra options to pass to datasette serve" diff --git a/datasette/publish/heroku.py b/datasette/publish/heroku.py index e75f76df..4db81d8e 100644 --- a/datasette/publish/heroku.py +++ b/datasette/publish/heroku.py @@ -11,7 +11,7 @@ from .common import ( add_common_publish_arguments_and_options, fail_if_publish_binary_not_installed, ) -from datasette.utils import link_or_copy, link_or_copy_directory +from datasette.utils import link_or_copy, link_or_copy_directory, parse_metadata @hookimpl @@ -154,7 +154,7 @@ def temporary_heroku_directory( file_names = [os.path.split(f)[-1] for f in files] if metadata: - metadata_content = json.load(metadata) + metadata_content = parse_metadata(metadata.read()) else: metadata_content = {} for key, value in extra_metadata.items(): diff --git a/datasette/utils/__init__.py b/datasette/utils/__init__.py index be99f890..226efe45 100644 --- a/datasette/utils/__init__.py +++ b/datasette/utils/__init__.py @@ -13,6 +13,7 @@ import types import shutil import urllib import numbers +import yaml try: import pysqlite3 as sqlite3 @@ -359,7 +360,7 @@ def temporary_docker_directory( file_paths = [os.path.join(saved_cwd, file_path) for file_path in files] file_names = [os.path.split(f)[-1] for f in files] if metadata: - metadata_content = json.load(metadata) + metadata_content = parse_metadata(metadata.read()) else: metadata_content = {} for key, value in extra_metadata.items(): @@ -785,3 +786,18 @@ def check_connection(conn): raise SpatialiteConnectionProblem(e) else: raise ConnectionProblem(e) + + +class BadMetadataError(Exception): + pass + + +def parse_metadata(content): + # content can be JSON or YAML + try: + return json.loads(content) + except json.JSONDecodeError: + try: + return yaml.safe_load(content) + except yaml.YAMLError: + raise BadMetadataError("Metadata is not valid JSON or YAML") diff --git a/setup.py b/setup.py index 85c935a5..7b6422fe 100644 --- a/setup.py +++ b/setup.py @@ -45,6 +45,7 @@ setup( "uvicorn~=0.11", "aiofiles~=0.4.0", "janus~=0.4.0", + "PyYAML~=5.3", ], entry_points=""" [console_scripts]