def test_issue_77_translate_external_refs_internal(): specs = '' with open('tests/specs/issue_78/openapi.json', 'r') as fh: specs = fh.read() from prance.util import formats specs = formats.parse_spec(specs, 'openapi.json') res = resolver.RefResolver(specs, fs.abspath('openapi.json'), resolve_types = resolver.RESOLVE_FILES | resolver.RESOLVE_INTERNAL, resolve_method= resolver.TRANSLATE_EXTERNAL ) res.resolve_references() from prance.util.path import path_get val = path_get(res.specs, ('components', 'schemas', '_schemas.json_Body')) # Reference to file is translated in components/schemas assert 'content' in val assert 'application/json' in val['content'] # Internal Reference links updated assert '#/components/schemas/_schemas.json_Something' == val['content']['application/json']['$ref'] # Internal references is copied to componnents/schemas seperately val = path_get(res.specs, ('components', 'schemas', '_schemas.json_Something')) assert 'type' in val # File reference url is updated as well val = path_get(res.specs, ('paths', '/endpoint', 'post', 'requestBody', '$ref')) assert val == '#/components/schemas/_schemas.json_Body'
def test_get_informative_key_error(): base = { 'foo': { 'bar': [123] } } # Match that the object being examing has its path printed, as # well as that the key is included. with pytest.raises(KeyError, match = r'.*"/".*asdf'): path_get(base, ('asdf',)) with pytest.raises(KeyError, match = r'.*"/foo".*asdf'): path_get(base, ('foo', 'asdf'))
def test_get_informative_key_error(): base = {"foo": {"bar": [123]}} # Match that the object being examing has its path printed, as # well as that the key is included. with pytest.raises(KeyError, match=r'.*"/".*asdf'): path_get(base, ("asdf",)) with pytest.raises(KeyError, match=r'.*"/foo".*asdf'): path_get(base, ("foo", "asdf"))
def test_issue_65_partial_resolution_files(): specs = '''openapi: "3.0.0" info: title: '' version: '1.0.0' paths: {} components: schemas: SampleArray: type: array items: $ref: '#/components/schemas/ItemType' ItemType: type: integer ''' from prance.util import resolver parser = ResolvingParser(spec_string=specs, resolve_types=resolver.RESOLVE_FILES) from prance.util.path import path_get val = path_get(parser.specification, ('components', 'schemas', 'SampleArray', 'items')) assert '$ref' in val
def test_issue_65_partial_resolution_files(): specs = '''openapi: "3.0.0" info: title: '' version: '1.0.0' paths: {} components: schemas: SampleArray: type: array items: $ref: '#/components/schemas/ItemType' ItemType: type: integer ''' from prance.util import formats specs = formats.parse_spec(specs, 'issue_65.yaml') res = resolver.RefResolver(specs, fs.abspath('issue_65.yaml'), resolve_types = resolver.RESOLVE_FILES ) res.resolve_references() from prance.util.path import path_get val = path_get(res.specs, ('components', 'schemas', 'SampleArray', 'items')) assert '$ref' in val
def test_get_value_no_default(): value = 42 # No path can be resolved in a value type result = 666 with pytest.raises(TypeError): result = path_get(value, ('foo', 'bar')) assert result == 666 # However, we can resolve zero length paths result = path_get(value, ()) assert 42 == result result = path_get(None, ()) assert result is None # Also we can resolve None-type paths result = path_get(value, None) assert 42 == result result = path_get(None, None) assert result is None
def test_get_value_default(): value = 42 # No path can be resolved in a value type result = None with pytest.raises(TypeError): result = path_get(value, ('foo', 'bar'), 123) assert result is None # However, we can resolve zero length paths result = path_get(value, (), 123) assert 42 == result result = path_get(None, (), 123) assert 123 == result # Also we can resolve None-type paths result = path_get(value, None, 321) assert 42 == result result = path_get(None, None, 321) assert 321 == result
def test_issue_23_partial_resolution_http(mock_get): mock_get.side_effect = mock_get_petstore specs = get_specs('tests/specs/with_externals.yaml') res = resolver.RefResolver(specs, fs.abspath('tests/specs/with_externals.yaml'), resolve_types = resolver.RESOLVE_HTTP ) res.resolve_references() # By default, all externals need to be resolved. from prance.util.path import path_get val = path_get(res.specs, ('paths', '/pets', 'get', 'responses', '200', 'schema')) assert '$ref' in val val = path_get(res.specs, ('paths', '/pets', 'get', 'responses', 'default', 'schema')) assert '$ref' in val val = path_get(res.specs, ('paths', '/pets', 'post', 'responses', 'default', 'schema')) assert '$ref' in val val = path_get(res.specs, ('paths', '/pets/{petId}', 'get', 'parameters', 0)) assert '$ref' in val val = path_get(res.specs, ('paths', '/pets/{petId}', 'get', 'responses', '200', 'schema')) assert '$ref' not in val val = path_get(res.specs, ('paths', '/pets/{petId}', 'get', 'responses', 'default', 'schema')) assert '$ref' in val
def test_get_bad_path(): # Raise with bad path types with pytest.raises(TypeError): path_get({}, 42) with pytest.raises(TypeError): path_get({}, 3.14) with pytest.raises(KeyError): path_get([], ('a', 'b'))
def _dereference(self, ref_url, obj_path): """ Dereference the URL and object path. Returns the dereferenced object. :param mixed ref_url: The URL at which the reference is located. :param list obj_path: The object path within the URL resource. :param tuple recursions: A recursion stack for resolving references. :return: A copy of the dereferenced value, with all internal references resolved. """ # In order to start dereferencing anything in the referenced URL, we have # to read and parse it, of course. contents = _url.fetch_url(ref_url, self.__reference_cache, strict=self.__strict) # In this inner parser's specification, we can now look for the referenced # object. value = contents if len(obj_path) != 0: from prance.util.path import path_get try: value = path_get(value, obj_path) except (KeyError, IndexError, TypeError) as ex: raise _url.ResolutionError( f'Cannot resolve reference "{ref_url.geturl()}": {str(ex)}' ) # Deep copy value; we don't want to create recursive structures import copy value = copy.deepcopy(value) # Now resolve partial specs value = self._translate_partial(ref_url, value) # That's it! return value
def test_issue_78_resolve_internal_bug(): specs = '' with open('tests/specs/issue_78/openapi.json', 'r') as fh: specs = fh.read() from prance.util import formats specs = formats.parse_spec(specs, 'openapi.json') res = resolver.RefResolver(specs, fs.abspath('openapi.json'), resolve_types = resolver.RESOLVE_FILES ) res.resolve_references() from prance.util.path import path_get val = path_get(res.specs, ('paths', '/endpoint', 'post', 'requestBody', 'content')) # Reference to file is resolved assert 'application/json' in val # Internal reference within file is NOT resolved assert '$ref' in val['application/json']
def test_issue_77_internal_refs_unresolved(): specs = '' with open('tests/specs/issue_78/openapi.json', 'r') as fh: specs = fh.read() from prance.util import formats specs = formats.parse_spec(specs, 'openapi.json') res = resolver.RefResolver(specs, fs.abspath('openapi.json'), resolve_types=resolver.RESOLVE_FILES, resolve_method=resolver.TRANSLATE_EXTERNAL) res.resolve_references() from prance.util.path import path_get val = path_get(res.specs, ('components', 'schemas')) # File reference resolved assert '_schemas.json_Body' in val # Internal file reference not resolved assert '_schemas.json_Something' not in val
def test_get_mapping_default(): value = { 'foo': 1, 'bar': 2, 3: 3 } # String paths should work in a Mapping result = path_get(value, ('foo',), 123) assert 1 == result # So should numeric keys result = path_get(value, (3,), 123) assert 3 == result # Zero length paths should return the value or default value result = path_get(value, (), 123) assert { 'foo': 1, 'bar': 2, 3: 3 } == result result = path_get(None, (), 123) assert 123 == result # And None paths as well result = path_get(value, None, 321) assert { 'foo': 1, 'bar': 2, 3: 3 } == result result = path_get(None, None, 321) assert 321 == result
def test_get_collection_no_default(): value = (1, 2, 3) # String paths in a Sequence should raise KeyError result = None with pytest.raises(KeyError): result = path_get(value, ('foo', 'bar')) assert result is None # A numeric path should work, though result = path_get(value, (1,)) assert 2 == result # Zero length paths should return the value or default value result = path_get(value, ()) assert (1, 2, 3) == result result = path_get(None, ()) assert result is None # And None paths as well result = path_get(value, None) assert (1, 2, 3) == result result = path_get(None, None) assert result is None
def test_get_informative_index_error(): base = { 'foo': { 'bar': [123] } } with pytest.raises(IndexError, match = r'.*"/foo/bar".*123'): path_get(base, ('foo', 'bar', 123))
def test_get_informative_index_error(): base = {"foo": {"bar": [123]}} with pytest.raises(IndexError, match=r'.*"/foo/bar".*123'): path_get(base, ("foo", "bar", 123))