class_docstr: TabPy application class for keeping context like settings, state, etc.
docstr: Provide consistent mechanism for pulling in configuration.
  
  Attempt to retain backward compatibility for
  existing implementations by grabbing port
  setting from CLI first.
  
  Take settings in the following order:
  
  1. CLI arguments if present
  2. config file
  3. OS environment variables (for ease of
     setting defaults if not present)
  4. current defaults if a setting is not present in any location
  
  Additionally provide similar configuration capabilities in between
  config file and environment variables.
  For consistency use the same variable name in the config file as
  in the os environment.
  For naming standards use all capitals and start with 'TABPY_'
code: def _parse_config(self, config_file):
      """Provide consistent mechanism for pulling in configuration.
  
      Attempt to retain backward compatibility for
      existing implementations by grabbing port
      setting from CLI first.
  
      Take settings in the following order:
  
      1. CLI arguments if present
      2. config file
      3. OS environment variables (for ease of
         setting defaults if not present)
      4. current defaults if a setting is not present in any location
  
      Additionally provide similar configuration capabilities in between
      config file and environment variables.
      For consistency use the same variable name in the config file as
      in the os environment.
      For naming standards use all capitals and start with 'TABPY_'
      """
      self.settings = {}
      self.subdirectory = ""
      self.tabpy_state = None
      self.python_service = None
      self.credentials = {}
  
      pkg_path = os.path.dirname(tabpy.__file__)
  
      parser = configparser.ConfigParser(os.environ)
      logger.info(f"Parsing config file {config_file}")
  
      file_exists = False
      if os.path.isfile(config_file):
          try:
              with open(config_file, "r") as f:
                  parser.read_string(f.read())
                  file_exists = True
          except Exception:
              pass
  
      if not file_exists:
          logger.warning(
              f"Unable to open config file {config_file}, "
              "using default settings."
          )
  
      settings_parameters = [
          (
              SettingsParameters.Port,
              ConfigParameters.TABPY_PORT,
              9004,
              None,
          ),
          (SettingsParameters.ServerVersion, None, __version__, None),
          (
              SettingsParameters.EvaluateEnabled,
              ConfigParameters.TABPY_EVALUATE_ENABLE,
              True,
              parser.getboolean,
          ),
          (
              SettingsParameters.EvaluateTimeout,
              ConfigParameters.TABPY_EVALUATE_TIMEOUT,
              30,
              parser.getfloat,
          ),
          (
              SettingsParameters.UploadDir,
              ConfigParameters.TABPY_QUERY_OBJECT_PATH,
              os.path.join(pkg_path, "tmp", "query_objects"),
              None,
          ),
          (
              SettingsParameters.TransferProtocol,
              ConfigParameters.TABPY_TRANSFER_PROTOCOL,
              "http",
              None,
          ),
          (
              SettingsParameters.CertificateFile,
              ConfigParameters.TABPY_CERTIFICATE_FILE,
              None,
              None,
          ),
          (
              SettingsParameters.KeyFile,
              ConfigParameters.TABPY_KEY_FILE,
              None,
              None,
          ),
          (
              SettingsParameters.StateFilePath,
              ConfigParameters.TABPY_STATE_PATH,
              os.path.join(pkg_path, "tabpy_server"),
              None,
          ),
          (
              SettingsParameters.StaticPath,
              ConfigParameters.TABPY_STATIC_PATH,
              os.path.join(pkg_path, "tabpy_server", "static"),
              None,
          ),
          (
              ConfigParameters.TABPY_PWD_FILE,
              ConfigParameters.TABPY_PWD_FILE,
              None,
              None,
          ),
          (
              SettingsParameters.LogRequestContext,
              ConfigParameters.TABPY_LOG_DETAILS,
              "false",
              None,
          ),
          (
              SettingsParameters.MaxRequestSizeInMb,
              ConfigParameters.TABPY_MAX_REQUEST_SIZE_MB,
              100,
              None,
          ),
          (
              SettingsParameters.GzipEnabled,
              ConfigParameters.TABPY_GZIP_ENABLE,
              True,
              parser.getboolean,
          ),
          (
              SettingsParameters.ArrowEnabled,
              ConfigParameters.TABPY_ARROW_ENABLE,
              False,
              parser.getboolean,
          ),
          (
              SettingsParameters.ArrowFlightPort,
              ConfigParameters.TABPY_ARROWFLIGHT_PORT,
              13622,
              parser.getint,
          ),
      ]
  
      for (
          setting,
          parameter,
          default_val,
          parse_function,
      ) in settings_parameters:
          self._set_parameter(
              parser, setting, parameter, default_val, parse_function
          )
  
      if not os.path.exists(
          self.settings[SettingsParameters.UploadDir]
      ):
          os.makedirs(self.settings[SettingsParameters.UploadDir])
  
      # set and validate transfer protocol
      self.settings[
          SettingsParameters.TransferProtocol
      ] = self.settings[SettingsParameters.TransferProtocol].lower()
  
      self._validate_transfer_protocol_settings()
  
      # Set max request size in bytes
      self.max_request_size = (
          int(self.settings[SettingsParameters.MaxRequestSizeInMb])
          * 1024
          * 1024
      )
      logger.info(
          f"Setting max request size to {self.max_request_size} bytes"
      )
  
      # if state.ini does not exist try and create it - remove
      # last dependence on batch/shell script
      self.settings[
          SettingsParameters.StateFilePath
      ] = os.path.realpath(
          os.path.normpath(
              os.path.expanduser(
                  self.settings[SettingsParameters.StateFilePath]
              )
          )
      )
      state_config, self.tabpy_state = self._build_tabpy_state()
  
      self.python_service = PythonServiceHandler(PythonService())
      self.settings["compress_response"] = True
      self.settings[SettingsParameters.StaticPath] = os.path.abspath(
          self.settings[SettingsParameters.StaticPath]
      )
      logger.debug(
          f"Static pages folder set to "
          f'"{self.settings[SettingsParameters.StaticPath]}"'
      )
  
      # Set subdirectory from config if applicable
      if state_config.has_option("Service Info", "Subdirectory"):
          self.subdirectory = "/" + state_config.get(
              "Service Info", "Subdirectory"
          )
  
      # If passwords file specified load credentials
      if ConfigParameters.TABPY_PWD_FILE in self.settings:
          if not self._parse_pwd_file():
              msg = (
                  "Failed to read passwords file "
                  f"{self.settings[ConfigParameters.TABPY_PWD_FILE]}"
              )
              logger.critical(msg)
              raise RuntimeError(msg)
      else:
          self._handle_configuration_without_authentication()
  
      features = self._get_features()
      self.settings[SettingsParameters.ApiVersions] = {
          "v1": {"features": features}
      }
  
      self.settings[SettingsParameters.LogRequestContext] = (
          self.settings[SettingsParameters.LogRequestContext].lower()
          != "false"
      )
      call_context_state = (
          "enabled"
          if self.settings[SettingsParameters.LogRequestContext]
          else "disabled"
      )
      logger.info(f"Call context logging is {call_context_state}")
  
imports: import concurrent.futures
  import configparser
  import logging
  import multiprocessing
  import os
  import shutil
  import signal
  import sys
  import _thread
  import tornado
  from tornado.http1connection import HTTP1Connection
  import tabpy
  import tabpy.tabpy_server.app.arrow_server
  from tabpy.tabpy import __version__
  from tabpy.tabpy_server.app.app_parameters import ConfigParameters, SettingsParameters
  from tabpy.tabpy_server.app.util import parse_pwd_file
  from tabpy.tabpy_server.handlers.basic_auth_server_middleware_factory import BasicAuthServerMiddlewareFactory
  from tabpy.tabpy_server.handlers.no_op_auth_handler import NoOpAuthHandler
  from tabpy.tabpy_server.management.state import TabPyState
  from tabpy.tabpy_server.management.util import _get_state_from_file
  from tabpy.tabpy_server.psws.callbacks import init_model_evaluator, init_ps_server
  from tabpy.tabpy_server.psws.python_service import PythonService, PythonServiceHandler
  from tabpy.tabpy_server.handlers import EndpointHandler, EndpointsHandler, EvaluationPlaneHandler, EvaluationPlaneDisabledHandler, QueryPlaneHandler, ServiceInfoHandler, StatusHandler, UploadDestinationHandler
label_desc: Use image node_id 7 for calling the TabPyApp obj's underlying member method code with example usage: obj._parse_config(config_file) without return types