<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def _prepare_context(self, data_id, data_dir, runtime_dir, **kwargs):
 """Prepare settings and constants JSONs for the executor. Settings and constants provided by other ``resolwe`` modules and :class:`~django.conf.settings` are all inaccessible in the executor once it is deployed, so they need to be serialized into the runtime directory. :param data_id: The :class:`~resolwe.flow.models.Data` object id being prepared for. :param data_dir: The target execution directory for this :class:`~resolwe.flow.models.Data` object. :param runtime_dir: The target runtime support directory for this :class:`~resolwe.flow.models.Data` object; this is where the environment is serialized into. :param kwargs: Extra settings to include in the main settings file. """

        files = {}
        secrets = {}

        settings_dict = {}
        settings_dict['DATA_DIR'] = data_dir
        settings_dict['REDIS_CHANNEL_PAIR'] = state.MANAGER_EXECUTOR_CHANNELS
        files[ExecutorFiles.EXECUTOR_SETTINGS] = settings_dict

        django_settings = {}
        django_settings.update(self.settings_actual)
        django_settings.update(kwargs)
        files[ExecutorFiles.DJANGO_SETTINGS] = django_settings

        # Add scheduling classes.
        files[ExecutorFiles.PROCESS_META] = {
            k: getattr(Process, k) for k in dir(Process)
            if k.startswith('SCHEDULING_CLASS_') and isinstance(getattr(Process, k), str)
        }

        # Add Data status constants.
        files[ExecutorFiles.DATA_META] = {
            k: getattr(Data, k) for k in dir(Data)
            if k.startswith('STATUS_') and isinstance(getattr(Data, k), str)
        }

        # Extend the settings with whatever the executor wants.
        self.executor.extend_settings(data_id, files, secrets)

        # Save the settings into the various files in the runtime dir.
        settings_dict[ExecutorFiles.FILE_LIST_KEY] = list(files.keys())
        for file_name in files:
            file_path = os.path.join(runtime_dir, file_name)
            with open(file_path, 'wt') as json_file:
                json.dump(files[file_name], json_file, cls=SettingsJSONifier)

        # Save the secrets in the runtime dir, with permissions to prevent listing the given
        # directory.
        secrets_dir = os.path.join(runtime_dir, ExecutorFiles.SECRETS_DIR)
        os.makedirs(secrets_dir, mode=0o300)
        for file_name, value in secrets.items():
            file_path = os.path.join(secrets_dir, file_name)

            # Set umask to 0 to ensure that we set the correct permissions.
            old_umask = os.umask(0)
            try:
                # We need to use os.open in order to correctly enforce file creation. Otherwise,
                # there is a race condition which can be used to create the file with different
                # ownership/permissions.
                file_descriptor = os.open(file_path, os.O_WRONLY | os.O_CREAT, mode=0o600)
                with os.fdopen(file_descriptor, 'w') as raw_file:
                    raw_file.write(value)
            finally:
                os.umask(old_umask)