Repository: Yelp/swagger_spec_validator

Issue:
Identified regression on version 2.4.2
swagger_spec_validator==2.4.2 introduced a regression while validating swagger spec split in multiple files.

The regression is caused by dereferencing references without keeping into account the scope (in which file was the reference defined)


Discussion:

Patch:
diff --git a/swagger_spec_validator/validator20.py b/swagger_spec_validator/validator20.py
index 381e9e4..8048241 100644
--- a/swagger_spec_validator/validator20.py
+++ b/swagger_spec_validator/validator20.py
@@ -85,9 +85,15 @@ def validate_references(raw_spec, deref, path=None, visited_spec_ids=None):
         # Due to _looks like_ we need to almost duplicate the check by removing the string enforcement
         validate_ref(ref_dict=raw_spec, path=path)
 
-    if is_ref(raw_spec):
-        if isinstance(raw_spec['$ref'], string_types):
-            validate_references(deref(raw_spec), deref, path, visited_spec_ids)
+    if is_ref(raw_spec) and 'x-scope' in raw_spec:
+        # Ensure that we're following references only if they were already
+        # descended by jsonschema during initial schema validation (x-scope is present)
+        # This is mostly done to ensure that we're not causing RefResolutionError
+        # due to the fact that the reference is relative and we have no information
+        # about the base path.
+        # This could be handled differently but we thought that checking references that
+        # were actively part of the specs is a valid trade-off here
+        validate_references(deref(raw_spec), deref, path, visited_spec_ids)
     elif isinstance(raw_spec, dict):
         for k, v in sorted(iteritems(raw_spec)):
             validate_references(v, deref, path + [k], visited_spec_ids)


Test patch:
diff --git a/tests/data/v2.0/test_complicated_refs/operations/operations.json b/tests/data/v2.0/test_complicated_refs/operations/operations.json
index 8f49353..7fc34d2 100644
--- a/tests/data/v2.0/test_complicated_refs/operations/operations.json
+++ b/tests/data/v2.0/test_complicated_refs/operations/operations.json
@@ -14,6 +14,11 @@
             },
             "tags": [
                 "pingpong"
+            ],
+            "x-something": [
+                {
+                    "$ref": "../responses/responses.json#/pong"
+                }
             ]
         }
     }
diff --git a/tests/validator20/validate_spec_url_test.py b/tests/validator20/validate_spec_url_test.py
index 27da6c2..f7f7a50 100644
--- a/tests/validator20/validate_spec_url_test.py
+++ b/tests/validator20/validate_spec_url_test.py
@@ -36,6 +36,11 @@ def test_success_crossref_url_json():
     validate_spec_url(urlpath)
 
 
+def test_complicated_refs_json():
+    urlpath = get_uri_from_file_path(os.path.abspath('./tests/data/v2.0/test_complicated_refs/swagger.json'))
+    validate_spec_url(urlpath)
+
+
 def test_specs_with_empty_reference():
     with pytest.warns(SwaggerValidationWarning) as warninfo:
         validate_spec_url(