Exemplo n.º 1
0
def test_fetch_url_text_cached():
  from prance.util import fs
  cache = {}

  content1, _ = url.fetch_url_text(url.absurl(fs.abspath('tests/specs/with_externals.yaml')), cache)
  content2, _ = url.fetch_url_text(url.absurl(fs.abspath('tests/specs/with_externals.yaml')), cache)

  # Strings are immutable, therefore IDs should be identical
  assert id(content1) == id(content2)
Exemplo n.º 2
0
def test_fetch_url_cached():
  from prance.util import fs
  cache = {}

  content1 = url.fetch_url(url.absurl(fs.abspath('tests/specs/with_externals.yaml')), cache)
  assert content1['swagger'] == '2.0'

  content2 = url.fetch_url(url.absurl(fs.abspath('tests/specs/with_externals.yaml')), cache)
  assert content2['swagger'] == '2.0'

  # Dicts are mutable, therefore we can't compare IDs. But individual
  # string fields should not be copied, because we shallow copy.
  assert id(content1['swagger']) == id(content2['swagger'])
Exemplo n.º 3
0
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
Exemplo n.º 4
0
def test_abspath_relative_dir():
    testname = 'error.json'
    relative = os.path.join(os.getcwd(), 'tests', 'specs')
    res = fs.abspath(testname, relative)
    expected = fs.to_posix(
        os.path.join(os.getcwd(), 'tests', 'specs', testname))
    assert res == expected
Exemplo n.º 5
0
def test_recursion_limit_set_limit_ignore_files(recursion_limit_files_file):
  # If we overload the handler, and set the recursion limit higher,
  # we should get nested Pet objects a few levels deep.

  import os.path
  res = resolver.RefResolver(recursion_limit_files_file,
      fs.abspath('tests/recursion_limit_files.yaml'),
      recursion_limit = 2,
      recursion_limit_handler = recursion_limit_handler_none)
  res.resolve_references()

  from prance.util import formats
  contents = formats.serialize_spec(res.specs, 'foo.yaml')

  # The effect of returning None on recursion limit should be that
  # despite having recursion, the outermost reference to
  # definitions/Pet should get resolved.
  assert 'properties' in res.specs['paths']['/pets']['get']['responses']['200']['schema']

  # However, the 'next' field should be resolved due to the higher recursion limit
  next_field = res.specs['paths']['/pets']['get']['responses']['200']['schema']['properties']['next']['schema']
  assert next_field is not None

  # But the 'next' field of the 'next' field should not be resolved.
  assert next_field['properties']['next']['schema'] is None
Exemplo n.º 6
0
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'
Exemplo n.º 7
0
def test_abspath_relative():
    testname = 'error.json'
    relative = os.path.join(os.getcwd(), 'tests/specs/with_externals.yaml')
    res = fs.abspath(testname, relative)
    expected = fs.to_posix(
        os.path.join(os.getcwd(), 'tests', 'specs', testname))
    assert res == expected
Exemplo n.º 8
0
def test_issue_23_partial_resolution_invalid_scheme():
  specs = {'$ref': 'foo://cannot-do-anything'}
  res = resolver.RefResolver(specs,
      fs.abspath('tests/specs/with_externals.yaml'))

  with pytest.raises(ValueError):
    res.resolve_references()
Exemplo n.º 9
0
def test_abspath_relative_dir():
    testname = "error.json"
    relative = os.path.join(os.getcwd(), "tests", "specs")
    res = fs.abspath(testname, relative)
    expected = fs.to_posix(
        os.path.join(os.getcwd(), "tests", "specs", testname))
    assert res == expected
Exemplo n.º 10
0
def __parser_for_url(url, resolve, backend, strict):  # noqa: N802
    """Return a parser instance for the URL and the given parameters."""
    # Try the URL
    formatted = click.format_filename(url)
    click.echo('Processing "%s"...' % (formatted, ))

    from prance.util import fs
    fsurl = fs.abspath(url)
    import os.path
    if os.path.exists(fs.from_posix(fsurl)):
        url = fsurl

    # Create parser to use
    if resolve:
        click.echo(' -> Resolving external references.')
        return CustomResolvingParser(url,
                                     lazy=True,
                                     backend=backend,
                                     strict=strict,
                                     recursion_limit=2), formatted
    else:
        click.echo(' -> Not resolving external references.')
        return prance.BaseParser(url,
                                 lazy=True,
                                 backend=backend,
                                 strict=strict), formatted
Exemplo n.º 11
0
def __parser_for_url(url, resolve, backend, strict, encoding):  # noqa: N802
  """Return a parser instance for the URL and the given parameters."""
  # Try the URL
  formatted = click.format_filename(url)
  click.echo('Processing "%s"...' % (formatted, ))

  from prance.util import fs
  fsurl = fs.abspath(url)
  import os.path
  if os.path.exists(fs.from_posix(fsurl)):
    url = fsurl

  # Create parser to use
  parser = None
  if resolve:
    click.echo(' -> Resolving external references.')
    parser = prance.ResolvingParser(url, lazy = True, backend = backend,
            strict = strict, encoding = encoding)
  else:
    click.echo(' -> Not resolving external references.')
    parser = prance.BaseParser(url, lazy = True, backend = backend,
            strict = strict, encoding = encoding)

  # XXX maybe enable tihs in debug mode or something.
  # click.echo(' -> Using backend: {0.backend}'.format(parser))
  return parser, formatted
Exemplo n.º 12
0
def test_abspath_relative():
    testname = "error.json"
    relative = os.path.join(os.getcwd(), "tests/specs/with_externals.yaml")
    res = fs.abspath(testname, relative)
    expected = fs.to_posix(
        os.path.join(os.getcwd(), "tests", "specs", testname))
    assert res == expected
Exemplo n.º 13
0
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
Exemplo n.º 14
0
def test_issue_22_empty_path(mock_get, externals_file):
  mock_get.side_effect = mock_get_petstore

  # The raw externals file must have unresolved data
  assert len(externals_file['paths']['/pets/{petId}']['get']['parameters']) == 1
  param = externals_file['paths']['/pets/{petId}']['get']['parameters'][0]

  assert 'overwritten' in param
  assert '$ref' in param

  import os.path
  from prance.util import fs
  res = resolver.RefResolver(externals_file,
      fs.abspath('tests/specs/with_externals.yaml'))
  res.resolve_references()

  # The tests should resolve the reference, but the reference overwrites
  # all else.
  assert len(res.specs['paths']['/pets/{petId}']['get']['parameters']) == 1
  param = res.specs['paths']['/pets/{petId}']['get']['parameters'][0]

  # Dereferenced keys must exist here
  assert 'type' in param
  assert 'description' in param
  assert 'required' in param
  assert 'in' in param
  assert 'name' in param

  # Previously defined keys must not
  assert 'overwritten' not in param
  assert '$ref' not in param
Exemplo n.º 15
0
def test_resolver_named(mock_get, externals_file):
  mock_get.side_effect = mock_get_petstore

  import os.path
  from prance.util import fs
  res = resolver.RefResolver(externals_file,
      fs.abspath('tests/specs/with_externals.yaml'))
  res.resolve_references()
Exemplo n.º 16
0
def test_resolver_recursive(recursive_file):
    import os.path
    res = resolver.RefResolver(recursive_file,
                               fs.abspath('tests/recursive.yaml'))
    with pytest.raises(ResolutionError) as exc:
        res.resolve_references()

    assert str(exc.value).startswith('Recursion detected')
Exemplo n.º 17
0
def test_resolver_missing_reference(missing_file):
  import os.path
  res = resolver.RefResolver(missing_file,
      fs.abspath('tests/missing_reference.yaml'))
  with pytest.raises(ResolutionError) as exc:
    res.resolve_references()

  assert str(exc.value).startswith('Cannot resolve')
Exemplo n.º 18
0
def test_resolver_recursive_files(mock_get, recursive_files_file):
  mock_get.side_effect = mock_get_petstore

  # Recursive references to files are not a problem
  import os.path
  res = resolver.RefResolver(recursive_files_file,
      fs.abspath('tests/specs/recursive_files.yaml'))
  res.resolve_references()
Exemplo n.º 19
0
def validate(resolve, strict, output_file, urls):
    """
  Validate the given spec or specs.

  If the --resolve option is set, references will be resolved before
  validation.

  Note that this can yield unexpected results. The swagger-spec-validator used
  as a basis for prance cannot deal with relative file path references, and
  will report them. However, resolving these references before validation will
  skip these errors.

  If the --output-file option is given, the validated spec is written to that
  file. Please note that with that option given, only one input file may be
  specified.
  """
    # Ensure that when an output file is given, only one input file exists.
    if output_file and len(urls) > 1:
        raise click.UsageError('If --output-file is given, only one input URL '
                               'is allowed!')

    import os.path
    from prance.util import fs
    # Process files
    for url in urls:
        formatted = click.format_filename(url)
        click.echo('Processing "%s"...' % (formatted, ))
        fsurl = fs.abspath(url)
        if os.path.exists(fs.from_posix(fsurl)):
            url = fsurl

        # Create parser to use
        if resolve:
            click.echo(' -> Resolving external references.')
            parser = prance.ResolvingParser(url, lazy=True, strict=strict)
        else:
            click.echo(' -> Not resolving external references.')
            parser = prance.BaseParser(url, lazy=True, strict=strict)

        # Try parsing
        from prance.util.url import ResolutionError
        from swagger_spec_validator.common import SwaggerValidationError
        try:
            parser.parse()
        except (ResolutionError, SwaggerValidationError) as err:
            msg = 'ERROR in "%s" [%s]: %s' % (formatted, type(err).__name__,
                                              str(err))
            click.secho(msg, err=True, fg='red')
            import sys
            sys.exit(1)

        # All good, next file.
        click.echo('Validates OK as Swagger/OpenAPI 2.0!')

        # If an output file is given, write the specs to it.
        if output_file:
            __write_to_file(output_file, parser.specification)
Exemplo n.º 20
0
def test_issue_69_urlparse_error():
    specs = {'$ref': "file://a\u2100b/bad/netloc"}
    res = resolver.RefResolver(specs,
                               fs.abspath('tests/specs/with_externals.yaml'))

    with pytest.raises(ResolutionError) as ex:
        res.resolve_references()

    assert 'bad/netloc' in str(ex)
Exemplo n.º 21
0
def test_issue_72_nonexistent_file_error():
  specs = {'$ref': "file://does/not/exist"}
  res = resolver.RefResolver(specs,
      fs.abspath('tests/specs/with_externals.yaml'))

  with pytest.raises(ResolutionError) as exinfo:
    res.resolve_references()

  assert 'not/exist' in str(exinfo.value)
Exemplo n.º 22
0
def test_resolver_recursive_objects(recursive_objs_file):
  # Recursive references to objects are a problem
  import os.path
  res = resolver.RefResolver(recursive_objs_file,
      fs.abspath('tests/recursive_objs.yaml'))
  with pytest.raises(ResolutionError) as exc:
    res.resolve_references()

  assert str(exc.value).startswith('Recursion reached limit')
Exemplo n.º 23
0
def test_recursion_limit_do_not_recurse_raise_files(recursion_limit_files_file):
  # Expect the default behaviour to raise.
  import os.path
  res = resolver.RefResolver(recursion_limit_files_file,
      fs.abspath('tests/recursion_limit_files.yaml'))
  with pytest.raises(ResolutionError) as exc:
    res.resolve_references()

  assert str(exc.value).startswith('Recursion reached limit of 1')
Exemplo n.º 24
0
def test_issue_38_tilde_one():
  specs = get_specs('tests/specs/issue_38_a.yaml')
  res = resolver.RefResolver(specs,
      fs.abspath('tests/specs/issue_38_a.yaml'))
  res.resolve_references()

  path = res.specs['paths']['/api/v2/vms']
  assert 'get' in path
  assert 'operationId' in path['get']
  assert 'description' in path['get']
Exemplo n.º 25
0
def test_resolver_missing_reference(mock_get, missing_file):
  mock_get.side_effect = mock_get_petstore

  import os.path
  res = resolver.RefResolver(missing_file,
      fs.abspath('tests/specs/missing_reference.yaml'))
  with pytest.raises(ResolutionError) as exc:
    res.resolve_references()

  assert str(exc.value).startswith('Cannot resolve')
Exemplo n.º 26
0
def test_issue_69_urlparse_error():
  # XXX depending on python version, the error may not actually come from
  #     parsing the URL, but from trying to load a local file that does
  #     not exist. See test_issue_72_* for a test case that specifically
  #     tries for a nonexistent file url.
  specs = {'$ref': "file://a\u2100b/bad/netloc"}
  res = resolver.RefResolver(specs,
      fs.abspath('tests/specs/with_externals.yaml'))

  with pytest.raises(ResolutionError) as exinfo:
    res.resolve_references()

  assert 'bad/netloc' in str(exinfo.value)
Exemplo n.º 27
0
def test_issue_205_swagger_resolution_failure():
  specs = ''
  with open('tests/specs/kubernetes_api_docs.json', 'r') as fh:
    specs = fh.read()

  from prance.util import formats
  specs = formats.parse_spec(specs, 'kubernetes_api_docs.json')

  res = resolver.RefResolver(specs,
    fs.abspath('kubernetes_api_docs.json'),
    resolve_types = resolver.RESOLVE_FILES,
    resolve_method= resolver.TRANSLATE_EXTERNAL
  )
  # test will raise an exception
  res.resolve_references()
Exemplo n.º 28
0
def test_recursion_limit_do_not_recurse_ignore_files(recursion_limit_files_file):
  # If we overload the handler, we should not get an error but should
  # also simply not have the 'next' field - or it should be None
  import os.path
  res = resolver.RefResolver(recursion_limit_files_file,
      fs.abspath('tests/recursion_limit_files.yaml'),
      recursion_limit_handler = recursion_limit_handler_none)
  res.resolve_references()

  from prance.util import formats
  contents = formats.serialize_spec(res.specs, 'foo.yaml')

  # The effect of returning None on recursion limit should be that
  # despite having recursion, the outermost reference to
  # definitions/Pet should get resolved.
  assert 'properties' in res.specs['paths']['/pets']['get']['responses']['200']['schema']

  # However, the 'next' field should not be resolved.
  assert res.specs['paths']['/pets']['get']['responses']['200']['schema']['properties']['next']['schema'] is None
Exemplo n.º 29
0
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']
Exemplo n.º 30
0
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