Skip to content

Commit

Permalink
Add new schema command line tool
Browse files Browse the repository at this point in the history
  • Loading branch information
geographika committed Jul 14, 2020
1 parent af4baa2 commit efd26b1
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 12 deletions.
14 changes: 14 additions & 0 deletions docs/client.rst
Original file line number Diff line number Diff line change
Expand Up @@ -99,3 +99,17 @@ To display the command's help text run the following:
mode con:cols=200
mappyfile validate --help > docs/validate.txt
mappyfile validate C:/Temp/*.map > docs/validation_errors.txt
.. _client-schema:

schema
------

Save the Mapfile schema to a file. Set the version parameter to output a specific version.

.. code-block:: bat
mappyfile schema --help
.. literalinclude:: format.txt
:language: console
32 changes: 30 additions & 2 deletions mappyfile/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,12 @@
import sys
import os
import codecs
import json
import glob
import logging
import mappyfile
import click
import mappyfile
from mappyfile.validator import Validator


def get_mapfiles(mapfiles):
Expand Down Expand Up @@ -79,7 +81,7 @@ def main(ctx, verbose, quiet):

@main.command(short_help="Format a Mapfile")
@click.argument('input-mapfile', nargs=1, type=click.Path(exists=True))
@click.argument('output-mapfile', nargs=1, type=click.Path())
@click.argument('output-mapfile', nargs=1, type=click.Path())
@click.option('--indent', default=4, show_default=True, help="The number of spacer characters to indent structures in the Mapfile") # noqa
@click.option('--spacer', default=" ", help="The character to use for indenting structures in the Mapfile")
@click.option('--quote', default='"', help="The quote character to use in the Mapfile (double or single quotes). Ensure these are escaped e.g. \\\" or \\' [default: \\\"]") # noqa
Expand Down Expand Up @@ -168,3 +170,29 @@ def validate(ctx, mapfiles, expand, version):

click.echo("{} file(s) validated ({} successfully)".format(len(all_mapfiles), validation_count))
sys.exit(errors)


@main.command(short_help="Export a Mapfile Schema")
@click.argument('output_file', nargs=1, type=click.Path())
@click.option('--version', type=click.FLOAT, help="The MapServer version number used to validate the Mapfile") # noqa
@click.pass_context
def schema(ctx, output_file, version=None):
"""
Save the Mapfile schema to a file. Set the version parameter to output a specific version.
Note output-file will be overwritten if it already exists.
Examples:
mappyfile schema C:/Temp/mapfile-schema.json
Example of a specific version:
mappyfile schema C:/Temp/mapfile-schema-7-6.json --version=7.6
"""
validator = Validator()
jsn = validator.get_versioned_schema(version)

with codecs.open(output_file, "w", encoding="utf-8") as f:
f.write(json.dumps(jsn, sort_keys=True, indent=4))

sys.exit(0)
4 changes: 2 additions & 2 deletions mappyfile/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -615,9 +615,9 @@ def validate(d, version=None):
return v.validate(d, version=version)


def _save(output_file, map_string):
def _save(output_file, string):
with codecs.open(output_file, "w", encoding="utf-8") as f:
f.write(map_string)
f.write(string)


def _pprint(d, indent, spacer, quote, newlinechar, end_comment, **kwargs):
Expand Down
24 changes: 18 additions & 6 deletions mappyfile/validator.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,22 @@ def is_valid_for_version(self, d, version):

return True

def get_versioned_schema(self, properties, version):
def get_versioned_schema(self, version=None, schema_name="map"):
"""
Get a fully expanded JSON schema for a specific MapServer
version. Optionally provide a schema_name to return an expanded
subsection of the full schema.
"""
jsn_schema = self.get_expanded_schema(schema_name)

if version:
# remove any properties based on minVersion and maxVersion
properties = jsn_schema["properties"]
jsn_schema["properties"] = self.get_versioned_properties(properties, version)

return jsn_schema

def get_versioned_properties(self, properties, version):
"""
For a dict object recursively check each child object
to see if it is valid for the supplied version
Expand All @@ -110,7 +125,7 @@ def get_versioned_schema(self, properties, version):
if isinstance(v, dict):
if self.is_valid_for_version(v, version) is False:
del properties[key]
self.get_versioned_schema(v, version)
self.get_versioned_properties(v, version)
elif isinstance(v, list):
valid_list = []
for props in v:
Expand Down Expand Up @@ -241,10 +256,7 @@ def validate(self, value, add_comments=False, schema_name="map", version=None):
verbose - also return the jsonschema error details
"""
if version:
jsn_schema = self.get_expanded_schema(schema_name)
# remove any properties based on minVersion and maxVersion
properties = jsn_schema["properties"]
jsn_schema["properties"] = self.get_versioned_schema(properties, version)
jsn_schema = self.get_versioned_schema(version, schema_name)
validator = jsonschema.Draft4Validator(schema=jsn_schema)
else:
validator = self.get_schema_validator(schema_name)
Expand Down
13 changes: 11 additions & 2 deletions tests/test_validation.py
Original file line number Diff line number Diff line change
Expand Up @@ -563,7 +563,7 @@ def test_keyword_versioning():

v = Validator()
assert "align" in properties["properties"].keys()
properties = v.get_versioned_schema(properties, 5.2)
properties = v.get_versioned_properties(properties, 5.2)
print(json.dumps(properties, indent=4))
assert "align" not in properties["properties"].keys()

Expand All @@ -586,11 +586,19 @@ def test_property_versioning():
v = Validator()
assert "enum" in properties["force"]["oneOf"][1].keys()
assert len(properties["force"]["oneOf"]) == 2
properties = v.get_versioned_schema(properties, 6.0)
properties = v.get_versioned_properties(properties, 6.0)
print(json.dumps(properties, indent=4))
assert len(properties["force"]["oneOf"]) == 1


def test_get_versioned_schema():

validator = Validator()
jsn = validator.get_versioned_schema(7.6)
# print(json.dumps(jsn, indent=4))
assert "defresolution" in jsn["properties"].keys()


def run_tests():
pytest.main(["tests/test_validation.py"])

Expand All @@ -601,4 +609,5 @@ def run_tests():
test_property_versioning()
test_version_warnings()
test_keyword_versioning()
test_get_versioned_schema()
print("Done!")

0 comments on commit efd26b1

Please sign in to comment.