def test_spec(client):
    """Check wether the spec endpoint is valid and available"""
    spec_url = f"v0.1/spec"
    response = client.get(spec_url)
    assert response.status_code == 200, 'Spec should be available'
    assert list(openapi_v3_spec_validator.iter_errors(
        response.get_json())) == [], 'Spec should pass validation'
Exemple #2
0
def validate_specification(spec):
    errors_iterator = openapi_v3_spec_validator.iter_errors(spec)
    l = list(errors_iterator)
    if (len(l) > 0):
        print(len(l), 'errors')
        sys.exit()

    print('specification is valid')
Exemple #3
0
    def perform_request(self):
        """
        Perform the validation.
        Uses https://github.com/p1c2u/openapi-spec-validator on
        the specfile (dict) returned from the OpenAPI endpoint.
        """

        # Step 1 basic sanity check
        result = Result(True, 'OpenAPI Validation Test')
        result.start()
        api_doc = None
        try:
            wfs3 = WebFeatureService(self._resource.url, version='3.0')

            # TODO: OWSLib 0.17.1 has no call to '/api yet.
            # Build endpoint URL (may have f=json etc)
            api_url = wfs3._build_url('api')

            # Get OpenAPI spec from endpoint as dict once
            api_doc = requests.get(api_url).json()

            # Basic sanity check
            for attr in ['components', 'paths', 'openapi']:
                val = api_doc.get(attr, None)
                if val is None:
                    msg = '/api: missing attr: %s' % attr
                    result.set(False, msg)
                    break
        except Exception as err:
            result.set(False, str(err))

        result.stop()
        self.result.add_result(result)

        # No use to proceed if OpenAPI basics not complied
        if api_doc is None or result.success is False:
            return

        # ASSERTION: /api exists, next OpenAPI Validation

        # Step 2 detailed OpenAPI Compliance test
        result = Result(True, 'Validate OpenAPI Compliance')
        result.start()
        try:
            # Call the openapi-spec-validator and iterate through errors
            errors_iterator = openapi_v3_spec_validator.iter_errors(api_doc)
            for error in errors_iterator:
                # Add each validation error as separate Result object
                result = push_result(self, result, False, str(error),
                                     'OpenAPI Compliance Result')
        except Exception as err:
            result.set(False, 'OpenAPI Validation err: e=%s' % str(err))

        result.stop()

        # Add to overall Probe result
        self.result.add_result(result)
Exemple #4
0
    def perform_request(self):
        """
        Perform the validation.
        Uses https://github.com/p1c2u/openapi-spec-validator on
        the specfile (dict) returned from the OpenAPI endpoint.
        """

        # Step 1 basic sanity check
        result = Result(True, 'OpenAPI Sanity Check')
        result.start()
        api_doc = None
        try:
            oa_feat = Features(self._resource.url,
                               headers=self.get_request_headers())

            set_accept_header(oa_feat, type_for_link(
                oa_feat.links, 'service-desc'))
            api_doc = oa_feat.api()

            # Basic sanity check
            for attr in ['components', 'paths', 'openapi']:
                val = api_doc.get(attr, None)
                if val is None:
                    msg = 'OpenAPI doc: missing attr: %s' % attr
                    result.set(False, msg)
                    break
        except Exception as err:
            result.set(False, '%s:%s' % (result.message, str(err)))

        result.stop()
        self.result.add_result(result)

        # No use to proceed if OpenAPI basics not complied
        if api_doc is None or result.success is False:
            return

        # ASSERTION: OpenAPI doc exists, next OpenAPI Validation

        # Step 2 detailed OpenAPI Compliance test
        result = Result(True, 'Validate OpenAPI Compliance')
        result.start()
        try:
            # Call the openapi-spec-validator and iterate through errors
            errors_iterator = openapi_v3_spec_validator.iter_errors(api_doc)
            for error in errors_iterator:
                # Add each validation error as separate Result object
                result = push_result(
                    self, result, False,
                    str(error), 'OpenAPI Compliance Result')
        except Exception as err:
            result.set(False, '%s:%s' % (result.message, str(err)))

        result.stop()

        # Add to overall Probe result
        self.result.add_result(result)
Exemple #5
0
    def test_yaml_schema(self):
        gen = OpenapiGenerator("Title", "Testing description", "0.0.1",
                               "https://swapi.co")
        response = requests.get("https://swapi.co/api/planets/",
                                params={"page": 2})
        gen.add_response(response)
        gen.export("example.yml", extension="yaml")

        with open("example.yml") as f:
            spec = yaml.load(f)
        errors_iterator = openapi_v3_spec_validator.iter_errors(spec)
        self.assertEqual(len(list(errors_iterator)), 0)
Exemple #6
0
def validate_specification(spec):
    """Validates the specification using **openapi_spec_validator** library

    Args:
        spec (dict): OpenAPI 3.0 specification as a dictionary
    """
    errors_iterator = openapi_v3_spec_validator.iter_errors(spec)
    errors = list(errors_iterator)
    if (len(errors) > 0):
        print(len(errors), 'errors')
        sys.exit()

    print('specification is valid')
def validate(url):
    counter = 0

    try:
        handler = UrlHandler("http", "https", "file")

        if not urlparse(url).scheme:
            url = "file://" + path.join(getcwd(), url)

        spec = handler(url)

        for i in openapi_v3_spec_validator.iter_errors(spec, spec_url=url):
            counter += 1
            print_error(counter, ":".join(i.absolute_path), i.message,
                        i.instance)

    except RefResolutionError as e:
        counter += 1
        print_error(
            counter,
            "",
            f"Unable to resolve {e.__context__.args[0]} in {e.args[0]}",
            "",
        )
    except BaseException:
        counter += 1
        print_error(counter, "", sys.exc_info()[0], "")
    finally:
        if counter > 0:
            print()
            print(
                color(
                    " [FAIL] %d errors found " % counter,
                    fg="white",
                    bg="red",
                    style="bold",
                ))
            return 1
        else:
            print_ok(" [PASS] No errors found ")
            return 0
Exemple #8
0
def validate(url):
    counter = 0

    try:
        handler = UrlHandler('http', 'https', 'file')

        if not urlparse(url).scheme:
            url = 'file://' + path.join(getcwd(), url)

        spec = handler(url)

        for i in openapi_v3_spec_validator.iter_errors(spec, spec_url=url):
            counter += 1
            print_error(counter, ':'.join(i.absolute_path), i.message,
                        i.instance)

    except RefResolutionError as e:
        counter += 1
        print_error(
            counter, '',
            f'Unable to resolve {e.__context__.args[0]} in {e.args[0]}', '')
    except BaseException:
        counter += 1
        print_error(counter, '', sys.exc_info()[0], '')
    finally:
        if counter > 0:
            print()
            print(
                color(' [FAIL] %d errors found ' % counter,
                      fg='white',
                      bg='red',
                      style='bold'))
            return 1
        else:
            print(
                color(' [PASS] No errors found ',
                      fg='white',
                      bg='green',
                      style='bold'))
            return 0
Exemple #9
0
    def test_audio_file(self):
        gen = OpenapiGenerator("Title", "Testing description", "0.0.1",
                               "test.audio.upload")
        lnk = "test.audio.upload"
        with open('test.wav', 'rb') as f:
            aud = f.read()

        response = requests.post(
            lnk,
            data=aud,
            headers={
                'Content-Type':
                'application/body-data;rate={};channels={}'.format(16000, 1)
            })

        gen.add_response(response)
        gen.export("wav.json", extension="json")

        with open("wav.json") as f:
            spec = json.load(f)
        errors_iterator = openapi_v3_spec_validator.iter_errors(spec)
        self.assertEqual(len(list(errors_iterator)), 0)
def validate_specification(spec, spec_url):
    """This function validates specification file (usually openapi.yaml) or url"""
    counter = 0
    try:
        for i in openapi_v3_spec_validator.iter_errors(spec,
                                                       spec_url=spec_url):
            counter += 1
            print_error(counter, ':'.join(i.absolute_path), i.message,
                        i.instance)

    except RefResolutionError as e:
        counter += 1
        print_error(
            counter, '',
            'Unable to resolve {} in {}'.format(e.__context__.args[0],
                                                e.args[0]), '')

    except BaseException:
        counter += 1
        print_error(counter, '', sys.exc_info()[0], '')

    finally:
        if counter > 0:
            print()
            print(
                color(' [FAIL] {:d} errors found '.format(counter),
                      fg='white',
                      bg='red',
                      style='bold'))
            return 1
        else:
            print(
                color(' [PASS] No errors found ',
                      fg='white',
                      bg='green',
                      style='bold'))
            return 0
def validate_specification(spec, spec_url):
    """This function validates specification file (usually openapi.yaml) or url"""
    counter = 0
    try:
        for i in openapi_v3_spec_validator.iter_errors(spec, spec_url=spec_url):
            counter += 1
            print_error(counter, ':'.join(i.absolute_path), i.message, i.instance)

    except RefResolutionError as e:
        counter += 1
        print_error(counter, '', 'Unable to resolve {} in {}'.format(e.__context__.args[0], e.args[0]), '')

    except BaseException:
        counter += 1
        print_error(counter, '', sys.exc_info()[0], '')

    finally:
        if counter > 0:
            print()
            print(color(' [FAIL] {:d} errors found '.format(counter), fg='white', bg='red', style='bold'))
            return 1
        else:
            print(color(' [PASS] No errors found ', fg='white', bg='green', style='bold'))
            return 0
Exemple #12
0
    def handle(self, module_name, *args, **kwargs):
        """
        Parse documentation information for the specified module.

        This command works like a top down parser, starting by parsing the module itself then parsing each of the
        view files and their serializers, then the methods and their controllers and/or permissions.

        The method lastly validates the openapi spec to make sure it's valid before writing out to `settings.DOCS_PATH`
        """
        # Set up logger
        logging.basicConfig(format='%(levelname)-8s: %(message)s')
        self.logger = logging.getLogger('docgen')
        self.logger.setLevel(
            logging.INFO if not kwargs['debug'] else logging.DEBUG)
        # Set up structure and initial settings
        start = perf_counter()
        self.spec = defaults.DEFAULT_SPEC

        # Attempt to import the module
        self.module_name = module_name
        module = import_module(module_name)

        # Update the `info` field with details from the module
        self.parse_module(module)

        # Load the controller, serializer and views modules here instead of multiple times
        self.controller_mod = import_module(f'{module_name}.controllers')
        self.serializer_mod = import_module(f'{module_name}.serializers')
        self.view_module = import_module(f'{module_name}.views')

        # Iterate through all the view files to build tags
        for attr_name in dir(self.view_module):
            attr = getattr(self.view_module, attr_name)
            if isinstance(attr, types.ModuleType):
                self.view_file = attr
                self.parse_view_file()

        # Iterate through the URL patterns to start building paths
        urlpatterns = import_module(f'{module_name}.urls').urlpatterns
        for urlpattern in urlpatterns:
            self.parse_urlpattern(urlpattern)

        # Check for errors generated while parsing
        if self.errors:
            self.logger.error('ERRORS FOUND WHEN PARSING DOCUMENTATION')
            sys.exit(1)

        # Now validate the generated spec (dump and load to make all keys strings)
        self.logger.info('OpenAPI Spec Error Checking')
        errors = openapi_v3_spec_validator.iter_errors(
            json.loads(json.dumps(self.spec)))
        valid = True
        for error in errors:
            valid = False
            self.logger.error(f'{error.message} @ {error.path}')
        if not valid:
            sys.exit(1)
        else:
            self.logger.info('OK')

        # Write out the generated docs to a JSON file
        output_path = kwargs['output'] or settings.DOCS_PATH
        with open(output_path, 'w') as f:
            json.dump(self.spec, f, sort_keys=True)
        end = perf_counter()

        self.logger.info(f'Documentation generated in {end - start} seconds!')
Exemple #13
0
target = sys.argv[1]
pretty = len(sys.argv) > 2 and sys.argv[2] == 'pretty'

error_symbol = '❌  ' if pretty else '!!!'
ok_symbol = '✅ ' if pretty else ''

if not os.path.isfile(target):
    print("File not found: {}".format(target))
    sys.exit(2)

with open(target) as f:
    spec = yaml.safe_load(f.read())

has_errors=False
errors = openapi_v3_spec_validator.iter_errors(spec)

try:
    for e in errors:
        has_errors=True
        print("{} {path}: {message}".format(error_symbol, path='.'.join(e.path), message=e.message))
except RefResolutionError as e:
    print("{} {}".format(error_symbol, e))
    has_errors=True


if has_errors:
    sys.exit(1)

print("{} OK".format(ok_symbol))