def run_safe_validations(handler):
    """This function runs all the validations that can safely be done without running
    user code. It returns the common parent directory of the archive.
    """
    logger.info(">> Running safe validations")
    # check archive format
    namelist = handler.get_namelist()
    common_dir = validate_archive_files(namelist)
    logger.debug("Common directory is %s" % common_dir)
    
    # check for and then read configuration file
    config_file = common_dir + os.sep + DJANGO_CFG_FILENAME
    if not handler.is_file_in_archive(config_file):
        raise FileMissingError("Archive missing configuration file %s" %
                               config_file)
    fileobj = handler.open_member(config_file)
    data = fileobj.read()
    django_config = django_config_from_json(data, COMPATIBLE_PACKAGER_VERSION)

    # check for additional_components file and parse if present
    components_file = common_dir + os.sep + COMPONENTS_FILENAME
    if handler.is_file_in_archive(components_file):
        fileobj = handler.open_member(components_file)
        read_components_file(fileobj, components_file, django_config.components)
    else:
        if len(django_config.components)>0:
            raise ValidationError("No additional component file at %s, but application with packaged with an additional component file" %
                                  filepath)

    # check for other required files
    settings_module_file = django_config.get_settings_module_file()
    if not handler.is_file_in_archive(settings_module_file):
        raise FileMissingError("Archive missing django settings file %s" % settings_module_file)
    logger.debug("Has required files")
    return (common_dir, django_config)
def simulated_install(archive_file_or_directory,
                      install_path,
                      django_settings_module,
                      package_cache_dir=None):
    """Simulate the install process. install_path is the directory under
    which we extract the archive. We also create a python virtualenv there
    and install all the required dependencies.
    """
    if not os.path.isdir(install_path):
        raise Exception(
            "simulated_install: install_path %s does not exist" % install_path)
    if os.path.isdir(archive_file_or_directory):
        app_dir_path = os.path.join(
            install_path, os.path.basename(archive_file_or_directory))
        shutil.copytree(archive_file_or_directory, app_dir_path)
    else:  # we have an archive
        with create_handler(archive_file_or_directory) as h:
            common_dir = validate_archive_files(h.get_namelist())
            h.extract(install_path)
        app_dir_path = os.path.join(install_path, common_dir)
    components_file = os.path.join(app_dir_path, COMPONENTS_FILENAME)
    if os.path.exists(components_file):
        with open(components_file, "rb") as cf:
            components_list = read_components_file(cf, components_file, None)
    else:
        components_list = []
    undo_ops = generate_settings_file(app_dir_path, django_settings_module,
                                      components_list)
    virtualenv_path = os.path.join(install_path, "python")
    create_virtualenv(virtualenv_path, package_cache_dir=package_cache_dir)
    platform_reqs = write_platform_requirements_file(install_path,
                                                     components_list)
    logger.info(">> Installing platform requirements into virtualenv")
    install_requirements(
        virtualenv_path, platform_reqs, package_cache_dir=package_cache_dir)
    app_reqs = os.path.join(app_dir_path, "requirements.txt")
    if os.path.exists(app_reqs):
        logger.info(">> Installing application requirements into virtualenv")
        install_requirements(
            virtualenv_path, app_reqs, package_cache_dir=package_cache_dir)
    else:
        logger.debug("No install requirements file at %s" % app_reqs)
    return (app_dir_path, undo_ops, os.path.join(virtualenv_path,
                                                 "bin/python"))