<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def from_raw_profile_info(cls, raw_profile, profile_name, cli_vars, user_cfg=None, target_override=None, threads_override=None):
 """Create a profile from its raw profile information. (this is an intermediate step, mostly useful for unit testing) :param raw_profile dict: The profile data for a single profile, from disk as yaml and its values rendered with jinja. :param profile_name str: The profile name used. :param cli_vars dict: The command-line variables passed as arguments, as a dict. :param user_cfg Optional[dict]: The global config for the user, if it was present. :param target_override Optional[str]: The target to use, if provided on the command line. :param threads_override Optional[str]: The thread count to use, if provided on the command line. :raises DbtProfileError: If the profile is invalid or missing, or the target could not be found :returns Profile: The new Profile object. """

        # user_cfg is not rendered since it only contains booleans.
        # TODO: should it be, and the values coerced to bool?
        target_name, profile_data = cls.render_profile(
            raw_profile, profile_name, target_override, cli_vars
        )

        # valid connections never include the number of threads, but it's
        # stored on a per-connection level in the raw configs
        threads = profile_data.pop('threads', DEFAULT_THREADS)
        if threads_override is not None:
            threads = threads_override

        credentials = cls._credentials_from_profile(
            profile_data, profile_name, target_name
        )

        return cls.from_credentials(
            credentials=credentials,
            profile_name=profile_name,
            target_name=target_name,
            threads=threads,
            user_cfg=user_cfg
        )