class_docstr: The `Flask` object with some web API support.
  
  Examples:
  
  ```python
  from apiflask import APIFlask
  
  app = APIFlask(__name__)
  ```
  
  Attributes:
      openapi_version: The version of OpenAPI Specification (openapi.openapi).
          This attribute can also be configured from the config with the
          `OPENAPI_VERSION` configuration key. Defaults to `'3.0.3'`.
      servers: The servers information of the API (openapi.servers), accepts
          multiple server dicts. Example value:
  
          ```python
          app.servers = [
              {
                  'name': 'Production Server',
                  'url': 'http://api.example.com'
              }
          ]
          ```
  
          This attribute can also be configured from the config with the
          `SERVERS` configuration key. Defaults to `None`.
      tags: The list of tags of the OpenAPI spec documentation (openapi.tags),
          accepts a list of dicts. You can also pass a simple list contains the
          tag name:
  
          ```python
          app.tags = ['foo', 'bar', 'baz']
          ```
  
          A standard OpenAPI tags list will look like this:
  
          ```python
          app.tags = [
              {'name': 'foo', 'description': 'The description of foo'},
              {'name': 'bar', 'description': 'The description of bar'},
              {'name': 'baz', 'description': 'The description of baz'}
          ]
          ```
  
          If not set, the blueprint names will be used as tags.
  
          This attribute can also be configured from the config with the
          `TAGS` configuration key. Defaults to `None`.
      external_docs: The external documentation information of the API
          (openapi.externalDocs). Example:
  
          ```python
          app.external_docs = {
              'description': 'Find more info here',
              'url': 'http://docs.example.com'
          }
          ```
  
          This attribute can also be configured from the config with the
          `EXTERNAL_DOCS` configuration key. Defaults to `None`.
      info: The info object (openapi.info), it accepts a dict contains following info fields:
          `description`, `termsOfService`, `contact`, `license`. You can use separate
          configuration variables to overwrite this dict. Example:
  
          ```python
          app.info = {
              'description': '...',
              'termsOfService': 'http://example.com',
              'contact': {
                  'name': 'API Support',
                  'url': 'http://www.example.com/support',
                  'email': 'support@example.com'
              },
              'license': {
                  'name': 'Apache 2.0',
                  'url': 'http://www.apache.org/licenses/LICENSE-2.0.html'
              }
          }
          ```
  
      description: The description of the API (openapi.info.description).
          This attribute can also be configured from the config with the
          `DESCRIPTION` configuration key. Defaults to `None`.
      contact: The contact information of the API (openapi.info.contact). Example:
  
          ```python
          app.contact = {
              'name': 'API Support',
              'url': 'http://www.example.com/support',
              'email': 'support@example.com'
          }
          ```
  
          This attribute can also be configured from the config with the
          `CONTACT` configuration key. Defaults to `None`.
      license: The license of the API (openapi.info.license). Example:
  
          ```python
          app.license = {
              'name': 'Apache 2.0',
              'url': 'http://www.apache.org/licenses/LICENSE-2.0.html'
          }
          ```
  
          This attribute can also be configured from the config with the
          `LICENSE` configuration key. Defaults to `None`.
      terms_of_service: The terms of service URL of the API
          (openapi.info.termsOfService). Example:
  
          ```python
          app.terms_of_service = 'http://example.com/terms/'
          ```
  
          This attribute can also be configured from the config with the
          `TERMS_OF_SERVICE` configuration key. Defaults to `None`.
      security_schemes: The security schemes of the API
          (openapi.components.securitySchemes). Example:
  
          ```python
          app.security_schemes = [
              'ApiKeyAuth': {
                  'type': 'apiKey',
                  'in': 'header',
                  'name': 'X-API-Key'
              }
          ]
          ```
  
          This attribute can also be configured from the config with the
          `SECURITY_SCHEMES` configuration key. Defaults to `None`.
      spec_callback: It stores the function object registered by
          [`spec_processor`][apiflask.APIFlask.spec_processor]. You can also
          pass a callback function to it directly without using `spec_processor`.
          Example:
  
          ```python
          def update_spec(spec):
              spec['title'] = 'Updated Title'
              return spec
  
          app.spec_callback = update_spec
          ```
  
      error_callback: It stores the function object registered by
          [`error_processor`][apiflask.APIFlask.error_processor]. You can also
          pass a callback function to it directly without using `error_processor`.
          See the docstring of `error_processor` for more details.
          Example:
  
          ```python
          def my_error_handler(error):
              return {
                  'status_code': error.status_code,
                  'message': error.message,
                  'detail': error.detail
              }, error.status_code, error.headers
  
          app.error_processor = my_error_handler
          ```
  
      schema_name_resolver: It stores the function that used to decided the schema name.
          The schema name resolver should accept the schema object as argument and return
          the name.
          Example:
  
          ```python
          # this is the default schema name resolver used in APIFlask
          def schema_name_resolver(schema):
              name = schema.__class__.__name__  # get schema class name
              if name.endswith('Schema'):  # remove the "Schema" suffix
                  name = name[:-6] or name
              if schema.partial:  # add a "Update" suffix for partial schema
                  name += 'Update'
              return name
  
          app.schema_name_resolver = schema_name_resolver
          ```
  
  *Version changed: 1.0*
  
  - Add instance attribute `security_schemes` as an alias of config `SECURITY_SCHEMES`.
  
  *Version changed: 0.9.0*
  
  - Add instance attribute `schema_name_resolver`.
class_docstr_tok: ["The","`","Flask","`","object","with","some","web","API","support",".","Examples",":","``","`","python","from","apiflask","import","APIFlask","app","=","APIFlask","(","__name__",")","``","`","Attributes",":","openapi_version",":","The","version","of","OpenAPI","Specification","(","openapi.openapi",")",".","This","attribute","can","also","be","configured","from","the","config","with","the","`","OPENAPI_VERSION","`","configuration","key",".","Defaults","to","`","'","3.0.3","'","`",".","servers",":","The","servers","information","of","the","API","(","openapi.servers",")",",","accepts","multiple","server","dicts",".","Example","value",":","``","`","python","app.servers","=","[","{","'name","'",":","'Production","Server","'",",","'url","'",":","'http",":","\/\/api.example.com'","}","]","``","`","This","attribute","can","also","be","configured","from","the","config","with","the","`","SERVERS","`","configuration","key",".","Defaults","to","`","None","`",".","tags",":","The","list","of","tags","of","the","OpenAPI","spec","documentation","(","openapi.tags",")",",","accepts","a","list","of","dicts",".","You","can","also","pass","a","simple","list","contains","the","tag","name",":","``","`","python","app.tags","=","[","'foo","'",",","'bar","'",",","'baz","'","]","``","`","A","standard","OpenAPI","tags","list","will","look","like","this",":","``","`","python","app.tags","=","[","{","'name","'",":","'foo","'",",","'description","'",":","'The","description","of","foo","'","}",",","{","'name","'",":","'bar","'",",","'description","'",":","'The","description","of","bar","'","}",",","{","'name","'",":","'baz","'",",","'description","'",":","'The","description","of","baz","'","}","]","``","`","If","not","set",",","the","blueprint","names","will","be","used","as","tags",".","This","attribute","can","also","be","configured","from","the","config","with","the","`","TAGS","`","configuration","key",".","Defaults","to","`","None","`",".","external_docs",":","The","external","documentation","information","of","the","API","(","openapi.externalDocs",")",".","Example",":","``","`","python","app.external_docs","=","{","'description","'",":","'Find","more","info","here","'",",","'url","'",":","'http",":","\/\/docs.example.com'","}","``","`","This","attribute","can","also","be","configured","from","the","config","with","the","`","EXTERNAL_DOCS","`","configuration","key",".","Defaults","to","`","None","`",".","info",":","The","info","object","(","openapi.info",")",",","it","accepts","a","dict","contains","following","info","fields",":","`","description","`",",","`","termsOfService","`",",","`","contact","`",",","`","license","`",".","You","can","use","separate","configuration","variables","to","overwrite","this","dict",".","Example",":","``","`","python","app.info","=","{","'description","'",":","'","...","'",",","'termsOfService","'",":","'http",":","\/\/example.com","'",",","'contact","'",":","{","'name","'",":","'API","Support","'",",","'url","'",":","'http",":","\/\/www.example.com\/support","'",",","'email","'",":","'support","@","example.com'","}",",","'license","'",":","{","'name","'",":","'Apache","2.0","'",",","'url","'",":","'http",":","\/\/www.apache.org\/licenses\/LICENSE-2.0.html'","}","}","``","`","description",":","The","description","of","the","API","(","openapi.info.description",")",".","This","attribute","can","also","be","configured","from","the","config","with","the","`","DESCRIPTION","`","configuration","key",".","Defaults","to","`","None","`",".","contact",":","The","contact","information","of","the","API","(","openapi.info.contact",")",".","Example",":","``","`","python","app.contact","=","{","'name","'",":","'API","Support","'",",","'url","'",":","'http",":","\/\/www.example.com\/support","'",",","'email","'",":","'support","@","example.com'","}","``","`","This","attribute","can","also","be","configured","from","the","config","with","the","`","CONTACT","`","configuration","key",".","Defaults","to","`","None","`",".","license",":","The","license","of","the","API","(","openapi.info.license",")",".","Example",":","``","`","python","app.license","=","{","'name","'",":","'Apache","2.0","'",",","'url","'",":","'http",":","\/\/www.apache.org\/licenses\/LICENSE-2.0.html'","}","``","`","This","attribute","can","also","be","configured","from","the","config","with","the","`","LICENSE","`","configuration","key",".","Defaults","to","`","None","`",".","terms_of_service",":","The","terms","of","service","URL","of","the","API","(","openapi.info.termsOfService",")",".","Example",":","``","`","python","app.terms_of_service","=","'http",":","\/\/example.com\/terms\/'","``","`","This","attribute","can","also","be","configured","from","the","config","with","the","`","TERMS_OF_SERVICE","`","configuration","key",".","Defaults","to","`","None","`",".","security_schemes",":","The","security","schemes","of","the","API","(","openapi.components.securitySchemes",")",".","Example",":","``","`","python","app.security_schemes","=","[","'ApiKeyAuth","'",":","{","'type","'",":","'apiKey","'",",","'in","'",":","'header","'",",","'name","'",":","'","X-API-Key'","}","]","``","`","This","attribute","can","also","be","configured","from","the","config","with","the","`","SECURITY_SCHEMES","`","configuration","key",".","Defaults","to","`","None","`",".","spec_callback",":","It","stores","the","function","object","registered","by","[","`","spec_processor","`","]","[","apiflask.APIFlask.spec_processor","]",".","You","can","also","pass","a","callback","function","to","it","directly","without","using","`","spec_processor","`",".","Example",":","``","`","python","def","update_spec","(","spec",")",":","spec","[","'title","'","]","=","'Updated","Title'","return","spec","app.spec_callback","=","update_spec","``","`","error_callback",":","It","stores","the","function","object","registered","by","[","`","error_processor","`","]","[","apiflask.APIFlask.error_processor","]",".","You","can","also","pass","a","callback","function","to","it","directly","without","using","`","error_processor","`",".","See","the","docstring","of","`","error_processor","`","for","more","details",".","Example",":","``","`","python","def","my_error_handler","(","error",")",":","return","{","'status_code","'",":","error.status_code",",","'message","'",":","error.message",",","'detail","'",":","error.detail","}",",","error.status_code",",","error.headers","app.error_processor","=","my_error_handler","``","`","schema_name_resolver",":","It","stores","the","function","that","used","to","decided","the","schema","name",".","The","schema","name","resolver","should","accept","the","schema","object","as","argument","and","return","the","name",".","Example",":","``","`","python","#","this","is","the","default","schema","name","resolver","used","in","APIFlask","def","schema_name_resolver","(","schema",")",":","name","=","schema.__class__.__name__","#","get","schema","class","name","if","name.endswith","(","'Schema","'",")",":","#","remove","the","``","Schema","''","suffix","name","=","name","[",":","-6","]","or","name","if","schema.partial",":","#","add","a","``","Update","''","suffix","for","partial","schema","name","+=","'Update'","return","name","app.schema_name_resolver","=","schema_name_resolver","``","`","*","Version","changed",":","1.0","*","-","Add","instance","attribute","`","security_schemes","`","as","an","alias","of","config","`","SECURITY_SCHEMES","`",".","*","Version","changed",":","0.9.0","*","-","Add","instance","attribute","`","schema_name_resolver","`","."]
docstr: Generate the spec, return an instance of `apispec.APISpec`.
  
  *Version changed: 1.3.0*
  
  - Support setting custom response content type.
  
  *Version changed: 1.2.1*
  
  - Set default `servers` value.
  
  *Version changed: 0.10.0*
  
  - Add support for `operationId`.
  - Add support for response `links`.
  
  *Version changed: 0.9.0*
  
  - Add base response customization support.
  
  *Version changed: 0.8.0*
  
  - Add automatic 404 response support.
docstr_tok: ["Generate","the","spec",",","return","an","instance","of","`","apispec.APISpec","`",".","*","Version","changed",":","1.3.0","*","-","Support","setting","custom","response","content","type",".","*","Version","changed",":","1.2.1","*","-","Set","default","`","servers","`","value",".","*","Version","changed",":","0.10.0","*","-","Add","support","for","`","operationId","`",".","-","Add","support","for","response","`","links","`",".","*","Version","changed",":","0.9.0","*","-","Add","base","response","customization","support",".","*","Version","changed",":","0.8.0","*","-","Add","automatic","404","response","support","."]
code: def _generate_spec(self) -> APISpec:
      """Generate the spec, return an instance of `apispec.APISpec`.
  
      *Version changed: 1.3.0*
  
      - Support setting custom response content type.
  
      *Version changed: 1.2.1*
  
      - Set default `servers` value.
  
      *Version changed: 0.10.0*
  
      - Add support for `operationId`.
      - Add support for response `links`.
  
      *Version changed: 0.9.0*
  
      - Add base response customization support.
  
      *Version changed: 0.8.0*
  
      - Add automatic 404 response support.
      """
      kwargs: dict = {}
      if self.servers:
          kwargs["servers"] = self.servers
      else:
          if self.config["AUTO_SERVERS"] and has_request_context():
              kwargs["servers"] = [{"url": request.url_root}]
      if self.external_docs:
          kwargs["externalDocs"] = self.external_docs
  
      self._ma_plugin: MarshmallowPlugin = MarshmallowPlugin(
          schema_name_resolver=self.schema_name_resolver  # type: ignore
      )
  
      spec_plugins: t.List[BasePlugin] = [
          self._ma_plugin,
          *self.spec_plugins,
      ]
  
      spec: APISpec = APISpec(
          title=self.title,
          version=self.version,
          openapi_version=self.config["OPENAPI_VERSION"],
          plugins=spec_plugins,
          info=self._make_info(),
          tags=self._make_tags(),
          **kwargs,
      )
  
      # configure flask-marshmallow URL types
      self._ma_plugin.converter.field_mapping[fields.URLFor] = ("string", "url")  # type: ignore
      self._ma_plugin.converter.field_mapping[fields.AbsoluteURLFor] = (  # type: ignore
          "string",
          "url",
      )
      if sqla is not None:  # pragma: no cover
          self._ma_plugin.converter.field_mapping[sqla.HyperlinkRelated] = (  # type: ignore
              "string",
              "url",
          )
  
      auth_names, auth_schemes = self._collect_security_info()
      security, security_schemes = get_security_and_security_schemes(
          auth_names, auth_schemes
      )
  
      if self.config["SECURITY_SCHEMES"] is not None:
          security_schemes.update(self.config["SECURITY_SCHEMES"])
  
      for name, scheme in security_schemes.items():
          spec.components.security_scheme(name, scheme)
  
      # paths
      paths: t.Dict[str, t.Dict[str, t.Any]] = {}
      rules: t.List[t.Any] = sorted(
          list(self.url_map.iter_rules()),
          key=lambda rule: len(rule.rule),
      )
      for rule in rules:
          operations: t.Dict[str, t.Any] = {}
          view_func: ViewFuncType = self.view_functions[rule.endpoint]  # type: ignore
          # skip endpoints from openapi blueprint and the built-in static endpoint
          if rule.endpoint in default_bypassed_endpoints:
              continue
          blueprint_name: t.Optional[str] = None  # type: ignore
          if "." in rule.endpoint:
              blueprint_name: str = rule.endpoint.rsplit(".", 1)[0]  # type: ignore
              blueprint = self.blueprints.get(blueprint_name)  # type: ignore
              if blueprint is None:
                  # just a normal view with dots in its endpoint, reset blueprint_name
                  blueprint_name = None
              else:
                  if (
                      rule.endpoint == (f"{blueprint_name}.static")
                      or not hasattr(blueprint, "enable_openapi")
                      or not blueprint.enable_openapi
                  ):  # type: ignore
                      continue
          # add a default 200 response for bare views
          if not hasattr(view_func, "_spec"):
              if (
                  not inspect.ismethod(view_func)
                  and self.config["AUTO_200_RESPONSE"]
              ):
                  view_func._spec = {"response": default_response}
              else:
                  continue  # pragma: no cover
          # method views
          if hasattr(view_func, "_method_spec"):
              skip = True
              for method, method_spec in view_func._method_spec.items():
                  if method_spec.get("no_spec"):
                      if self.config["AUTO_200_RESPONSE"]:
                          view_func._method_spec[method][
                              "response"
                          ] = default_response
                          skip = False
                  else:
                      skip = False
              if skip:
                  continue
          # skip views flagged with @app.doc(hide=True)
          if view_func._spec.get("hide"):
              continue
  
          # operation tags
          operation_tags: t.Optional[t.List[str]] = None
          if view_func._spec.get("tags"):
              operation_tags = view_func._spec.get("tags")
          else:
              # use blueprint name as tag
              if (
                  self.tags is None
                  and self.config["AUTO_TAGS"]
                  and blueprint_name is not None
              ):
                  blueprint = self.blueprints[blueprint_name]
                  operation_tags = get_operation_tags(
                      blueprint, blueprint_name
                  )  # type: ignore
  
          for method in ["GET", "POST", "PUT", "PATCH", "DELETE"]:
              if method not in rule.methods:
                  continue
              # method views
              if hasattr(view_func, "_method_spec"):
                  if method not in view_func._method_spec:
                      continue  # pragma: no cover
                  view_func._spec = view_func._method_spec[method]
  
                  if (
                      view_func._spec.get("no_spec")
                      and not self.config["AUTO_200_RESPONSE"]
                  ):
                      continue
                  if (
                      view_func._spec.get("generated_summary")
                      and not self.config["AUTO_OPERATION_SUMMARY"]
                  ):
                      view_func._spec["summary"] = ""
                  if (
                      view_func._spec.get("generated_description")
                      and not self.config["AUTO_OPERATION_DESCRIPTION"]
                  ):
                      view_func._spec["description"] = ""
                  if view_func._spec.get("hide"):
                      continue
                  if view_func._spec.get("tags"):
                      operation_tags = view_func._spec.get("tags")
                  else:
                      if (
                          self.tags is None
                          and self.config["AUTO_TAGS"]
                          and blueprint_name is not None
                      ):
                          blueprint = self.blueprints[blueprint_name]
                          operation_tags = get_operation_tags(
                              blueprint, blueprint_name
                          )  # type: ignore
  
              operation: t.Dict[str, t.Any] = {
                  "parameters": [
                      {"in": location, "schema": schema}
                      for schema, location in view_func._spec.get(
                          "args", []
                      )
                  ],
                  "responses": {},
              }
              if operation_tags:
                  operation["tags"] = operation_tags
  
              # summary
              if view_func._spec.get("summary"):
                  operation["summary"] = view_func._spec.get("summary")
              else:
                  # auto-generate summary from dotstring or view function name
                  if self.config["AUTO_OPERATION_SUMMARY"]:
                      operation["summary"] = get_path_summary(view_func)  # type: ignore
  
              # description
              if view_func._spec.get("description"):
                  operation["description"] = view_func._spec.get(
                      "description"
                  )
              else:
                  # auto-generate description from dotstring
                  if self.config["AUTO_OPERATION_DESCRIPTION"]:
                      docs = [
                          line.strip()
                          for line in (view_func.__doc__ or "")
                          .strip()
                          .split("\n")
                      ]
                      if len(docs) > 1:
                          # use the remain lines of docstring as description
                          operation["description"] = "\n".join(
                              docs[1:]
                          ).strip()
  
              # deprecated
              if view_func._spec.get("deprecated"):
                  operation["deprecated"] = view_func._spec.get(
                      "deprecated"
                  )
  
              # operationId
              operation_id = view_func._spec.get("operation_id")
              if operation_id is None:
                  if self.config["AUTO_OPERATION_ID"]:
                      operation[
                          "operationId"
                      ] = f"{method.lower()}_{rule.endpoint.replace('.', '_')}"
              else:
                  operation["operationId"] = operation_id
  
              # responses
              if view_func._spec.get("response"):
                  schema = view_func._spec.get("response")["schema"]
                  status_code: str = str(
                      view_func._spec.get("response")["status_code"]
                  )
                  description: str = (
                      view_func._spec.get("response")["description"]
                      or self.config["SUCCESS_DESCRIPTION"]
                  )
                  example = view_func._spec.get("response")["example"]
                  examples = view_func._spec.get("response")["examples"]
                  links = view_func._spec.get("response")["links"]
                  content_type = view_func._spec.get("response")[
                      "content_type"
                  ]
                  headers = view_func._spec.get("response")["headers"]
                  self._add_response(
                      operation,
                      status_code,
                      schema,
                      description,
                      example=example,
                      examples=examples,
                      links=links,
                      content_type=content_type,
                      headers_schema=headers,
                  )
              else:
                  # add a default 200 response for views without using @app.output
                  # or @app.doc(responses={...})
                  if (
                      not view_func._spec.get("responses")
                      and self.config["AUTO_200_RESPONSE"]
                  ):
                      self._add_response(
                          operation,
                          "200",
                          {},
                          self.config["SUCCESS_DESCRIPTION"],
                      )
  
              # add validation error response
              if self.config["AUTO_VALIDATION_ERROR_RESPONSE"] and (
                  view_func._spec.get("body")
                  or view_func._spec.get("args")
              ):
                  status_code: str = str(  # type: ignore
                      self.config["VALIDATION_ERROR_STATUS_CODE"]
                  )
                  description: str = self.config[  # type: ignore
                      "VALIDATION_ERROR_DESCRIPTION"
                  ]
                  schema: SchemaType = self.config["VALIDATION_ERROR_SCHEMA"]  # type: ignore
                  self._add_response_with_schema(
                      spec,
                      operation,
                      status_code,
                      schema,
                      "ValidationError",
                      description,
                  )
  
              # add authentication error response
              has_bp_level_auth = (
                  blueprint_name is not None
                  and blueprint_name in self._auth_blueprints
              )
              view_func_auth = view_func._spec.get("auth")
              custom_security = view_func._spec.get("security")
              if self.config["AUTO_AUTH_ERROR_RESPONSE"] and (
                  has_bp_level_auth or view_func_auth or custom_security
              ):
                  status_code: str = str(  # type: ignore
                      self.config["AUTH_ERROR_STATUS_CODE"]
                  )
                  description: str = self.config["AUTH_ERROR_DESCRIPTION"]  # type: ignore
                  schema: SchemaType = self.config["HTTP_ERROR_SCHEMA"]  # type: ignore
                  self._add_response_with_schema(
                      spec,
                      operation,
                      status_code,
                      schema,
                      "HTTPError",
                      description,
                  )
  
              # add 404 error response
              if self.config["AUTO_404_RESPONSE"] and rule.arguments:
                  description: str = self.config["NOT_FOUND_DESCRIPTION"]  # type: ignore
                  schema: SchemaType = self.config["HTTP_ERROR_SCHEMA"]  # type: ignore
                  self._add_response_with_schema(
                      spec,
                      operation,
                      "404",
                      schema,
                      "HTTPError",
                      description,
                  )
  
              if view_func._spec.get("responses"):
                  responses: ResponsesType = view_func._spec.get(
                      "responses"
                  )
                  # turn status_code list to dict {status_code: reason_phrase}
                  if isinstance(responses, list):
                      responses: t.Dict[int, str] = {}  # type: ignore
                      for status_code in view_func._spec.get(
                          "responses"
                      ):
                          responses[  # type: ignore
                              status_code
                          ] = get_reason_phrase(int(status_code), "")
                  for status_code, value in responses.items():  # type: ignore
                      status_code: str = str(status_code)  # type: ignore
                      # custom complete response spec
                      if isinstance(value, dict):
                          existing_response = operation[
                              "responses"
                          ].setdefault(status_code, {})
                          existing_response_content = (
                              existing_response.setdefault(
                                  "content", {}
                              )
                          )
                          existing_response_content.update(
                              value.get("content", {})
                          )
                          if (
                              new_description := value.get(
                                  "description"
                              )
                          ) is not None:
                              existing_response[
                                  "description"
                              ] = new_description
                          continue
                      else:
                          description = value
                      # overwrite existing response description
                      if status_code in operation["responses"]:
                          if not isinstance(
                              view_func._spec.get("responses"), list
                          ):  # pragma: no cover
                              operation["responses"][status_code][
                                  "description"
                              ] = description
                          continue
                      # add error response schema for error responses
                      if status_code.startswith(
                          "4"
                      ) or status_code.startswith("5"):
                          schema: SchemaType = self.config["HTTP_ERROR_SCHEMA"]  # type: ignore
                          self._add_response_with_schema(
                              spec,
                              operation,
                              status_code,
                              schema,
                              "HTTPError",
                              description,
                          )
                      else:  # add default response for other responses
                          self._add_response(
                              operation, status_code, {}, description
                          )
  
              # requestBody
              if view_func._spec.get("body"):
                  content_type = view_func._spec.get(
                      "content_type", "application/json"
                  )
                  operation["requestBody"] = {
                      "content": {
                          content_type: {
                              "schema": view_func._spec["body"],
                          }
                      }
                  }
                  if view_func._spec.get("body_example"):
                      example = view_func._spec.get("body_example")
                      operation["requestBody"]["content"][content_type][
                          "example"
                      ] = example
                  if view_func._spec.get("body_examples"):
                      examples = view_func._spec.get("body_examples")
                      operation["requestBody"]["content"][content_type][
                          "examples"
                      ] = examples
  
              # security
              if custom_security:  # custom security
                  # TODO: validate the security name and the format
                  operation["security"] = []
                  operation_security = custom_security
                  if isinstance(
                      operation_security, str
                  ):  # 'A' -> [{'A': []}]
                      operation["security"] = [{operation_security: []}]
                  elif isinstance(operation_security, list):
                      # ['A', 'B'] -> [{'A': []}, {'B': []}]
                      if isinstance(operation_security[0], str):
                          operation["security"] = [
                              {name: []} for name in operation_security
                          ]
                      else:
                          operation["security"] = operation_security
                  else:
                      raise ValueError(
                          "The operation security must be a string or a list."
                      )
              else:
                  if has_bp_level_auth:
                      bp_auth_info = self._auth_blueprints[blueprint_name]  # type: ignore
                      operation["security"] = [
                          {
                              security[
                                  bp_auth_info["auth"]
                              ]: bp_auth_info["roles"]
                          }
                      ]
  
                  # view-wide auth
                  if view_func_auth:
                      operation["security"] = [
                          {
                              security[view_func_auth]: view_func._spec[
                                  "roles"
                              ]
                          }
                      ]
  
              operations[method.lower()] = operation
  
          # parameters
          path_arguments: t.Iterable = re.findall(
              r"<(([^<:]+:)?([^>]+))>", rule.rule
          )
          if path_arguments and not (
              hasattr(view_func, "_spec")
              and view_func._spec.get(
                  "omit_default_path_parameters", False
              )
          ):
              arguments: t.List[t.Dict[str, str]] = []
              for _, argument_type, argument_name in path_arguments:
                  argument = get_argument(argument_type, argument_name)
                  arguments.append(argument)
  
              for _method, operation in operations.items():
                  operation["parameters"] = (
                      arguments + operation["parameters"]
                  )
  
          path: str = re.sub(r"<([^<:]+:)?", "{", rule.rule).replace(
              ">", "}"
          )
          if path not in paths:
              paths[path] = operations
          else:
              paths[path].update(operations)
  
      for path, operations in paths.items():
          # sort by method before adding them to the spec
          sorted_operations: t.Dict[str, t.Any] = {}
          for method in ["get", "post", "put", "patch", "delete"]:
              if method in operations:
                  sorted_operations[method] = operations[method]
          spec.path(path=path, operations=sorted_operations)
  
      return spec
  
imports: import inspect
  import json
  import re
  import typing
  import warnings
  from functools import wraps
  from apispec import APISpec
  from apispec import BasePlugin
  from apispec.ext.marshmallow import MarshmallowPlugin
  from flask import Blueprint
  from flask import Flask
  from flask import has_request_context
  from flask import jsonify
  from flask import render_template_string
  from flask import request
  from flask.config import ConfigAttribute
  from flask.wrappers import Response
  from werkzeug.exceptions import HTTPException
  from .exceptions import HTTPError
  from .exceptions import _bad_schema_message
  from .helpers import get_reason_phrase
  from .route import route_patch
  from .schemas import Schema
  from .schemas import FileSchema
  from .schemas import EmptySchema
  from .types import ResponseReturnValueType, ResponsesType
  from .types import ViewFuncType
  from .types import ErrorCallbackType
  from .types import SpecCallbackType
  from .types import SchemaType
  from .types import HTTPAuthType
  from .types import TagsType
  from .types import OpenAPISchemaType
  from .openapi import default_bypassed_endpoints
  from .openapi import default_response
  from .openapi import get_tag
  from .openapi import get_operation_tags
  from .openapi import get_path_summary
  from .openapi import get_auth_name
  from .openapi import get_argument
  from .openapi import get_security_and_security_schemes
  from .ui_templates import ui_templates
  from .ui_templates import swagger_ui_oauth2_redirect_template
  from .scaffold import APIScaffold
label_desc: Use image node_id 15 for calling the APIFlask obj's underlying member method code with example usage: obj._generate_spec() and returns: spec