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'
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')
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)
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)
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)
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
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
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
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!')
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))