<commit_before>import json
import tarfile
import re
import os
import subprocess
from StringIO import StringIO
from time import sleep

import click
import requests

from ..utils import dev_null, execute, redirect_stdout
from ..cloud import get_aldryn_host
from .. import settings
from . import utils

DEFAULT_GIT_HOST = 'git@git.{aldryn_host}'
GIT_CLONE_URL = '{git_host}:{project_slug}.git'

def get_git_host():
    git_host = os.environ.get('ALDRYN_GIT_HOST')
    if git_host:
        click.secho('Using custom git host {}\n'.format(git_host), fg='yellow')
    else:
        git_host = DEFAULT_GIT_HOST.format(aldryn_host=get_aldryn_host())
    return git_host

def get_git_clone_url(slug):
    return GIT_CLONE_URL.format(git_host=get_git_host(), project_slug=slug)

def create_workspace(client, website_slug, path=None):
    click.secho('Creating workspace...', fg='green')

    path = os.path.abspath(
        os.path.join(path, website_slug)
        if path else website_slug
    )

    docker_compose = utils.get_docker_compose_cmd(path)
    website_id = client.get_website_id_for_slug(website_slug)
    website_git_url = get_git_clone_url(website_slug)

    try:
        click.secho('\ncloning project repository', fg='green')
        clone_args = ['git', 'clone', website_git_url]
        if path:
            clone_args.append(path)
        execute(clone_args, silent=False, stderr=subprocess.STDOUT)
    except subprocess.CalledProcessError as exc:
        raise click.ClickException(exc.output)

    # Detect old style or invalid projects
    compose_config = os.path.join(path or website_slug, 'docker-compose.yml')
    if not os.path.isfile(compose_config):
        raise click.ClickException(
            "Aldryn local development only works with projects using "
            "baseproject version 3 and have a valid 'docker-compose.yml' file."
        )

    # create .aldryn file
    website_data = {'id': website_id, 'slug': website_slug}
    with open(os.path.join(path, settings.ALDRYN_DOT_FILE), 'w+') as fh:
        json.dump(website_data, fh)

    existing_db_container_id = utils.get_db_container_id(path)

    # stop all running for project
    execute(docker_compose('stop'), silent=True)

    # pull docker images
    click.secho('downloading remote docker images', fg='green')
    execute(docker_compose('pull'), silent=False, stderr=subprocess.STDOUT)

    # build docker images
    click.secho('building local docker images', fg='green')
    execute(docker_compose('build'), silent=False, stderr=subprocess.STDOUT)

    if existing_db_container_id:
        click.secho('removing old database container', fg='green')
        execute(
            docker_compose('stop', 'db'),
            stderr=subprocess.STDOUT,
            silent=False,
        )
        execute(
            docker_compose('rm', '-f', 'db'),
            stderr=subprocess.STDOUT,
            silent=False,
        )

    click.secho('creating new database container', fg='green')
    load_database_dump(client, path, recreate=True)

    click.secho('sync and migrate database', fg='green')
    # FIXME: Running this command with silent=False raises:
    #   IOError: [Errno 35] Resource temporarily unavailable
    #   see http://trac.edgewall.org/ticket/2066
    execute(
        docker_compose('run', 'web', './migrate.sh'),
        stderr=subprocess.STDOUT,
        silent=True,  # silent=False raises
    )

    instructions = [
        "Finished setting up your project's workspace!",
        "To start the project, please:",
    ]

    if path:
        instructions.append(' - change directory into {}'.format(path))
    instructions.append(' - run aldryn project up')

    click.secho('\n\n{}'.format(os.linesep.join(instructions)), fg='green')

def load_database_dump(client, path=None, recreate=False):
    path = path or utils.get_project_home(path)
    website_slug = utils.get_aldryn_project_settings(path)['slug']
    docker_compose = utils.get_docker_compose_cmd(path)

    start_db_cmd = ['up', '-d']
    if recreate:
        start_db_cmd.append('--force-recreate')
    start_db_cmd.append('db')

    # start db
    execute(
        docker_compose(*start_db_cmd),
        stderr=subprocess.STDOUT,
        silent=True,
    )

    # get db container id
    db_container_id = utils.get_db_container_id(path)

    click.secho('fetching database dump', fg='green')
    db_dump_path = client.download_db(website_slug, directory=path)
    # strip path from dump_path for use in the docker container
    db_dump_path = db_dump_path.replace(path, '')

    # waiting another 10 seconds to make sure
    # the db has enough time to start
    sleep(10)

    # create empty db
    try:
        execute([
            'docker', 'exec', db_container_id,
            'dropdb', '-U', 'postgres', 'db',
        ], silent=True, stderr=subprocess.STDOUT)
    except subprocess.CalledProcessError:
        pass

    execute([
        'docker', 'exec', db_container_id,
        'createdb', '-U', 'postgres', 'db',
    ], silent=True, stderr=subprocess.STDOUT)

    click.secho('inserting database dump', fg='green')
    # FIXME: because of different ownership,
    # this spits a lot of warnings which can
    # ignored but we can't really validate success
    with dev_null() as devnull:
        try:
            piped_restore = (
                'tar -xzOf /app/{}'
                ' | pg_restore -U postgres -d db'
                .format(db_dump_path)
            )
            subprocess.call((
                'docker', 'exec', db_container_id,
                '/bin/bash', '-c', piped_restore,
            ), stdout=devnull, stderr=devnull)
        except subprocess.CalledProcessError:
            pass

    # stop db
    execute(
        docker_compose('stop'),
        silent=True,
        stderr=subprocess.STDOUT,
    )

def download_media(client, path=None):
    click.secho('fetching media files', fg='green')

    path = path or os.path.join(utils.get_project_home(path), 'data/media')
    website_slug = utils.get_aldryn_project_settings(path)['slug']
    backup_path = client.download_backup(website_slug)

    with tarfile.open(backup_path, 'r:gz') as backup_archive:
        media_archive_name = 'media_files.tar.gz'
        if media_archive_name not in backup_archive.getnames():
            click.secho('Media archive empty', fg='yellow')
            return

        media_fobj = backup_archive.extractfile(media_archive_name)
        with tarfile.open(fileobj=media_fobj, mode='r:gz') as media_archive:
            media_archive.extractall(path=path)

    os.remove(backup_path)
    click.secho('Downloaded media files into {}'.format(path), fg='green')

def upload_database(client):
    project_home = utils.get_project_home()
    website_id = utils.get_aldryn_project_settings(project_home)['id']
    dump_filename = 'local_db.sql'
    archive_filename = 'local_db.tar.gz'
    archive_path = os.path.join(project_home, archive_filename)

    # take dump of database
    click.secho('Dumping local database', fg='green')
    db_container_id = utils.get_db_container_id(project_home)

    subprocess.call((
        'docker', 'exec', db_container_id,
        'pg_dump', '-U', 'postgres', '-d', 'db',
        '-f', os.path.join('/app/', dump_filename)
    ))

    click.secho('Creating archive of SQL dump', fg='green')
    with tarfile.open(archive_path, mode='w:gz') as tar:
        tar.add(
            os.path.join(project_home, dump_filename),
            arcname=dump_filename
        )

    click.secho('Pushing database to Aldryn', fg='green')
    client.upload_db(website_id, archive_path)
    # clean up
    for temp_file in (dump_filename, archive_filename):
        os.remove(os.path.join(project_home, temp_file))
    click.secho('Done', fg='green')

def upload_media(client):
    project_home = utils.get_project_home()
    website_id = utils.get_aldryn_project_settings(project_home)['id']
    archive_path = os.path.join(project_home, 'local_media.tar.gz')

    click.secho('Creating archive of local media folder', fg='green')
    with tarfile.open(archive_path, mode='w:gz') as tar:
        media_dir = os.path.join(project_home, 'data', 'media')
        for item in os.listdir(media_dir):
            tar.add(os.path.join(media_dir, item), arcname=item)

    click.secho('Pushing archive to Aldryn', fg='green')
    client.upload_media_files(website_id, archive_path)

    # clean up
    os.remove(archive_path)
    click.secho('Done', fg='green')

def develop_package(package, no_rebuild=False):
    """
    :param package: package name in addons-dev folder
    """

    project_home = utils.get_project_home()
    addons_dev_dir = os.path.join(project_home, 'addons-dev')

    if not os.path.isdir(os.path.join(addons_dev_dir, package)):
        raise click.ClickException(
            'Package {} could not be found in {}. Please make '
            'sure it exists and try again.'
            .format(package, addons_dev_dir)
        )

    url_pattern = re.compile('(\S*/{}/\S*)'.format(package))
    new_package_path = '-e /app/addons-dev/{}\n'.format(package)

    # add package to requirements.in for dependencies
    requirements_file = os.path.join(project_home, 'requirements.in')
    # open file with 'universal newline support'
    # https://docs.python.org/2/library/functions.html#open
    with open(requirements_file, 'rU') as fh:
        addons = fh.readlines()

    replaced = False

    for counter, addon in enumerate(addons):
        if re.match(url_pattern, addon) or addon == new_package_path:
            addons[counter] = new_package_path
            replaced = True
            break

    if not replaced:
        # Not replaced, append to generated part of requirements
        for counter, addon in enumerate(addons):
            if '</INSTALLED_ADDONS>' in addon:
                addons.insert(counter, new_package_path)
                replaced = True
                break

    if not replaced:
        # fallback: generated section seems to be missing, appending
        addons.append(new_package_path)

    with open(requirements_file, 'w') as fh:
        fh.writelines(addons)

    if not no_rebuild:
        # build web again
        docker_compose = utils.get_docker_compose_cmd(project_home)

        try:
            execute(
                docker_compose('build', 'web'),
                silent=False,
                stderr=subprocess.STDOUT,
            )
        except subprocess.CalledProcessError as exc:
            raise click.ClickException(exc.output)

    click.secho(
        'The package {} has been added to your local development project!'
        .format(package)
    )

def open_project(open_browser=True):
    docker_compose = utils.get_docker_compose_cmd(utils.get_project_home())
    try:
        addr = execute(docker_compose('port', 'web', '80'), silent=True)
    except subprocess.CalledProcessError:
        if click.prompt('Your project is not running. Do you want to start '
                        'it now?'):
            return start_project()
        return
    host, port = addr.split(':')

    if host == '0.0.0.0':
        docker_host_url = os.environ.get('DOCKER_HOST')
        if docker_host_url:
            proto, host_port = os.environ.get('DOCKER_HOST').split('://')
            host = host_port.split(':')[0]

    addr = 'http://{host}:{port}/'.format(
        host=host.replace(os.linesep, ''),
        port=port.replace(os.linesep, ''),
    )

    click.secho(
        'Your project is configured to run at {}'.format(addr),
        fg='green'
    )

    click.secho('Waiting for project to start..', fg='green', nl=False)
    # wait 30s for runserver to startup
    seconds = 30
    for attempt in range(seconds):
        click.secho('.', fg='green', nl=False)
        try:
            requests.head(addr)
        except requests.ConnectionError:
            sleep(1)
        else:
            break

        if attempt == seconds - 1:
            raise click.ClickException(
                "\nProject failed to start. Please run 'docker-compose logs' "
                "to get more information."
            )

    if open_browser:
        click.launch(addr)
    return addr

def start_project():
    docker_compose = utils.get_docker_compose_cmd(utils.get_project_home())
    my_stdout = StringIO()
    try:
        with redirect_stdout(my_stdout):
            execute(docker_compose('up', '-d'), stderr=subprocess.STDOUT)
    except subprocess.CalledProcessError as e:
        my_stdout.seek(0)
        output = my_stdout.read()
        if 'port is already allocated' in output:
            click.secho(
                "There's already another program running on this project's "
                "port. Please either stop the other program or change the"
                "port in the 'docker-compose.yml' file and try again.\n",
                fg='red'
            )
        raise click.ClickException(output)

    return open_project(open_browser=True)

def stop_project():
    docker_compose = utils.get_docker_compose_cmd(utils.get_project_home())
    execute(docker_compose('stop'))
<commit_msg>upload-db: start db container first<commit_after>import json
import tarfile
import re
import os
import subprocess
from StringIO import StringIO
from time import sleep

import click
import requests

from ..utils import dev_null, execute, redirect_stdout
from ..cloud import get_aldryn_host
from .. import settings
from . import utils

DEFAULT_GIT_HOST = 'git@git.{aldryn_host}'
GIT_CLONE_URL = '{git_host}:{project_slug}.git'

def get_git_host():
    git_host = os.environ.get('ALDRYN_GIT_HOST')
    if git_host:
        click.secho('Using custom git host {}\n'.format(git_host), fg='yellow')
    else:
        git_host = DEFAULT_GIT_HOST.format(aldryn_host=get_aldryn_host())
    return git_host

def get_git_clone_url(slug):
    return GIT_CLONE_URL.format(git_host=get_git_host(), project_slug=slug)

def create_workspace(client, website_slug, path=None):
    click.secho('Creating workspace...', fg='green')

    path = os.path.abspath(
        os.path.join(path, website_slug)
        if path else website_slug
    )

    docker_compose = utils.get_docker_compose_cmd(path)
    website_id = client.get_website_id_for_slug(website_slug)
    website_git_url = get_git_clone_url(website_slug)

    try:
        click.secho('\ncloning project repository', fg='green')
        clone_args = ['git', 'clone', website_git_url]
        if path:
            clone_args.append(path)
        execute(clone_args, silent=False, stderr=subprocess.STDOUT)
    except subprocess.CalledProcessError as exc:
        raise click.ClickException(exc.output)

    # Detect old style or invalid projects
    compose_config = os.path.join(path or website_slug, 'docker-compose.yml')
    if not os.path.isfile(compose_config):
        raise click.ClickException(
            "Aldryn local development only works with projects using "
            "baseproject version 3 and have a valid 'docker-compose.yml' file."
        )

    # create .aldryn file
    website_data = {'id': website_id, 'slug': website_slug}
    with open(os.path.join(path, settings.ALDRYN_DOT_FILE), 'w+') as fh:
        json.dump(website_data, fh)

    existing_db_container_id = utils.get_db_container_id(path)

    # stop all running for project
    execute(docker_compose('stop'), silent=True)

    # pull docker images
    click.secho('downloading remote docker images', fg='green')
    execute(docker_compose('pull'), silent=False, stderr=subprocess.STDOUT)

    # build docker images
    click.secho('building local docker images', fg='green')
    execute(docker_compose('build'), silent=False, stderr=subprocess.STDOUT)

    if existing_db_container_id:
        click.secho('removing old database container', fg='green')
        execute(
            docker_compose('stop', 'db'),
            stderr=subprocess.STDOUT,
            silent=False,
        )
        execute(
            docker_compose('rm', '-f', 'db'),
            stderr=subprocess.STDOUT,
            silent=False,
        )

    click.secho('creating new database container', fg='green')
    load_database_dump(client, path, recreate=True)

    click.secho('sync and migrate database', fg='green')
    # FIXME: Running this command with silent=False raises:
    #   IOError: [Errno 35] Resource temporarily unavailable
    #   see http://trac.edgewall.org/ticket/2066
    execute(
        docker_compose('run', 'web', './migrate.sh'),
        stderr=subprocess.STDOUT,
        silent=True,  # silent=False raises
    )

    instructions = [
        "Finished setting up your project's workspace!",
        "To start the project, please:",
    ]

    if path:
        instructions.append(' - change directory into {}'.format(path))
    instructions.append(' - run aldryn project up')

    click.secho('\n\n{}'.format(os.linesep.join(instructions)), fg='green')

def load_database_dump(client, path=None, recreate=False):
    path = path or utils.get_project_home(path)
    website_slug = utils.get_aldryn_project_settings(path)['slug']
    docker_compose = utils.get_docker_compose_cmd(path)

    start_db_cmd = ['up', '-d']
    if recreate:
        start_db_cmd.append('--force-recreate')
    start_db_cmd.append('db')

    # start db
    execute(
        docker_compose(*start_db_cmd),
        stderr=subprocess.STDOUT,
        silent=True,
    )

    # get db container id
    db_container_id = utils.get_db_container_id(path)

    click.secho('fetching database dump', fg='green')
    db_dump_path = client.download_db(website_slug, directory=path)
    # strip path from dump_path for use in the docker container
    db_dump_path = db_dump_path.replace(path, '')

    # waiting another 10 seconds to make sure
    # the db has enough time to start
    sleep(10)

    # create empty db
    try:
        execute([
            'docker', 'exec', db_container_id,
            'dropdb', '-U', 'postgres', 'db',
        ], silent=True, stderr=subprocess.STDOUT)
    except subprocess.CalledProcessError:
        pass

    execute([
        'docker', 'exec', db_container_id,
        'createdb', '-U', 'postgres', 'db',
    ], silent=True, stderr=subprocess.STDOUT)

    click.secho('inserting database dump', fg='green')
    # FIXME: because of different ownership,
    # this spits a lot of warnings which can
    # ignored but we can't really validate success
    with dev_null() as devnull:
        try:
            piped_restore = (
                'tar -xzOf /app/{}'
                ' | pg_restore -U postgres -d db'
                .format(db_dump_path)
            )
            subprocess.call((
                'docker', 'exec', db_container_id,
                '/bin/bash', '-c', piped_restore,
            ), stdout=devnull, stderr=devnull)
        except subprocess.CalledProcessError:
            pass

    # stop db
    execute(
        docker_compose('stop'),
        silent=True,
        stderr=subprocess.STDOUT,
    )

def download_media(client, path=None):
    click.secho('fetching media files', fg='green')

    path = path or os.path.join(utils.get_project_home(path), 'data/media')
    website_slug = utils.get_aldryn_project_settings(path)['slug']
    backup_path = client.download_backup(website_slug)

    with tarfile.open(backup_path, 'r:gz') as backup_archive:
        media_archive_name = 'media_files.tar.gz'
        if media_archive_name not in backup_archive.getnames():
            click.secho('Media archive empty', fg='yellow')
            return

        media_fobj = backup_archive.extractfile(media_archive_name)
        with tarfile.open(fileobj=media_fobj, mode='r:gz') as media_archive:
            media_archive.extractall(path=path)

    os.remove(backup_path)
    click.secho('Downloaded media files into {}'.format(path), fg='green')

def upload_database(client):
    project_home = utils.get_project_home()
    website_id = utils.get_aldryn_project_settings(project_home)['id']
    dump_filename = 'local_db.sql'
    archive_filename = 'local_db.tar.gz'
    archive_path = os.path.join(project_home, archive_filename)
    docker_compose = utils.get_docker_compose_cmd(project_home)

    # start db
    execute(
        docker_compose('up', '-d', 'db'),
        stderr=subprocess.STDOUT,
        silent=True,
    )

    # take dump of database
    click.secho('Dumping local database', fg='green')
    db_container_id = utils.get_db_container_id(project_home)

    subprocess.call((
        'docker', 'exec', db_container_id,
        'pg_dump', '-U', 'postgres', '-d', 'db',
        '-f', os.path.join('/app/', dump_filename)
    ))

    click.secho('Creating archive of SQL dump', fg='green')
    with tarfile.open(archive_path, mode='w:gz') as tar:
        tar.add(
            os.path.join(project_home, dump_filename),
            arcname=dump_filename
        )

    click.secho('Pushing database to Aldryn', fg='green')
    client.upload_db(website_id, archive_path)
    # clean up
    for temp_file in (dump_filename, archive_filename):
        os.remove(os.path.join(project_home, temp_file))
    click.secho('Done', fg='green')

def upload_media(client):
    project_home = utils.get_project_home()
    website_id = utils.get_aldryn_project_settings(project_home)['id']
    archive_path = os.path.join(project_home, 'local_media.tar.gz')

    click.secho('Creating archive of local media folder', fg='green')
    with tarfile.open(archive_path, mode='w:gz') as tar:
        media_dir = os.path.join(project_home, 'data', 'media')
        for item in os.listdir(media_dir):
            tar.add(os.path.join(media_dir, item), arcname=item)

    click.secho('Pushing archive to Aldryn', fg='green')
    client.upload_media_files(website_id, archive_path)

    # clean up
    os.remove(archive_path)
    click.secho('Done', fg='green')

def develop_package(package, no_rebuild=False):
    """
    :param package: package name in addons-dev folder
    """

    project_home = utils.get_project_home()
    addons_dev_dir = os.path.join(project_home, 'addons-dev')

    if not os.path.isdir(os.path.join(addons_dev_dir, package)):
        raise click.ClickException(
            'Package {} could not be found in {}. Please make '
            'sure it exists and try again.'
            .format(package, addons_dev_dir)
        )

    url_pattern = re.compile('(\S*/{}/\S*)'.format(package))
    new_package_path = '-e /app/addons-dev/{}\n'.format(package)

    # add package to requirements.in for dependencies
    requirements_file = os.path.join(project_home, 'requirements.in')
    # open file with 'universal newline support'
    # https://docs.python.org/2/library/functions.html#open
    with open(requirements_file, 'rU') as fh:
        addons = fh.readlines()

    replaced = False

    for counter, addon in enumerate(addons):
        if re.match(url_pattern, addon) or addon == new_package_path:
            addons[counter] = new_package_path
            replaced = True
            break

    if not replaced:
        # Not replaced, append to generated part of requirements
        for counter, addon in enumerate(addons):
            if '</INSTALLED_ADDONS>' in addon:
                addons.insert(counter, new_package_path)
                replaced = True
                break

    if not replaced:
        # fallback: generated section seems to be missing, appending
        addons.append(new_package_path)

    with open(requirements_file, 'w') as fh:
        fh.writelines(addons)

    if not no_rebuild:
        # build web again
        docker_compose = utils.get_docker_compose_cmd(project_home)

        try:
            execute(
                docker_compose('build', 'web'),
                silent=False,
                stderr=subprocess.STDOUT,
            )
        except subprocess.CalledProcessError as exc:
            raise click.ClickException(exc.output)

    click.secho(
        'The package {} has been added to your local development project!'
        .format(package)
    )

def open_project(open_browser=True):
    docker_compose = utils.get_docker_compose_cmd(utils.get_project_home())
    try:
        addr = execute(docker_compose('port', 'web', '80'), silent=True)
    except subprocess.CalledProcessError:
        if click.prompt('Your project is not running. Do you want to start '
                        'it now?'):
            return start_project()
        return
    host, port = addr.split(':')

    if host == '0.0.0.0':
        docker_host_url = os.environ.get('DOCKER_HOST')
        if docker_host_url:
            proto, host_port = os.environ.get('DOCKER_HOST').split('://')
            host = host_port.split(':')[0]

    addr = 'http://{host}:{port}/'.format(
        host=host.replace(os.linesep, ''),
        port=port.replace(os.linesep, ''),
    )

    click.secho(
        'Your project is configured to run at {}'.format(addr),
        fg='green'
    )

    click.secho('Waiting for project to start..', fg='green', nl=False)
    # wait 30s for runserver to startup
    seconds = 30
    for attempt in range(seconds):
        click.secho('.', fg='green', nl=False)
        try:
            requests.head(addr)
        except requests.ConnectionError:
            sleep(1)
        else:
            break

        if attempt == seconds - 1:
            raise click.ClickException(
                "\nProject failed to start. Please run 'docker-compose logs' "
                "to get more information."
            )

    if open_browser:
        click.launch(addr)
    return addr

def start_project():
    docker_compose = utils.get_docker_compose_cmd(utils.get_project_home())
    my_stdout = StringIO()
    try:
        with redirect_stdout(my_stdout):
            execute(docker_compose('up', '-d'), stderr=subprocess.STDOUT)
    except subprocess.CalledProcessError as e:
        my_stdout.seek(0)
        output = my_stdout.read()
        if 'port is already allocated' in output:
            click.secho(
                "There's already another program running on this project's "
                "port. Please either stop the other program or change the"
                "port in the 'docker-compose.yml' file and try again.\n",
                fg='red'
            )
        raise click.ClickException(output)

    return open_project(open_browser=True)

def stop_project():
    docker_compose = utils.get_docker_compose_cmd(utils.get_project_home())
    execute(docker_compose('stop'))
<|endoftext|>


<commit_before>###############################################################################
# The MIT License (MIT)
#
# Copyright (c) 2013 Cassio Paixao
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
###############################################################################

from core.event import EventType, EventBuilder

class CloudSimulator:

    def __init__(self, config):
        self._config = config
        self._logger = None

    def simulate(self):
        self._initialize()
        while True:
            events = self._config.events_queue.next_events()
            if events is None:
                self._config.statistics.notify_event('simulation_finished',
                                                     timestamp=self._config.simulation_info.current_timestamp)
                break
            self._update_simulation_info(events[0])
            self._logger.debug('Processing %d events of type: %s', len(events), EventType.get_type(events[0].type))
            for event in events:
                self._logger.debug('Will process event: %s', event.dump())

            self._config.simulation_info.scope.append(events[0].type)
            self._logger.debug('Adding %s to scope.', EventType.get_type(events[0].type))
            self._process_events(events)
            removed_from_scope = self._config.simulation_info.scope.pop()
            self._logger.debug('Removing %s from scope.', EventType.get_type(removed_from_scope))

    def _initialize(self):
        self._config.initialize()
        self._logger = self._config.getLogger(self)
        self._add_prediction_time(int(self._config.params['first_prediction_time']))
        self._add_vms_pool_verification_time(int(self._config.params['vms_pool_first_verification']))
        self._vms_pool_verification_interval = int(self._config.params['vms_pool_verification_interval'])
        self._add_punish_vms_time(int(self._config.params['vms_punishment_first_time']))
        self._punish_vms_interval = int(self._config.params['vms_punishment_interval'])
        self._add_simulation_started_event()

    def _process_events(self, events):
        strategies = self._config.strategies
        events_type = events[0].type

        if events_type in [EventType.TIME_TO_PREDICT, EventType.UPDATES_FINISHED, EventType.VERIFY_VMS_POOL, EventType.PUNISH_VMS]:
            if len(events) > 1:
                self._logger.warning('There should be only one event of type %s. %d found.',
                                     EventType.get_type(events[0].type), len(events))
            self._process_event(events[0])

        elif events_type == EventType.SUBMIT:
            self._config.statistics.notify_event('submit_events', len(events))
            vms = []
            for event in events:
                self._config.resource_manager.add_vm(event.vm, event.process_time)
                vms.append(event.vm)
            strategies.scheduling.schedule_vms(vms)

        elif events_type == EventType.UPDATE:
            self._config.statistics.notify_event('update_events', len(events))
            for event in events:
                self._config.resource_manager.update_vm_demands(event.vm)

        elif events_type == EventType.FINISH:
            updated_servers = []
            for event in events:
                if self._config.resource_manager.is_it_time_to_finish_vm(event.vm):
                    updated_servers.append(self._config.resource_manager.get_server_of_vm(event.vm.name))
                    self._config.statistics.notify_event('finish_events')
                    self._config.resource_manager.free_vm_resources(event.vm)
                    self._config.statistics.notify_event('vm_finished',
                                                         vm= event.vm)
                    # this should be removed. A global observer/notifier can be used
                    if 'MeasurementReader' in self._config.module:
                        self._config.module['MeasurementReader'].free_cache_for_vm(event.vm.name)
                else:
                    self._config.statistics.notify_event('outdated_finish_events')
            self._verify_machines_to_turn_off(set(updated_servers))

        elif events_type == EventType.NOTIFY:
            for event in events:
                self._config.statistics.notify_event(event.message)

        else:
            self._logger.error('Unknown event: %s'.format(event.dump()))
            raise Exception('Unknown event: %s'.format(event.dump()))

        if self._does_simulation_finished():
            self._verify_machines_to_turn_off()
            self._config.events_queue.clear()

    def _process_event(self, event):
        strategies = self._config.strategies

        if event.type == EventType.TIME_TO_PREDICT:
            for server in self._config.resource_manager.online_servers():
                for vm in server.vm_list():
                    prediction = strategies.prediction.predict(vm.name)
                    if prediction is not None:
                        self._config.events_queue.add_event(
                            EventBuilder.build_update_event(self._config.simulation_info.current_timestamp,
                                                            vm.name,
                                                            prediction[0],
                                                            prediction[1]))
            self._add_prediction_time(
                self._config.simulation_info.current_timestamp + strategies.prediction.next_prediction_interval())

        elif event.type == EventType.UPDATES_FINISHED:
            self._config.simulation_info.scope.append('migration')
            should_migrate = strategies.migration.list_of_vms_to_migrate(
                self._config.resource_manager.online_servers())
            for vm in should_migrate:
                self._config.resource_manager.free_vm_resources(vm)
            strategies.migration.migrate_vms(should_migrate)
            self._config.simulation_info.scope.pop()
            self._verify_machines_to_turn_off()

        elif event.type == EventType.VERIFY_VMS_POOL:
            self._try_to_allocate_vms_in_pool()

        elif event.type == EventType.PUNISH_VMS:
            self._punish_performance_of_vms_at_overloaded_servers()

        else:
            self._logger.error('Unknown event: %s'.format(event.dump()))
            raise Exception('Unknown event: %s'.format(event.dump()))

    def _punish_performance_of_vms_at_overloaded_servers(self):
        measurement_reader = self._config.module['MeasurementReader']
        overloaded_servers = measurement_reader.overloaded_servers()
        for server in overloaded_servers:
            cpu_demmand = mem_demmand = 0.0
            for vm in server.vm_list():
                measurement = measurement_reader.current_measurement(vm.name)
                cpu_demmand += measurement[measurement_reader.CPU]
                mem_demmand += measurement[measurement_reader.MEM]
            cpu_exceeded = max(0.0, cpu_demmand - server.cpu)
            mem_exceeded = max(0.0, mem_demmand - server.mem)
            time_punish_factor = min(0.95, cpu_exceeded + mem_exceeded) # in [0.0, 0.95]
            time_punish = int(self._vms_pool_verification_interval * time_punish_factor)
            self._logger.debug('Will punish %d VMs of server %s. Time punish factor: %.4f; Time punish: %d',
                               len(server.vm_list()), server.name, time_punish_factor, time_punish)
            for vm in server.vm_list():
                self._config.resource_manager.add_processing_time_to_vm(vm, time_punish)
            self._config.statistics.notify_event('processing_time_added_to_vms', time_punish*len(server.vm_list()))

        self._add_punish_vms_time(self._config.simulation_info.current_timestamp + self._punish_vms_interval)

    def _does_simulation_finished(self):
        if len(self._config.resource_manager.online_vms_names()) == 0 and \
            len(self._config.vms_pool) == 0 and \
            not self._config.events_queue.has_submit_events():
            return True
        return False

    def _add_prediction_time(self, timestamp):
        self._config.events_queue.add_event(
            EventBuilder.build_time_to_predict_event(timestamp))
        self._config.events_queue.add_event(
            EventBuilder.build_updates_finished_event(timestamp))

    def _add_simulation_started_event(self):
        self._config.events_queue.add_event(
            EventBuilder.build_notify_event(0, 'simulation_started'))

    def _update_simulation_info(self, event):
        if event.time > self._config.simulation_info.current_timestamp:
            self._notify_timestamp_change(self._config.simulation_info.current_timestamp, event.time)
        self._config.simulation_info.current_timestamp = event.time

    def _notify_timestamp_change(self, last_timestamp, new_timestamp):
        self._config.statistics.notify_event('timestamp_ended',    timestamp=last_timestamp)
        self._config.statistics.notify_event('timestamp_starting', timestamp=new_timestamp )
        self._logger.info('Timestamp start: %d', new_timestamp)

    def _try_to_allocate_vms_in_pool(self):
        vms = list(self._config.vms_pool.get_ordered_list())
        self._config.strategies.scheduling.schedule_vms(self._config.vms_pool.get_high_priority_vms())
        self._config.strategies.scheduling.schedule_vms(self._config.vms_pool.get_low_priority_vms())
        for vm in vms:
            if self._config.resource_manager.get_server_of_vm(vm.name) is not None:
                self._config.vms_pool.remove(vm)

        self._add_vms_pool_verification_time(self._config.simulation_info.current_timestamp + self._vms_pool_verification_interval)

    def _add_vms_pool_verification_time(self, timestamp):
        self._config.events_queue.add_event(EventBuilder.build_verify_vms_pool_event(timestamp))

    def _add_punish_vms_time(self, timestamp):
        self._config.events_queue.add_event(EventBuilder.build_punish_vms_event(timestamp))

    def _verify_machines_to_turn_off(self, servers=None):
        self._config.strategies.powering_off.power_off_if_necessary(servers)

class SimulationInfo:
    def __init__(self):
        self.current_timestamp = 0
        self.scope = []
<commit_msg>Revert "Max punishment factor downed to 0.95"<commit_after>###############################################################################
# The MIT License (MIT)
#
# Copyright (c) 2013 Cassio Paixao
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
###############################################################################

from core.event import EventType, EventBuilder

class CloudSimulator:

    def __init__(self, config):
        self._config = config
        self._logger = None

    def simulate(self):
        self._initialize()
        while True:
            events = self._config.events_queue.next_events()
            if events is None:
                self._config.statistics.notify_event('simulation_finished',
                                                     timestamp=self._config.simulation_info.current_timestamp)
                break
            self._update_simulation_info(events[0])
            self._logger.debug('Processing %d events of type: %s', len(events), EventType.get_type(events[0].type))
            for event in events:
                self._logger.debug('Will process event: %s', event.dump())

            self._config.simulation_info.scope.append(events[0].type)
            self._logger.debug('Adding %s to scope.', EventType.get_type(events[0].type))
            self._process_events(events)
            removed_from_scope = self._config.simulation_info.scope.pop()
            self._logger.debug('Removing %s from scope.', EventType.get_type(removed_from_scope))

    def _initialize(self):
        self._config.initialize()
        self._logger = self._config.getLogger(self)
        self._add_prediction_time(int(self._config.params['first_prediction_time']))
        self._add_vms_pool_verification_time(int(self._config.params['vms_pool_first_verification']))
        self._vms_pool_verification_interval = int(self._config.params['vms_pool_verification_interval'])
        self._add_punish_vms_time(int(self._config.params['vms_punishment_first_time']))
        self._punish_vms_interval = int(self._config.params['vms_punishment_interval'])
        self._add_simulation_started_event()

    def _process_events(self, events):
        strategies = self._config.strategies
        events_type = events[0].type

        if events_type in [EventType.TIME_TO_PREDICT, EventType.UPDATES_FINISHED, EventType.VERIFY_VMS_POOL, EventType.PUNISH_VMS]:
            if len(events) > 1:
                self._logger.warning('There should be only one event of type %s. %d found.',
                                     EventType.get_type(events[0].type), len(events))
            self._process_event(events[0])

        elif events_type == EventType.SUBMIT:
            self._config.statistics.notify_event('submit_events', len(events))
            vms = []
            for event in events:
                self._config.resource_manager.add_vm(event.vm, event.process_time)
                vms.append(event.vm)
            strategies.scheduling.schedule_vms(vms)

        elif events_type == EventType.UPDATE:
            self._config.statistics.notify_event('update_events', len(events))
            for event in events:
                self._config.resource_manager.update_vm_demands(event.vm)

        elif events_type == EventType.FINISH:
            updated_servers = []
            for event in events:
                if self._config.resource_manager.is_it_time_to_finish_vm(event.vm):
                    updated_servers.append(self._config.resource_manager.get_server_of_vm(event.vm.name))
                    self._config.statistics.notify_event('finish_events')
                    self._config.resource_manager.free_vm_resources(event.vm)
                    self._config.statistics.notify_event('vm_finished',
                                                         vm= event.vm)
                    # this should be removed. A global observer/notifier can be used
                    if 'MeasurementReader' in self._config.module:
                        self._config.module['MeasurementReader'].free_cache_for_vm(event.vm.name)
                else:
                    self._config.statistics.notify_event('outdated_finish_events')
            self._verify_machines_to_turn_off(set(updated_servers))

        elif events_type == EventType.NOTIFY:
            for event in events:
                self._config.statistics.notify_event(event.message)

        else:
            self._logger.error('Unknown event: %s'.format(event.dump()))
            raise Exception('Unknown event: %s'.format(event.dump()))

        if self._does_simulation_finished():
            self._verify_machines_to_turn_off()
            self._config.events_queue.clear()

    def _process_event(self, event):
        strategies = self._config.strategies

        if event.type == EventType.TIME_TO_PREDICT:
            for server in self._config.resource_manager.online_servers():
                for vm in server.vm_list():
                    prediction = strategies.prediction.predict(vm.name)
                    if prediction is not None:
                        self._config.events_queue.add_event(
                            EventBuilder.build_update_event(self._config.simulation_info.current_timestamp,
                                                            vm.name,
                                                            prediction[0],
                                                            prediction[1]))
            self._add_prediction_time(
                self._config.simulation_info.current_timestamp + strategies.prediction.next_prediction_interval())

        elif event.type == EventType.UPDATES_FINISHED:
            self._config.simulation_info.scope.append('migration')
            should_migrate = strategies.migration.list_of_vms_to_migrate(
                self._config.resource_manager.online_servers())
            for vm in should_migrate:
                self._config.resource_manager.free_vm_resources(vm)
            strategies.migration.migrate_vms(should_migrate)
            self._config.simulation_info.scope.pop()
            self._verify_machines_to_turn_off()

        elif event.type == EventType.VERIFY_VMS_POOL:
            self._try_to_allocate_vms_in_pool()

        elif event.type == EventType.PUNISH_VMS:
            self._punish_performance_of_vms_at_overloaded_servers()

        else:
            self._logger.error('Unknown event: %s'.format(event.dump()))
            raise Exception('Unknown event: %s'.format(event.dump()))

    def _punish_performance_of_vms_at_overloaded_servers(self):
        measurement_reader = self._config.module['MeasurementReader']
        overloaded_servers = measurement_reader.overloaded_servers()
        for server in overloaded_servers:
            cpu_demmand = mem_demmand = 0.0
            for vm in server.vm_list():
                measurement = measurement_reader.current_measurement(vm.name)
                cpu_demmand += measurement[measurement_reader.CPU]
                mem_demmand += measurement[measurement_reader.MEM]
            cpu_exceeded = max(0.0, cpu_demmand - server.cpu)
            mem_exceeded = max(0.0, mem_demmand - server.mem)
            time_punish_factor = min(1.0, cpu_exceeded + mem_exceeded) # in [0.0, 1.0]
            time_punish = int(self._vms_pool_verification_interval * time_punish_factor)
            self._logger.debug('Will punish %d VMs of server %s. Time punish factor: %.4f; Time punish: %d',
                               len(server.vm_list()), server.name, time_punish_factor, time_punish)
            for vm in server.vm_list():
                self._config.resource_manager.add_processing_time_to_vm(vm, time_punish)
            self._config.statistics.notify_event('processing_time_added_to_vms', time_punish*len(server.vm_list()))

        self._add_punish_vms_time(self._config.simulation_info.current_timestamp + self._punish_vms_interval)

    def _does_simulation_finished(self):
        if len(self._config.resource_manager.online_vms_names()) == 0 and \
            len(self._config.vms_pool) == 0 and \
            not self._config.events_queue.has_submit_events():
            return True
        return False

    def _add_prediction_time(self, timestamp):
        self._config.events_queue.add_event(
            EventBuilder.build_time_to_predict_event(timestamp))
        self._config.events_queue.add_event(
            EventBuilder.build_updates_finished_event(timestamp))

    def _add_simulation_started_event(self):
        self._config.events_queue.add_event(
            EventBuilder.build_notify_event(0, 'simulation_started'))

    def _update_simulation_info(self, event):
        if event.time > self._config.simulation_info.current_timestamp:
            self._notify_timestamp_change(self._config.simulation_info.current_timestamp, event.time)
        self._config.simulation_info.current_timestamp = event.time

    def _notify_timestamp_change(self, last_timestamp, new_timestamp):
        self._config.statistics.notify_event('timestamp_ended',    timestamp=last_timestamp)
        self._config.statistics.notify_event('timestamp_starting', timestamp=new_timestamp )
        self._logger.info('Timestamp start: %d', new_timestamp)

    def _try_to_allocate_vms_in_pool(self):
        vms = list(self._config.vms_pool.get_ordered_list())
        self._config.strategies.scheduling.schedule_vms(self._config.vms_pool.get_high_priority_vms())
        self._config.strategies.scheduling.schedule_vms(self._config.vms_pool.get_low_priority_vms())
        for vm in vms:
            if self._config.resource_manager.get_server_of_vm(vm.name) is not None:
                self._config.vms_pool.remove(vm)

        self._add_vms_pool_verification_time(self._config.simulation_info.current_timestamp + self._vms_pool_verification_interval)

    def _add_vms_pool_verification_time(self, timestamp):
        self._config.events_queue.add_event(EventBuilder.build_verify_vms_pool_event(timestamp))

    def _add_punish_vms_time(self, timestamp):
        self._config.events_queue.add_event(EventBuilder.build_punish_vms_event(timestamp))

    def _verify_machines_to_turn_off(self, servers=None):
        self._config.strategies.powering_off.power_off_if_necessary(servers)

class SimulationInfo:
    def __init__(self):
        self.current_timestamp = 0
        self.scope = []
<|endoftext|>


<commit_before>#!/usr/bin/env python
# -*- coding: utf-8 -*-

import pygame

# создадим окно (высота, ширина)
window = pygame.display.set_mode((400, 400))
pygame.display.set_caption('Game!')

#игровой экран
screen = pygame.Surface((400, 400))

#вводим класс для героя
class Sprite:
    def __init__ (self,xpos,ypos,filename):
        self.x=xpos
        self.y=ypos
        self.bitmap=pygame.image.load(filename)
# фон делаем прозрачным
        self.bitmap.set_colorkey((255,255,255))
# отображаем обьект на игровой экран
    def render(self):
        screen.blit(self.bitmap,(self.x, self.y))

# создаем героев
boy1 = Sprite(200,0, 'face1.png')
# новый атрибут герою - рычаг управления_1
boy1_go_right = True
boy1_go_up = False

boy2 = Sprite(200,360, 'face2.png')
# новый атрибут герою - рычаг управления_2
boy2_go_right = True
boy2_go_up = True

# функция проверки пересечения объектов. 40 - величина ширины объектов
def Intersect(x1, x2, y1, y2):
    if ((x1 > x2-40) and (x1 < x2+40) and (y1 > y2-40) and (y1 < y2+40)) :
        return 1
    else:
        return 0

done = True
while done:
    for e in pygame.event.get():
        if e.type == pygame.QUIT:
            done = False

# красим окно , цвета в RGB
    screen.fill((50, 16, 85))

# учим обьекты двигаться

    if boy1_go_up == False:
        boy1.y += 1
        if boy1.y > 360:
            boy1_go_up = True
    else:
        boy1.y -= 1
        if boy1.y < 0:
            boy1_go_up = False

    if boy2_go_up == True:
        boy2.y -= 1
        if boy2.y < 0:
            boy2_go_up = False
    else:
        boy2.y += 1
        if boy2.y > 360:
            boy2_go_up = True
        # проверяем, столкнулись ил и меняем направление движения

    if Intersect(boy2.x, boy1.x, boy2.y, boy1.y) == 1:
        if boy1_go_up == True:
            boy1_go_up = False
        else:
            boy1_go_up = True
        if boy2_go_up == True:
            boy2_go_up = False
        else:
            boy2_go_up = True

    '''
    # boy1
    if boy1_go_right == True:
        boy1.x += 1
        if boy1.x > 360: # ширина экрана минус ширина обьекта
            boy1_go_right = False
    else:
        boy1.x -= 1
        if boy1.x < 0:
            boy1_go_right = True

    if boy1_go_down == True:
        boy1.y += 1
        if boy1.y > 360: # высота экрана минус ширина обьекта
            boy1_go_down = False
    else:
        boy1.y -= 1
        if boy1.y < 0:
            boy1_go_down = True

    # boy2

    if boy2_go_right == True:
        boy2.x += 1
        if boy2.x > 360: # ширина экрана минус ширина обьекта
            boy2_go_right = False
    else:
        boy2.x -= 3
        if boy2.x < 0:
            boy2_go_right = True

    if boy2_go_down == True:
        boy2.y += 1
        if boy2.y > 360: # высота экрана минус ширина обьекта
            boy2_go_down = False
    else:
        boy2.y -= 2
        if boy2.y < 0:
            boy2_go_down = True
   '''

# отобразим обьекты
    boy1.render()
    boy2.render()

    window.blit(screen,  (0, 0))
    pygame.display.flip()
    # делаем задержку
    pygame.time.delay(15)
<commit_msg>add ball<commit_after>#!/usr/bin/env python
# -*- coding: utf-8 -*-

import pygame

# создадим окно (высота, ширина)
window = pygame.display.set_mode((400, 400))
pygame.display.set_caption('Game!')

#игровой экран
screen = pygame.Surface((400, 400))

#вводим класс для героя
class Sprite:
    def __init__ (self,xpos,ypos,filename):
        self.x=xpos
        self.y=ypos
        self.bitmap=pygame.image.load(filename)
# фон делаем прозрачным
        self.bitmap.set_colorkey((255,255,255))
# отображаем обьект на игровой экран
    def render(self):
        screen.blit(self.bitmap,(self.x, self.y))

# создаем героев
boy1 = Sprite(0,0, 'face1.png')
# новый атрибут герою - рычаг управления_1
boy1_go_right = True
boy1_go_up = False

boy2 = Sprite(360,360, 'face2.png')
# новый атрибут герою - рычаг управления_2
boy2_go_right = True
boy2_go_up = True

ball = Sprite(200,200, 'bb1.png')
ball_go = True

# функция проверки пересечения объектов. 40 - величина ширины объектов
def Intersect(x1, x2, y1, y2):
    if ((x1 > x2-40) and (x1 < x2+40) and (y1 > y2-40) and (y1 < y2+40)) :
        return 1
    else:
        return 0

done = True
while done:
    for e in pygame.event.get():
        if e.type == pygame.QUIT:
            done = False

# красим окно , цвета в RGB
    screen.fill((50, 16, 85))

# учим обьекты двигаться

    if boy1_go_up == False:
        boy1.x += 1
        if boy1.x > 360:
            boy1_go_up = True
    else:
        boy1.x -= 1
        if boy1.x < 0:
            boy1_go_up = False

    if boy2_go_up == True:
        boy2.x -= 1
        if boy2.x < 0:
            boy2_go_up = False
    else:
        boy2.x += 1
        if boy2.x > 360:
            boy2_go_up = True
        # проверяем, столкнулись ил и меняем направление движения

    if ball_go == True:
        ball.x += 3
        if ball.x > 385:
            ball_go = False
    else:
        ball.x -= 3
        if ball.x < 0:
            ball_go = True

    if ball_go == True:
        ball.y += 2
        if ball.y > 385:
            ball_go = False
    else:
        ball.y -= 2
        if ball.y < 0:
            ball_go = True

    if Intersect(boy2.x, boy1.x, boy2.y, boy1.y) == 1:
        if boy1_go_up == True:
            boy1_go_up = False
        else:
            boy1_go_up = True
        if boy2_go_up == True:
            boy2_go_up = False
        else:
            boy2_go_up = True

    '''
    # boy1
    if boy1_go_right == True:
        boy1.x += 1
        if boy1.x > 360: # ширина экрана минус ширина обьекта
            boy1_go_right = False
    else:
        boy1.x -= 1
        if boy1.x < 0:
            boy1_go_right = True

    if boy1_go_down == True:
        boy1.y += 1
        if boy1.y > 360: # высота экрана минус ширина обьекта
            boy1_go_down = False
    else:
        boy1.y -= 1
        if boy1.y < 0:
            boy1_go_down = True

    # boy2

    if boy2_go_right == True:
        boy2.x += 1
        if boy2.x > 360: # ширина экрана минус ширина обьекта
            boy2_go_right = False
    else:
        boy2.x -= 3
        if boy2.x < 0:
            boy2_go_right = True

    if boy2_go_down == True:
        boy2.y += 1
        if boy2.y > 360: # высота экрана минус ширина обьекта
            boy2_go_down = False
    else:
        boy2.y -= 2
        if boy2.y < 0:
            boy2_go_down = True
   '''

# отобразим обьекты
    boy1.render()
    boy2.render()
    ball.render()

    window.blit(screen,  (0, 0))
    pygame.display.flip()
    # делаем задержку
    pygame.time.delay(15)
<|endoftext|>


<commit_before># Regression tests for the post-processing tests: sequencing, tracking, tracking
# back, etc.

import unittest
import os, shutil, glob, re

from scipy.misc import imread

from ptv1 import py_start_proc_c, py_init_proc_c
from ptv1 import py_sequence_init, py_sequence_loop, py_set_img
from ptv1 import py_trackcorr_init, py_trackcorr_loop, py_trackcorr_finish
from ptv1 import py_trackback_c

def compare_directories(dir1, dir2, mask=None):
    """
    For all files in dir1, check that the file exists in dir2 and that the
    files are equal line by line.

    Arguments:
    dir1, dir2 - path to the directories for comparison.
    mask - a compiled regular wxpression. Only file names matching it will be
        compared, others will be skipped. If None (default), all files are
        compared.

    Returns:
    True if equal, False otherwise.
    """
    for fname in os.listdir(dir1):
        if (mask is not None) and (mask.search(fname) is None):
            continue

        fout = open(dir1 + fname, "r")
        fcmp = open(dir2 + fname, "r")

        while True:
            lout = fout.readline()
            lcmp = fcmp.readline()
            if lout != lcmp:
                return False
            if len(lout) == 0: break

        fout.close()
        fcmp.close()

    return True

class TestProcessing(unittest.TestCase):
    def setUp(self):
        os.chdir("testing_fodder/")

        if os.path.exists("res/"):
            shutil.rmtree("res/")
        if os.path.exists("scene83_event1/"):
            shutil.rmtree("scene83_event1/")

        shutil.copytree("clean_scene/", "scene83_event1/")

    def tearDown(self):
        shutil.rmtree("res/")
        shutil.rmtree("scene83_event1/")
        os.chdir("../")

    def test_sequencing(self):
        """Sequencing reproduces sample results"""
        os.mkdir("res/")

        py_init_proc_c()
        py_start_proc_c()
        py_sequence_init(0)

        for frame in xrange(497, 598):
            for cam in xrange(4):
                img = imread(
                    "scene83_event1/cam%d_Scene83_%04d" % (cam + 1, frame))
                py_set_img(img, cam)
                py_sequence_loop(0, frame)

        self.failUnless(compare_directories("res/", "after_sequencing/"))
        self.failUnless(compare_directories(
            "scene83_event1/", "after_sequencing_targets/",
            mask=re.compile("_targets$")))

    def test_tracking_run_object(self):
        """The TrackingRun object has access to needed attributes"""
        shutil.copytree("after_sequencing/", "res/")

        run_info = py_trackcorr_init()
        first, last = run_info.get_sequence_range()

        self.failUnlessEqual(first, 497)
        self.failUnlessEqual(last, 597)

    def test_tracking(self):
        """Tracking reproduces sample results"""
        shutil.copytree("after_sequencing/", "res/")
        for fname in glob.iglob("after_sequencing_targets/*"):
            shutil.copy(fname, "scene83_event1/")

        py_init_proc_c()
        py_start_proc_c()
        run_info = py_trackcorr_init()

        for frame in range(497, 597):
            py_trackcorr_loop(run_info, frame, display=0)
        py_trackcorr_finish(run_info, 597)

        self.failUnless(compare_directories("res/", "after_tracking/"))
        self.failUnless(compare_directories(
            "scene83_event1/", "after_tracking_targets/",
            mask=re.compile("_targets$")))

    def test_backtracking(self):
        """Tracking back reproduces sample results"""
        shutil.copytree("after_tracking/", "res/")
        for fname in glob.iglob("after_tracking_targets/*"):
            shutil.copy(fname, "scene83_event1/")

        py_init_proc_c()
        py_start_proc_c()
        py_trackback_c()

        self.failUnless(compare_directories("res/", "after_backtracking/"))
        self.failUnless(compare_directories(
            "scene83_event1/", "after_backtracking_targets/",
            mask=re.compile("_targets$")))

if __name__ == '__main__':
    unittest.main()

<commit_msg>Fix to make the newest test run in sequence with others.<commit_after># Regression tests for the post-processing tests: sequencing, tracking, tracking
# back, etc.

import unittest
import os, shutil, glob, re

from scipy.misc import imread

from ptv1 import py_start_proc_c, py_init_proc_c
from ptv1 import py_sequence_init, py_sequence_loop, py_set_img
from ptv1 import py_trackcorr_init, py_trackcorr_loop, py_trackcorr_finish
from ptv1 import py_trackback_c

def compare_directories(dir1, dir2, mask=None):
    """
    For all files in dir1, check that the file exists in dir2 and that the
    files are equal line by line.

    Arguments:
    dir1, dir2 - path to the directories for comparison.
    mask - a compiled regular wxpression. Only file names matching it will be
        compared, others will be skipped. If None (default), all files are
        compared.

    Returns:
    True if equal, False otherwise.
    """
    for fname in os.listdir(dir1):
        if (mask is not None) and (mask.search(fname) is None):
            continue

        fout = open(dir1 + fname, "r")
        fcmp = open(dir2 + fname, "r")

        while True:
            lout = fout.readline()
            lcmp = fcmp.readline()
            if lout != lcmp:
                return False
            if len(lout) == 0: break

        fout.close()
        fcmp.close()

    return True

class TestProcessing(unittest.TestCase):
    def setUp(self):
        os.chdir("testing_fodder/")

        if os.path.exists("res/"):
            shutil.rmtree("res/")
        if os.path.exists("scene83_event1/"):
            shutil.rmtree("scene83_event1/")

        shutil.copytree("clean_scene/", "scene83_event1/")

    def tearDown(self):
        shutil.rmtree("res/")
        shutil.rmtree("scene83_event1/")
        os.chdir("../")

    def test_sequencing(self):
        """Sequencing reproduces sample results"""
        os.mkdir("res/")

        py_init_proc_c()
        py_start_proc_c()
        py_sequence_init(0)

        for frame in xrange(497, 598):
            for cam in xrange(4):
                img = imread(
                    "scene83_event1/cam%d_Scene83_%04d" % (cam + 1, frame))
                py_set_img(img, cam)
                py_sequence_loop(0, frame)

        self.failUnless(compare_directories("res/", "after_sequencing/"))
        self.failUnless(compare_directories(
            "scene83_event1/", "after_sequencing_targets/",
            mask=re.compile("_targets$")))

    def test_tracking_run_object(self):
        """The TrackingRun object has access to needed attributes"""
        shutil.copytree("after_sequencing/", "res/")
        for fname in glob.iglob("after_sequencing_targets/*"):
            shutil.copy(fname, "scene83_event1/")

        run_info = py_trackcorr_init()
        first, last = run_info.get_sequence_range()

        self.failUnlessEqual(first, 497)
        self.failUnlessEqual(last, 597)

    def test_tracking(self):
        """Tracking reproduces sample results"""
        shutil.copytree("after_sequencing/", "res/")
        for fname in glob.iglob("after_sequencing_targets/*"):
            shutil.copy(fname, "scene83_event1/")

        py_init_proc_c()
        py_start_proc_c()
        run_info = py_trackcorr_init()

        for frame in range(497, 597):
            py_trackcorr_loop(run_info, frame, display=0)
        py_trackcorr_finish(run_info, 597)

        self.failUnless(compare_directories("res/", "after_tracking/"))
        self.failUnless(compare_directories(
            "scene83_event1/", "after_tracking_targets/",
            mask=re.compile("_targets$")))

    def test_backtracking(self):
        """Tracking back reproduces sample results"""
        shutil.copytree("after_tracking/", "res/")
        for fname in glob.iglob("after_tracking_targets/*"):
            shutil.copy(fname, "scene83_event1/")

        py_init_proc_c()
        py_start_proc_c()
        py_trackback_c()

        self.failUnless(compare_directories("res/", "after_backtracking/"))
        self.failUnless(compare_directories(
            "scene83_event1/", "after_backtracking_targets/",
            mask=re.compile("_targets$")))

if __name__ == '__main__':
    unittest.main()

<|endoftext|>


<commit_before>import logging
from gi.repository import Gtk

class CompositionToolbarController(object):
	""" Manages Accelerators and Clicks on the Composition Toolbar-Buttons """

	def __init__(self, drawing_area, win, uibuilder):
		self.log = logging.getLogger('CompositionToolbarController')

		accelerators = Gtk.AccelGroup()
		win.add_accel_group(accelerators)

		composites = [
			'composite-fullscreen',
			'composite-picture-in-picture',
			'composite-side-by-side-equal',
			'composite-side-by-side-preview'
		]

		for idx, name in enumerate(composites):
			key, mod = Gtk.accelerator_parse('F%u' % (idx+1))
			btn = uibuilder.find_widget_recursive(drawing_area, name)
			btn.set_name(name)

			# Thanks to http://stackoverflow.com/a/19739855/1659732
			btn.get_child().add_accelerator('clicked', accelerators, key, mod, Gtk.AccelFlags.VISIBLE)
			btn.connect('toggled', self.on_btn_toggled)

	def on_btn_toggled(self, btn):
		if not btn.get_active():
			return

		self.log.info("on_btn_toggled: %s", btn.get_name())
<commit_msg>connect composition-toolbar to server<commit_after>import logging
from gi.repository import Gtk

import lib.connection as Connection

class CompositionToolbarController(object):
	""" Manages Accelerators and Clicks on the Composition Toolbar-Buttons """

	def __init__(self, drawing_area, win, uibuilder):
		self.log = logging.getLogger('CompositionToolbarController')

		accelerators = Gtk.AccelGroup()
		win.add_accel_group(accelerators)

		composites = [
			'fullscreen',
			'picture_in_picture',
			'side_by_side_equal',
			'side_by_side_preview'
		]

		self.composite_btns = {}

		for idx, name in enumerate(composites):
			key, mod = Gtk.accelerator_parse('F%u' % (idx+1))
			btn = uibuilder.find_widget_recursive(drawing_area, 'composite-'+name.replace('_', '-'))
			btn.set_name(name)

			# Thanks to http://stackoverflow.com/a/19739855/1659732
			btn.get_child().add_accelerator('clicked', accelerators, key, mod, Gtk.AccelFlags.VISIBLE)
			btn.connect('toggled', self.on_btn_toggled)

			self.composite_btns[name] = btn

		# connect event-handler and request initial state
		Connection.on('composite_mode', self.on_composite_mode)
		Connection.send('get_composite_mode')

	def on_btn_toggled(self, btn):
		if not btn.get_active():
			return

		btn_name = btn.get_name()
		self.log.info('composition-mode activated: %s', btn_name)
		Connection.send('set_composite_mode', btn_name)

	def on_composite_mode(self, mode):
		self.log.info('on_composite_mode callback w/ mode %s', mode)
		self.composite_btns[mode].set_active(True)
<|endoftext|>


<commit_before>"""
Signal receiving functions which handle Modified Preorder Tree Traversal
related logic when model instances are about to be saved or deleted.
"""
import operator

from django.db.models.query import Q
from django.utils.translation import ugettext as _

__all__ = ('pre_save', 'pre_delete')

def _insertion_target_filters(node, order_insertion_by):
    """
    Creates a filter which matches suitable right siblings for ``node``,
    where insertion should maintain ordering according to the list of
    fields in ``order_insertion_by``.

    For example, given an ``order_insertion_by`` of
    ``['field1', 'field2', 'field3']``, the resulting filter should
    correspond to the following SQL::

       field1 > %s
       OR (field1 = %s AND field2 > %s)
       OR (field1 = %s AND field2 = %s AND field3 > %s)

    """
    fields = []
    filters = []
    for field in order_insertion_by:
        value = getattr(node, field)
        filters.append(reduce(operator.and_, [Q(**{f: v}) for f, v in fields] +
                                             [Q(**{'%s__gt' % field: value})]))
        fields.append((field, value))
    return reduce(operator.or_, filters)

def _get_ordered_insertion_target(node, parent):
    """
    Attempts to retrieve a suitable right sibling for ``node``
    underneath ``parent`` (which may be ``None`` in the case of root
    nodes) so that ordering by the fields specified by the node's class'
    ``order_insertion_by`` option is maintained.

    Returns ``None`` if no suitable sibling can be found.
    """
    right_sibling = None
    # Optimisation - if the parent doesn't have descendants,
    # the node will always be its last child.
    if parent is None or parent.get_descendant_count() > 0:
        opts = node._meta
        order_by = opts.order_insertion_by[:]
        filters = _insertion_target_filters(node, order_by)
        if parent:
            filters = filters & Q(**{opts.parent_attr: parent})
            # Fall back on tree ordering if multiple child nodes have
            # the same values.
            order_by.append(opts.left_attr)
        else:
            filters = filters & Q(**{'%s__isnull' % opts.parent_attr: True})
            # Fall back on tree id ordering if multiple root nodes have
            # the same values.
            order_by.append(opts.tree_id_attr)
        try:
            right_sibling = \
                node._default_manager.filter(filters).order_by(*order_by)[0]
        except IndexError:
            # No suitable right sibling could be found
            pass
    return right_sibling

def pre_save(instance, **kwargs):
    """
    If this is a new node, sets tree fields up before it is inserted
    into the database, making room in the tree structure as neccessary,
    defaulting to making the new node the last child of its parent.

    It the node's left and right edge indicators already been set, we
    take this as indication that the node has already been set up for
    insertion, so its tree fields are left untouched.

    If this is an existing node and its parent has been changed,
    performs reparenting in the tree structure, defaulting to making the
    node the last child of its new parent.

    In either case, if the node's class has its ``order_insertion_by``
    tree option set, the node will be inserted or moved to the
    appropriate position to maintain ordering by the specified field.

    .. note::
       The ``raw`` argument accepted by ``Model.save()`` is not
       currently passed along when the ``pre_save`` signal is
       dispatched, but we check for it anyway for the benefit of people
       who need to use fixtures and are willing to apply the patch in
       ticket http://code.djangoproject.com/ticket/5422 to their own
       version of Django.

    """
    if kwargs.get('raw'):
        return

    opts = instance._meta
    parent = getattr(instance, opts.parent_attr)
    if not instance.pk:
        if (getattr(instance, opts.left_attr) and
            getattr(instance, opts.right_attr)):
            # This node has already been set up for insertion.
            return

        if opts.order_insertion_by:
            right_sibling = _get_ordered_insertion_target(instance, parent)
            if right_sibling:
                instance.insert_at(right_sibling, 'left')
                return

        # Default insertion
        instance.insert_at(parent, position='last-child')
    else:
        # TODO Is it possible to track the original parent so we
        #      don't have to look it up again on each save after the
        #      first?
        old_parent = getattr(instance._default_manager.get(pk=instance.pk),
                             opts.parent_attr)
        if parent != old_parent:
            setattr(instance, opts.parent_attr, old_parent)
            try:
                if opts.order_insertion_by:
                    right_sibling = _get_ordered_insertion_target(instance,
                                                                  parent)
                    if right_sibling:
                        instance.move_to(right_sibling, 'left')
                        return

                # Default movement
                instance.move_to(parent, position='last-child')
            finally:
                # Make sure the instance's new parent is always
                # restored on the way out in case of errors.
                setattr(instance, opts.parent_attr, parent)

def pre_delete(instance, **kwargs):
    """
    Updates tree node edge indicators which will by affected by the
    deletion of the given model instance and any descendants it may
    have, to ensure the integrity of the tree structure is
    maintained.
    """
    opts = instance._meta
    tree_width = (getattr(instance, opts.right_attr) -
                  getattr(instance, opts.left_attr) + 1)
    target_right = getattr(instance, opts.right_attr)
    tree_id = getattr(instance, opts.tree_id_attr)
    instance._tree_manager._close_gap(tree_width, target_right, tree_id)
<commit_msg>Removed obsolete note.<commit_after>"""
Signal receiving functions which handle Modified Preorder Tree Traversal
related logic when model instances are about to be saved or deleted.
"""
import operator

from django.db.models.query import Q
from django.utils.translation import ugettext as _

__all__ = ('pre_save', 'pre_delete')

def _insertion_target_filters(node, order_insertion_by):
    """
    Creates a filter which matches suitable right siblings for ``node``,
    where insertion should maintain ordering according to the list of
    fields in ``order_insertion_by``.

    For example, given an ``order_insertion_by`` of
    ``['field1', 'field2', 'field3']``, the resulting filter should
    correspond to the following SQL::

       field1 > %s
       OR (field1 = %s AND field2 > %s)
       OR (field1 = %s AND field2 = %s AND field3 > %s)

    """
    fields = []
    filters = []
    for field in order_insertion_by:
        value = getattr(node, field)
        filters.append(reduce(operator.and_, [Q(**{f: v}) for f, v in fields] +
                                             [Q(**{'%s__gt' % field: value})]))
        fields.append((field, value))
    return reduce(operator.or_, filters)

def _get_ordered_insertion_target(node, parent):
    """
    Attempts to retrieve a suitable right sibling for ``node``
    underneath ``parent`` (which may be ``None`` in the case of root
    nodes) so that ordering by the fields specified by the node's class'
    ``order_insertion_by`` option is maintained.

    Returns ``None`` if no suitable sibling can be found.
    """
    right_sibling = None
    # Optimisation - if the parent doesn't have descendants,
    # the node will always be its last child.
    if parent is None or parent.get_descendant_count() > 0:
        opts = node._meta
        order_by = opts.order_insertion_by[:]
        filters = _insertion_target_filters(node, order_by)
        if parent:
            filters = filters & Q(**{opts.parent_attr: parent})
            # Fall back on tree ordering if multiple child nodes have
            # the same values.
            order_by.append(opts.left_attr)
        else:
            filters = filters & Q(**{'%s__isnull' % opts.parent_attr: True})
            # Fall back on tree id ordering if multiple root nodes have
            # the same values.
            order_by.append(opts.tree_id_attr)
        try:
            right_sibling = \
                node._default_manager.filter(filters).order_by(*order_by)[0]
        except IndexError:
            # No suitable right sibling could be found
            pass
    return right_sibling

def pre_save(instance, **kwargs):
    """
    If this is a new node, sets tree fields up before it is inserted
    into the database, making room in the tree structure as neccessary,
    defaulting to making the new node the last child of its parent.

    It the node's left and right edge indicators already been set, we
    take this as indication that the node has already been set up for
    insertion, so its tree fields are left untouched.

    If this is an existing node and its parent has been changed,
    performs reparenting in the tree structure, defaulting to making the
    node the last child of its new parent.

    In either case, if the node's class has its ``order_insertion_by``
    tree option set, the node will be inserted or moved to the
    appropriate position to maintain ordering by the specified field.
    """
    if kwargs.get('raw'):
        return

    opts = instance._meta
    parent = getattr(instance, opts.parent_attr)
    if not instance.pk:
        if (getattr(instance, opts.left_attr) and
            getattr(instance, opts.right_attr)):
            # This node has already been set up for insertion.
            return

        if opts.order_insertion_by:
            right_sibling = _get_ordered_insertion_target(instance, parent)
            if right_sibling:
                instance.insert_at(right_sibling, 'left')
                return

        # Default insertion
        instance.insert_at(parent, position='last-child')
    else:
        # TODO Is it possible to track the original parent so we
        #      don't have to look it up again on each save after the
        #      first?
        old_parent = getattr(instance._default_manager.get(pk=instance.pk),
                             opts.parent_attr)
        if parent != old_parent:
            setattr(instance, opts.parent_attr, old_parent)
            try:
                if opts.order_insertion_by:
                    right_sibling = _get_ordered_insertion_target(instance,
                                                                  parent)
                    if right_sibling:
                        instance.move_to(right_sibling, 'left')
                        return

                # Default movement
                instance.move_to(parent, position='last-child')
            finally:
                # Make sure the instance's new parent is always
                # restored on the way out in case of errors.
                setattr(instance, opts.parent_attr, parent)

def pre_delete(instance, **kwargs):
    """
    Updates tree node edge indicators which will by affected by the
    deletion of the given model instance and any descendants it may
    have, to ensure the integrity of the tree structure is
    maintained.
    """
    opts = instance._meta
    tree_width = (getattr(instance, opts.right_attr) -
                  getattr(instance, opts.left_attr) + 1)
    target_right = getattr(instance, opts.right_attr)
    tree_id = getattr(instance, opts.tree_id_attr)
    instance._tree_manager._close_gap(tree_width, target_right, tree_id)
<|endoftext|>


<commit_before>from spack import *
import os
import re

from spack.pkg.builtin.intel import IntelInstaller, filter_pick, \
    get_all_components

class IntelParallelStudio(IntelInstaller):
    """Intel Parallel Studio.

    Note: You will have to add the download file to a
    mirror so that Spack can find it. For instructions on how to set up a
    mirror, see http://software.llnl.gov/spack/mirrors.html"""

    homepage = "https://software.intel.com/en-us/intel-parallel-studio-xe"

    # TODO: can also try the online installer (will download files on demand)
    version('composer.2016.2', '1133fb831312eb519f7da897fec223fa',
        url="file://%s/parallel_studio_xe_2016_composer_edition_update2.tgz"  # NOQA: ignore=E501
        % os.getcwd())
    version('professional.2016.2', '70be832f2d34c9bf596a5e99d5f2d832',
        url="file://%s/parallel_studio_xe_2016_update2.tgz" % os.getcwd())  # NOQA: ignore=E501
    version('cluster.2016.2', '70be832f2d34c9bf596a5e99d5f2d832',
        url="file://%s/parallel_studio_xe_2016_update2.tgz" % os.getcwd())  # NOQA: ignore=E501
    version('composer.2016.3', '3208eeabee951fc27579177b593cefe9',
        url="file://%s/parallel_studio_xe_2016_composer_edition_update3.tgz"  # NOQA: ignore=E501
        % os.getcwd())
    version('professional.2016.3', 'eda19bb0d0d19709197ede58f13443f3',
        url="file://%s/parallel_studio_xe_2016_update3.tgz" % os.getcwd())  # NOQA: ignore=E501
    version('cluster.2016.3', 'eda19bb0d0d19709197ede58f13443f3',
        url="file://%s/parallel_studio_xe_2016_update3.tgz" % os.getcwd())  # NOQA: ignore=E501

    variant('rpath', default=True, description="Add rpath to .cfg files")
    variant('all', default=False,
            description="Install all files with the requested edition")
    variant('mpi', default=True,
            description="Install the Intel MPI library and ITAC tool")
    variant('mkl', default=True, description="Install the Intel MKL library")
    variant('daal',
            default=True, description="Install the Intel DAAL libraries")
    variant('ipp', default=True, description="Install the Intel IPP libraries")
    variant('tools', default=True, description="""Install the Intel Advisor,\
VTune Amplifier, and Inspector tools""")

    provides('mpi', when='@cluster:+mpi')
    provides('mkl', when='+mkl')
    provides('daal', when='+daal')
    provides('ipp', when='+ipp')

    def install(self, spec, prefix):

        base_components = "ALL"  # when in doubt, install everything
        mpi_components = ""
        mkl_components = ""
        daal_components = ""
        ipp_components = ""

        if spec.satisfies('+all'):
            base_components = "ALL"
        else:
            all_components = get_all_components()
            regex = '(comp|openmp|intel-tbb|icc|ifort|psxe|icsxe-pset)'
            base_components = \
                filter_pick(all_components, re.compile(regex).search)
            regex = '(icsxe|imb|mpi|itac|intel-tc|clck)'
            mpi_components = \
                filter_pick(all_components, re.compile(regex).search)
            mkl_components = \
                filter_pick(all_components, re.compile('(mkl)').search)
            daal_components = \
                filter_pick(all_components, re.compile('(daal)').search)
            ipp_components = \
                filter_pick(all_components, re.compile('(ipp)').search)
            regex = '(gdb|vtune|inspector|advisor)'
            tool_components = \
                filter_pick(all_components, re.compile(regex).search)

        components = base_components
        if not spec.satisfies('+all'):
            if spec.satisfies('+mpi') and 'cluster' in str(spec.version):
                components += mpi_components
            if spec.satisfies('+mkl'):
                components += mkl_components
            if spec.satisfies('+daal'):
                components += daal_components
            if spec.satisfies('+ipp'):
                components += ipp_components
            if spec.satisfies('+tools') and (spec.satisfies('@cluster') or
               spec.satisfies('@professional')):
                components += tool_components

        self.intel_components = ';'.join(components)
        IntelInstaller.install(self, spec, prefix)

        absbindir = os.path.dirname(os.path.realpath(os.path.join(
            self.prefix.bin, "icc")))
        abslibdir = os.path.dirname(os.path.realpath(os.path.join
                                    (self.prefix.lib, "intel64", "libimf.a")))

        os.symlink(self.global_license_file, os.path.join(absbindir,
                                                          "license.lic"))
        if spec.satisfies('+tools') and (spec.satisfies('@cluster') or
                                         spec.satisfies('@professional')):
            os.mkdir(os.path.join(self.prefix, "inspector_xe/licenses"))
            os.symlink(self.global_license_file, os.path.join(
                self.prefix, "inspector_xe/licenses", "license.lic"))
            os.mkdir(os.path.join(self.prefix, "advisor_xe/licenses"))
            os.symlink(self.global_license_file, os.path.join(
                self.prefix, "advisor_xe/licenses", "license.lic"))
            os.mkdir(os.path.join(self.prefix, "vtune_amplifier_xe/licenses"))
            os.symlink(self.global_license_file, os.path.join(
                self.prefix, "vtune_amplifier_xe/licenses", "license.lic"))

        if (spec.satisfies('+all') or spec.satisfies('+mpi')) and \
                spec.satisfies('@cluster'):
                os.symlink(self.global_license_file, os.path.join(
                           self.prefix, "itac_latest", "license.lic"))

        if spec.satisfies('+rpath'):
            for compiler_command in ["icc", "icpc", "ifort"]:
                cfgfilename = os.path.join(absbindir, "%s.cfg" %
                                           compiler_command)
                with open(cfgfilename, "w") as f:
                    f.write('-Xlinker -rpath -Xlinker %s\n' % abslibdir)

        os.symlink(os.path.join(self.prefix.man, "common", "man1"),
                   os.path.join(self.prefix.man, "man1"))
<commit_msg>added newdtags variant, default to false (i.e., remove --enable-new-dtags)<commit_after>from spack import *
import os
import re

from spack.pkg.builtin.intel import IntelInstaller, filter_pick, \
    get_all_components

class IntelParallelStudio(IntelInstaller):
    """Intel Parallel Studio.

    Note: You will have to add the download file to a
    mirror so that Spack can find it. For instructions on how to set up a
    mirror, see http://software.llnl.gov/spack/mirrors.html"""

    homepage = "https://software.intel.com/en-us/intel-parallel-studio-xe"

    # TODO: can also try the online installer (will download files on demand)
    version('composer.2016.2', '1133fb831312eb519f7da897fec223fa',
        url="file://%s/parallel_studio_xe_2016_composer_edition_update2.tgz"  # NOQA: ignore=E501
        % os.getcwd())
    version('professional.2016.2', '70be832f2d34c9bf596a5e99d5f2d832',
        url="file://%s/parallel_studio_xe_2016_update2.tgz" % os.getcwd())  # NOQA: ignore=E501
    version('cluster.2016.2', '70be832f2d34c9bf596a5e99d5f2d832',
        url="file://%s/parallel_studio_xe_2016_update2.tgz" % os.getcwd())  # NOQA: ignore=E501
    version('composer.2016.3', '3208eeabee951fc27579177b593cefe9',
        url="file://%s/parallel_studio_xe_2016_composer_edition_update3.tgz"  # NOQA: ignore=E501
        % os.getcwd())
    version('professional.2016.3', 'eda19bb0d0d19709197ede58f13443f3',
        url="file://%s/parallel_studio_xe_2016_update3.tgz" % os.getcwd())  # NOQA: ignore=E501
    version('cluster.2016.3', 'eda19bb0d0d19709197ede58f13443f3',
        url="file://%s/parallel_studio_xe_2016_update3.tgz" % os.getcwd())  # NOQA: ignore=E501

    variant('rpath', default=True, description="Add rpath to .cfg files")
    variant('newdtags', default=False,
            description="Allow use of --enable-new-dtags in MPI wrappers")
    variant('all', default=False,
            description="Install all files with the requested edition")
    variant('mpi', default=True,
            description="Install the Intel MPI library and ITAC tool")
    variant('mkl', default=True, description="Install the Intel MKL library")
    variant('daal',
            default=True, description="Install the Intel DAAL libraries")
    variant('ipp', default=True, description="Install the Intel IPP libraries")
    variant('tools', default=True, description="""Install the Intel Advisor,\
VTune Amplifier, and Inspector tools""")

    provides('mpi', when='@cluster:+mpi')
    provides('mkl', when='+mkl')
    provides('daal', when='+daal')
    provides('ipp', when='+ipp')

    def install(self, spec, prefix):

        base_components = "ALL"  # when in doubt, install everything
        mpi_components = ""
        mkl_components = ""
        daal_components = ""
        ipp_components = ""

        if spec.satisfies('+all'):
            base_components = "ALL"
        else:
            all_components = get_all_components()
            regex = '(comp|openmp|intel-tbb|icc|ifort|psxe|icsxe-pset)'
            base_components = \
                filter_pick(all_components, re.compile(regex).search)
            regex = '(icsxe|imb|mpi|itac|intel-tc|clck)'
            mpi_components = \
                filter_pick(all_components, re.compile(regex).search)
            mkl_components = \
                filter_pick(all_components, re.compile('(mkl)').search)
            daal_components = \
                filter_pick(all_components, re.compile('(daal)').search)
            ipp_components = \
                filter_pick(all_components, re.compile('(ipp)').search)
            regex = '(gdb|vtune|inspector|advisor)'
            tool_components = \
                filter_pick(all_components, re.compile(regex).search)

        components = base_components
        if not spec.satisfies('+all'):
            if spec.satisfies('+mpi') and 'cluster' in str(spec.version):
                components += mpi_components
            if spec.satisfies('+mkl'):
                components += mkl_components
            if spec.satisfies('+daal'):
                components += daal_components
            if spec.satisfies('+ipp'):
                components += ipp_components
            if spec.satisfies('+tools') and (spec.satisfies('@cluster') or
               spec.satisfies('@professional')):
                components += tool_components

        self.intel_components = ';'.join(components)
        IntelInstaller.install(self, spec, prefix)

        absbindir = os.path.dirname(os.path.realpath(os.path.join(
            self.prefix.bin, "icc")))
        abslibdir = os.path.dirname(os.path.realpath(os.path.join
                                    (self.prefix.lib, "intel64", "libimf.a")))

        os.symlink(self.global_license_file, os.path.join(absbindir,
                                                          "license.lic"))
        if spec.satisfies('+tools') and (spec.satisfies('@cluster') or
                                         spec.satisfies('@professional')):
            os.mkdir(os.path.join(self.prefix, "inspector_xe/licenses"))
            os.symlink(self.global_license_file, os.path.join(
                self.prefix, "inspector_xe/licenses", "license.lic"))
            os.mkdir(os.path.join(self.prefix, "advisor_xe/licenses"))
            os.symlink(self.global_license_file, os.path.join(
                self.prefix, "advisor_xe/licenses", "license.lic"))
            os.mkdir(os.path.join(self.prefix, "vtune_amplifier_xe/licenses"))
            os.symlink(self.global_license_file, os.path.join(
                self.prefix, "vtune_amplifier_xe/licenses", "license.lic"))

        if (spec.satisfies('+all') or spec.satisfies('+mpi')) and \
                spec.satisfies('@cluster'):
                os.symlink(self.global_license_file, os.path.join(
                           self.prefix, "itac_latest", "license.lic"))
                if spec.satisfies('~newdtags'):
                    wrappers = ["mpif77", "mpif77", "mpif90", "mpif90",
                                "mpigcc", "mpigcc", "mpigxx", "mpigxx",
                                "mpiicc", "mpiicc", "mpiicpc", "mpiicpc",
                                "mpiifort", "mpiifort"]
                    wrapper_paths = []
                    for root, dirs, files in os.walk(spec.prefix):
                        for name in files:
                            if name in wrappers:
                                wrapper_paths.append(os.path.join(spec.prefix,
                                                                  root, name))
                    for wrapper in wrapper_paths:
                        filter_file(r'-Xlinker --enable-new-dtags', r' ',
                                    wrapper)

        if spec.satisfies('+rpath'):
            for compiler_command in ["icc", "icpc", "ifort"]:
                cfgfilename = os.path.join(absbindir, "%s.cfg" %
                                           compiler_command)
                with open(cfgfilename, "w") as f:
                    f.write('-Xlinker -rpath -Xlinker %s\n' % abslibdir)

        os.symlink(os.path.join(self.prefix.man, "common", "man1"),
                   os.path.join(self.prefix.man, "man1"))
<|endoftext|>