Repository: geographika/mappyfile

Issue:
Invalid value in COMPOSITE - 'compfilter'
COMPFILTER is missing in the COMPOSITE block

mappyfile validate layer_comp.map 
layer_comp.map (Line: 124 Column: 3) ERROR: Invalid value in COMPOSITE - 'compfilter' does not match any of the regexes: '^__[a-z]+__$'

Working mapfile in: https://gist.github.com/LarsSchy/4aa75fd2a6bc7eb01a7cff9beb64b59a

Discussion:

Patch:
diff --git a/docs/schemas/mapfile-schema-7-6.json b/docs/schemas/mapfile-schema-7-6.json
index 3e01f5a..ce41cb3 100644
--- a/docs/schemas/mapfile-schema-7-6.json
+++ b/docs/schemas/mapfile-schema-7-6.json
@@ -2727,9 +2727,41 @@
                                         "composite"
                                     ]
                                 },
-                                "compop": {
+                                "compfilter": {
                                     "type": "string"
                                 },
+                                "compop": {
+                                    "enum": [
+                                        "clear",
+                                        "color-burn",
+                                        "color-dodge",
+                                        "contrast",
+                                        "darken",
+                                        "difference",
+                                        "dst",
+                                        "dst-atop",
+                                        "dst-in",
+                                        "dst-out",
+                                        "dst-over",
+                                        "exclusion",
+                                        "hard-light",
+                                        "invert",
+                                        "invert-rgb",
+                                        "lighten",
+                                        "minus",
+                                        "multiply",
+                                        "overlay",
+                                        "plus",
+                                        "screen",
+                                        "soft-light",
+                                        "src",
+                                        "src-atop",
+                                        "src-in",
+                                        "src-out",
+                                        "src-over",
+                                        "xor"
+                                    ]
+                                },
                                 "include": {
                                     "items": {
                                         "type": "string"
diff --git a/docs/schemas/mapfile-schema-8-0.json b/docs/schemas/mapfile-schema-8-0.json
index 6332e45..0df75f6 100644
--- a/docs/schemas/mapfile-schema-8-0.json
+++ b/docs/schemas/mapfile-schema-8-0.json
@@ -2297,9 +2297,41 @@
                                         "composite"
                                     ]
                                 },
-                                "compop": {
+                                "compfilter": {
                                     "type": "string"
                                 },
+                                "compop": {
+                                    "enum": [
+                                        "clear",
+                                        "color-burn",
+                                        "color-dodge",
+                                        "contrast",
+                                        "darken",
+                                        "difference",
+                                        "dst",
+                                        "dst-atop",
+                                        "dst-in",
+                                        "dst-out",
+                                        "dst-over",
+                                        "exclusion",
+                                        "hard-light",
+                                        "invert",
+                                        "invert-rgb",
+                                        "lighten",
+                                        "minus",
+                                        "multiply",
+                                        "overlay",
+                                        "plus",
+                                        "screen",
+                                        "soft-light",
+                                        "src",
+                                        "src-atop",
+                                        "src-in",
+                                        "src-out",
+                                        "src-over",
+                                        "xor"
+                                    ]
+                                },
                                 "include": {
                                     "items": {
                                         "type": "string"
diff --git a/mappyfile/schemas/composite.json b/mappyfile/schemas/composite.json
index 83c0390..fa858b1 100644
--- a/mappyfile/schemas/composite.json
+++ b/mappyfile/schemas/composite.json
@@ -19,8 +19,40 @@
       "minimum": 0,
       "maximum": 100
     },
-    "compop": {
+    "compfilter": {
       "type": "string"
+    },
+    "compop": {
+      "enum": [
+        "clear",
+        "color-burn",
+        "color-dodge",
+        "contrast",
+        "darken",
+        "difference",
+        "dst",
+        "dst-atop",
+        "dst-in",
+        "dst-out",
+        "dst-over",
+        "exclusion",
+        "hard-light",
+        "invert",
+        "invert-rgb",
+        "lighten",
+        "minus",
+        "multiply",
+        "overlay",
+        "plus",
+        "screen",
+        "soft-light",
+        "src",
+        "src-atop",
+        "src-in",
+        "src-out",
+        "src-over",
+        "xor"
+      ]
     }
   }
 }
diff --git a/mappyfile/validator.py b/mappyfile/validator.py
index 8bb87aa..2bb61c5 100644
--- a/mappyfile/validator.py
+++ b/mappyfile/validator.py
@@ -104,7 +104,7 @@ class Validator(object):
         version. Optionally provide a schema_name to return an expanded
         subsection of the full schema.
         """
-        jsn_schema = self.get_expanded_schema(schema_name)
+        jsn_schema = self.get_expanded_schema(schema_name, version)
 
         if version:
             # remove any properties based on minVersion and maxVersion
@@ -271,11 +271,18 @@ class Validator(object):
 
         return error_messages
 
-    def get_expanded_schema(self, schema_name):
+    def get_expanded_schema(self, schema_name, version=None):
         """
         Return a schema file with all $ref properties expanded
         """
-        if schema_name not in self.expanded_schemas:
+
+        # ensure we cache per version to handle validator reuse
+        if version is not None:
+            cache_schema_name = schema_name + str(version)
+        else:
+            cache_schema_name = schema_name
+
+        if cache_schema_name not in self.expanded_schemas:
             fn = self.get_schema_file(schema_name)
             schemas_folder = self.get_schemas_folder()
             base_uri = self.get_schema_path(schemas_folder)
@@ -284,8 +291,8 @@ class Validator(object):
                 jsn_schema = jsonref.load(f, base_uri=base_uri)
 
                 # cache the schema for future use
-                self.expanded_schemas[schema_name] = jsn_schema
+                self.expanded_schemas[cache_schema_name] = jsn_schema
         else:
-            jsn_schema = self.expanded_schemas[schema_name]
+            jsn_schema = self.expanded_schemas[cache_schema_name]
 
         return jsn_schema


Test patch:
diff --git a/docs/schemas/mapfile-latest.json b/docs/schemas/mapfile-latest.json
index 8cf05eb..bf82d63 100644
--- a/docs/schemas/mapfile-latest.json
+++ b/docs/schemas/mapfile-latest.json
@@ -2798,9 +2798,41 @@
                                         "composite"
                                     ]
                                 },
-                                "compop": {
+                                "compfilter": {
                                     "type": "string"
                                 },
+                                "compop": {
+                                    "enum": [
+                                        "clear",
+                                        "color-burn",
+                                        "color-dodge",
+                                        "contrast",
+                                        "darken",
+                                        "difference",
+                                        "dst",
+                                        "dst-atop",
+                                        "dst-in",
+                                        "dst-out",
+                                        "dst-over",
+                                        "exclusion",
+                                        "hard-light",
+                                        "invert",
+                                        "invert-rgb",
+                                        "lighten",
+                                        "minus",
+                                        "multiply",
+                                        "overlay",
+                                        "plus",
+                                        "screen",
+                                        "soft-light",
+                                        "src",
+                                        "src-atop",
+                                        "src-in",
+                                        "src-out",
+                                        "src-over",
+                                        "xor"
+                                    ]
+                                },
                                 "include": {
                                     "items": {
                                         "type": "string"
diff --git a/tests/test_validation.py b/tests/test_validation.py
index 66ffff2..f87087e 100644
--- a/tests/test_validation.py
+++ b/tests/test_validation.py
@@ -598,6 +598,34 @@ def test_property_versioning():
     assert len(properties["force"]["oneOf"]) == 1
 
 
+def test_object_versioning():
+    """
+    Exclude whole objects if they were added in a
+    later version of MapServer
+    """
+
+    s = """MAP
+    NAME "sample"
+    LAYER
+        TYPE POLYGON
+        COMPOSITE
+            COMPOP "lighten"
+            OPACITY 50
+            COMPFILTER "blur(10)"
+        END
+    END
+END"""
+
+    d = mappyfile.loads(s, include_position=False)
+    v = Validator()
+    errors = v.validate(d, add_comments=True, version=6.0)
+    assert len(errors) == 1
+
+    d = mappyfile.loads(s, include_position=False)
+    errors = v.validate(d, add_comments=True, version=7.0)
+    assert len(errors) == 0
+
+
 def test_get_versioned_schema():
 
     validator = Validator()
@@ -613,8 +641,5 @@ def run_tests():
 if __name__ == "__main__":
     logging.basicConfig(level=logging.INFO)
     # run_tests()
-    test_property_versioning()
-    test_version_warnings()
-    test_keyword_versioning()
-    test_get_versioned_schema()
+    test_object_versioning()
     print("Done!")