def test_get_employees_200_response_yaml(): with open("examples/employees.yaml") as f: response = f.read() oapi = build_openapi("GET", "/employees", "200", response=response) spec_dict, spec_url = read_from_filename( "tests/test_get_employees_200_response.yaml") assert oapi == spec_dict
def test_open_api_tag(self): spec = get_spec( 'test api', camel_case=True, default_response_descriptions={ HTTPStatus.INTERNAL_SERVER_ERROR: 'Unexpected internal server error.', HTTPStatus.NO_CONTENT: 'Operation succeeded. Nothing to return.', HTTPStatus.NOT_FOUND: 'Could not find data.', HTTPStatus.CREATED: 'Resource was created successfully.', HTTPStatus.BAD_REQUEST: 'Invalid input data.', HTTPStatus.OK: 'Success.' }, default_parameter_descriptions={ 'skip': 'The number of data records to skip before fetching a page.', 'take': 'Number of records to return. Use value -1 to get all data.', 'sortColumn': 'The database field to sort by. Use python_syntax for the field name.', 'sortDirection': 'The direction to sort by (asc or desc).', 'createdAt': 'Filter on the creation date. Use an exact date, or a date range e.g. \'[2018-01-01,2019-01-01[\', \']2018-01-01,\' or \'2015-01-01\'', 'modifiedAt': 'Filter on the last modification date. Use an exact date, or a date range e.g. \'[2018-01-01,2019-01-01[\', \']2018-01-01,\' or \'2015-01-01\'', 'ids': 'Ids to match.' }) self.assertEqual(spec['openapi'], '3.0.0') os.makedirs('./temp', exist_ok=True) spec_file = './temp/openapi.json' with open(spec_file, 'w') as file: file.write(json.dumps(spec, indent=4)) spec_dict, spec_url = read_from_filename(spec_file) validate_spec(spec_dict)
def test_get_employees_200_info(): oapi = build_openapi("GET", "/employees", "200", title="Custom Title", version="v1-custom") spec_dict, spec_url = read_from_filename( "tests/test_get_employees_200_info.yaml") assert oapi == spec_dict
def load_spec(): """Validate openapi spec.""" napp_dir = Path(__file__).parent yml_file = napp_dir / "openapi.yml" spec_dict, _ = read_from_filename(yml_file) validate_spec(spec_dict) return create_spec(spec_dict)
def test_get_employees_200_params(): oapi = build_openapi( "GET", "/employees", "200", parameters=[("id", "path"), ("limit", "query"), ("token", "header")], ) spec_dict, spec_url = read_from_filename( "tests/test_get_employees_200_params.yaml") assert oapi == spec_dict
def test_post_employees_201_request_response(): with open("examples/new_employee_req.json") as f: request = f.read() with open("examples/new_employee_resp.json") as f: response = f.read() oapi = build_openapi("POST", "/employees", "201", request=request, response=response) spec_dict, spec_url = read_from_filename( "tests/test_post_employees_201_request_response.yaml") assert oapi == spec_dict
def test_get_employees_200_response_mediatype(): with open("examples/employees.json") as f: response = f.read() oapi = build_openapi( "GET", "/employees", "200", response=response, media_type="application/yaml", ) spec_dict, spec_url = read_from_filename( "tests/test_get_employees_200_response_mediatype.yaml") assert oapi == spec_dict
def __init__(self, path: str): self.path = path self.body, self.url = read_from_filename(path) self.ref_resolver = RefResolver.from_schema(self.body)
def test_get_employees_200(): oapi = build_openapi("GET", "/employees", "200") spec_dict, spec_url = read_from_filename( "tests/test_get_employees_200.yaml") assert oapi == spec_dict
def ChillApi(app: Flask = None, config_file: str = _CONFIG_FILE, export_path: str = f"{CWD}/var"): """ChillApi Loader. :param app: param config_file: :param export_path: :param app: Flask: (Default value = None) :param config_file: str: (Default value = _CONFIG_FILE) :param export_path: str: (Default value = f"{CWD}/var") """ if not os.path.exists(export_path): os.makedirs(export_path) SCHEMA_CONFIG_FILE = os.path.realpath( f"{pathlib.Path(__file__).parent.absolute()}/api.schema.json") api_config = read_yaml(config_file) api_schema = json.load(open(SCHEMA_CONFIG_FILE)) try: validate(instance=api_config, schema=api_schema) except ValidationError as e: raise ConfigError(e) _app_name = api_config["app"]["name"] if app is None: app = Flask(_app_name) ApiConfig.reset() module_loader = ChillApiModuleLoader() set_api_security(api_config, module_loader) extensions = ChillApiExtensions(module_loader) config = ApiConfig(**{**api_config, **{"extensions": extensions}}) db = config.db data_repository = config.repository api_manager = FlaskApiManager(config) register_error_handlers(app) app.config["BASE_DIR"] = CWD # app.config["SQLALCHEMY_DATABASE_URI"] = os.environ.get("__CHILLAPI_DB_DSN__") app.config["SECRET_KEY"] = os.environ.get("__CHILLAPI_APP_SECRET_KEY__") app.config["WTF_CSRF_ENABLED"] = False app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = True app.config["TRAP_HTTP_EXCEPTIONS"] = True app.config["TRAP_BAD_REQUEST_ERRORS"] = True app.config["REQUEST_ID_UNIQUE_VALUE_PREFIX"] = None CORS(app) RequestID(app) api = Api( app, security_level=api_config["app"]["security_level"] if "security_level" in api_config["app"] else "STANDARD", version=api_config["app"]["version"], api_spec_url=api_config["app"]["swagger_url"], security=api_config["app"]["security"] if "security" in api_config["app"] else None, license=api_config["app"]["license"] if "license" in api_config["app"] else None, contact=api_config["app"]["contact"] if "contact" in api_config["app"] else None, externalDocs=api_config["app"]["externalDocs"] if "externalDocs" in api_config["app"] else None, components={ "securitySchemes": api_config["app"]["securitySchemes"] if "securitySchemes" in api_config["app"] else None }, ) api_doc.SwaggerUI(app, title=_app_name, doc=api_config["app"]["swagger_ui_url"], config={"app_name": _app_name}) # Swagger UI config overrides api_spec_file = f"{export_path}/api_spec.json" if not os.path.exists(api_spec_file): import requests url = "https://raw.githubusercontent.com/OAI/OpenAPI-Specification/main/schemas/v3.1/schema.yaml" # noqa E501 r = requests.get(url, allow_redirects=True) open(api_spec_file, "wb").write(r.content) path_full = api_spec_file schema_v3 = read_yaml_file(path_full) schema_v3_url = parse.urljoin("file:", request.pathname2url(path_full)) openapi_v3_validator_factory = JSONSpecValidatorFactory( schema_v3, schema_v3_url, resolver_handlers=default_handlers, ) openapi_v3_spec_validator = SpecValidator( openapi_v3_validator_factory, resolver_handlers=default_handlers, ) simplejson.dump(api.get_swagger_doc(), open(f"{export_path}/{_app_name}_swagger.json", "w"), indent=2, cls=CustomEncoder, for_json=True) spec_dict, spec_url = read_from_filename( f"{export_path}/{_app_name}_swagger.json") # If no exception is raised by validate_spec(), the spec is valid. # do not stop the execution but show a critical errors_iterator = openapi_v3_spec_validator.iter_errors(spec_dict) for _ie, err in enumerate(errors_iterator): logger.critical(err) simplejson.dump(config.to_dict(), open(f"{export_path}/{_app_name}_api.config.json", "w"), indent=2, cls=CustomEncoder, for_json=True) api_manager.create_api(api) # register_audit_handler(app, extensions.get_extension("audit")) if api_config["app"]["debug"]: if not os.path.exists(f"{export_path}/profile"): os.makedirs(f"{export_path}/profile") from werkzeug.middleware.profiler import ProfilerMiddleware app.config["PROFILE"] = True app.config["DEBUG"] = True def filename_format(env): """ :param env: """ return "{uuid}.prof".format(uuid=env["HTTP_X_REQUEST_ID"]) app.wsgi_app = ProfilerMiddleware(app.wsgi_app, restrictions=[30], profile_dir=f"{export_path}/profile", filename_format=filename_format) register_routes_sitemap(app) return AttributeDict({ "app": app, "api": api, "api_manager": api_manager, "api_config": api_config, "db": db, "data_repository": data_repository, "module_loader": module_loader, "table_extensions": extensions, })
from typing import Any from openapi_spec_validator.readers import read_from_filename from jinja2 import Template spec_dict, spec_url = read_from_filename('example-api.yaml') def openapi_type_to_python(property: Any, quote: bool = True) -> str: if property.get('$ref') is not None: res = f"{property['$ref'].rsplit('/', maxsplit=1)[1]}" return f"'{res}'" if quote else res if property['type'] == 'string': return 'str' elif property['type'] == 'boolean': return 'bool' elif property['type'] == 'integer': return 'int' elif property['type'] == 'number': return 'float' elif property['type'] == 'array': return f'List[{openapi_type_to_python(property["items"])}]' else: return 'object' with open('template.py', 'r+') as f: template = Template(f.read()) template.globals[ 'openapi_type_to_python'] = openapi_type_to_python # type: ignore