Exemple #1
0
    def test_uuid_reproducibility(self):
        from dallinger.experiment import Experiment
        exp = Experiment()
        random.seed(1)
        exp_uuid1 = exp.make_uuid()
        exp_uuid2 = exp.make_uuid()
        random.seed(1)
        exp_uuid3 = exp.make_uuid()

        assert exp_uuid1 != exp_uuid2
        assert exp_uuid1 == exp_uuid3
Exemple #2
0
def setup_experiment(log,
                     debug=True,
                     verbose=False,
                     app=None,
                     exp_config=None):
    """Checks the experiment's python dependencies, then prepares a temp directory
    with files merged from the custom experiment and Dallinger.

    The resulting directory includes all the files necessary to deploy to
    Heroku.
    """

    # Verify that the Postgres server is running.
    try:
        db.check_connection()
    except Exception:
        log("There was a problem connecting to the Postgres database!")
        raise

    # Check that the demo-specific requirements are satisfied.
    try:
        with open("requirements.txt", "r") as f:
            dependencies = [r for r in f.readlines() if r[:3] != "-e "]
    except (OSError, IOError):
        dependencies = []
    pkg_resources.require(dependencies)

    # Generate a unique id for this experiment.
    from dallinger.experiment import Experiment

    generated_uid = public_id = Experiment.make_uuid(app)

    # If the user provided an app name, use it everywhere that's user-facing.
    if app:
        public_id = str(app)

    log("Experiment id is " + public_id + "")

    # Load and update the config
    config = get_config()
    if not config.ready:
        config.load()  #
    if exp_config:
        config.extend(exp_config)
    config.extend({"id": six.text_type(generated_uid)})

    temp_dir = assemble_experiment_temp_dir(config)
    log("Deployment temp directory: {}".format(temp_dir), chevrons=False)

    # Zip up the temporary directory and place it in the cwd.
    if not debug:
        log("Freezing the experiment package...")
        shutil.make_archive(
            os.path.join(os.getcwd(), "snapshots", public_id + "-code"), "zip",
            temp_dir)

    return (public_id, temp_dir)
Exemple #3
0
def bootstrap_development_session(exp_config, experiment_path, log):
    check_local_db_connection(log)
    check_experiment_dependencies(Path(experiment_path) / "requirements.txt")

    # Generate a unique id for this experiment.
    from dallinger.experiment import Experiment

    experiment_uid = Experiment.make_uuid()
    log("Experiment UID: {}".format(experiment_uid))

    # Load and update the config
    config = get_config()
    if not config.ready:
        config.load()  #
    config.extend(exp_config)
    config.extend({
        "id": str(experiment_uid),
        "heroku_app_id_root": str(experiment_uid),
    })
    if not config.get("dashboard_password", None):
        config.set("dashboard_password",
                   fake.password(length=20, special_chars=False))

    develop_source_path = Path(dallinger_package_path()) / "dev_server"
    dst = Path(experiment_path) / "develop"
    log("Wiping develop directory and re-writing it...")
    ensure_directory(dst)
    expunge_directory(dst)
    collate_experiment_files(config,
                             experiment_path=experiment_path,
                             destination=dst,
                             copy_func=symlink_file)

    copy_file(develop_source_path / "app.py", dst / "app.py")
    copy_file(develop_source_path / "run.sh", dst / "run.sh")
    (dst / "run.sh").chmod(0o744)  # Make run script executable

    config.write(directory=dst)

    return (experiment_uid, dst)
Exemple #4
0
    def test_uuid(self):
        from dallinger.experiment import Experiment

        exp_uuid = Experiment.make_uuid()
        assert isinstance(UUID(exp_uuid, version=4), UUID)
Exemple #5
0
def uuid():
    """Print a new UUID"""
    from dallinger.experiment import Experiment
    click.echo(Experiment.make_uuid())
Exemple #6
0
def setup_experiment(debug=True, verbose=False, app=None, exp_config=None):
    """Check the app and, if compatible with Dallinger, freeze its state."""
    log(header, chevrons=False)

    # Verify that the Postgres server is running.
    try:
        psycopg2.connect(database="x", user="******", password="******")
    except psycopg2.OperationalError as e:
        if "could not connect to server" in str(e):
            raise RuntimeError("The Postgres server isn't running.")

    # Load configuration.
    config = get_config()
    if not config.ready:
        config.load()

    # Check that the demo-specific requirements are satisfied.
    try:
        with open("requirements.txt", "r") as f:
            dependencies = [r for r in f.readlines() if r[:3] != "-e "]
    except (OSError, IOError):
        dependencies = []

    pkg_resources.require(dependencies)

    # Generate a unique id for this experiment.
    from dallinger.experiment import Experiment
    generated_uid = public_id = Experiment.make_uuid()

    # If the user provided an app name, use it everywhere that's user-facing.
    if app:
        public_id = str(app)

    log("Experiment id is " + public_id + "")

    # Copy this directory into a temporary folder, ignoring .git
    dst = os.path.join(tempfile.mkdtemp(), public_id)
    to_ignore = shutil.ignore_patterns(os.path.join(".git", "*"), "*.db",
                                       "snapshots", "data", "server.log")
    shutil.copytree(os.getcwd(), dst, ignore=to_ignore)

    click.echo(dst)

    # Save the experiment id
    with open(os.path.join(dst, "experiment_id.txt"), "w") as file:
        file.write(generated_uid)

    # Change directory to the temporary folder.
    cwd = os.getcwd()
    os.chdir(dst)

    # Write the custom config
    if exp_config:
        config.extend(exp_config)

    config.extend({'id': unicode(generated_uid)})

    config.write(filter_sensitive=True)

    # Zip up the temporary directory and place it in the cwd.
    if not debug:
        log("Freezing the experiment package...")
        shutil.make_archive(
            os.path.join(cwd, "snapshots", public_id + "-code"), "zip", dst)

    # Check directories.
    ensure_directory(os.path.join("static", "scripts"))
    ensure_directory(os.path.join("templates", "default"))
    ensure_directory(os.path.join("static", "css"))

    # Rename experiment.py for backwards compatibility.
    os.rename(os.path.join(dst, "experiment.py"),
              os.path.join(dst, "dallinger_experiment.py"))

    # Get dallinger package location.
    from pkg_resources import get_distribution
    dist = get_distribution('dallinger')
    src_base = os.path.join(dist.location, dist.project_name)

    heroku_files = [
        "Procfile",
        "launch.py",
        "worker.py",
        "clock.py",
        "runtime.txt",
    ]

    for filename in heroku_files:
        src = os.path.join(src_base, "heroku", filename)
        shutil.copy(src, os.path.join(dst, filename))

    clock_on = config.get('clock_on', False)

    # If the clock process has been disabled, overwrite the Procfile.
    if not clock_on:
        src = os.path.join(src_base, "heroku", "Procfile_no_clock")
        shutil.copy(src, os.path.join(dst, "Procfile"))

    frontend_files = [
        os.path.join("static", "css", "dallinger.css"),
        os.path.join("static", "scripts", "dallinger.js"),
        os.path.join("static", "scripts", "dallinger2.js"),
        os.path.join("static", "scripts", "reqwest.min.js"),
        os.path.join("static", "scripts", "require.js"),
        os.path.join("static", "scripts", "reconnecting-websocket.js"),
        os.path.join("static", "scripts", "spin.min.js"),
        os.path.join("static", "scripts", "tracker.js"),
        os.path.join("templates", "error.html"),
        os.path.join("templates", "launch.html"),
        os.path.join("templates", "complete.html"),
        os.path.join("templates", "questionnaire.html"),
        os.path.join("templates", "thanks.html"),
        os.path.join("templates", "waiting.html"),
        os.path.join("static", "robots.txt")
    ]
    frontend_dirs = [
        os.path.join("templates", "base"),
    ]

    for filename in frontend_files:
        src = os.path.join(src_base, "frontend", filename)
        dst_filepath = os.path.join(dst, filename)
        if not os.path.exists(dst_filepath):
            shutil.copy(src, dst_filepath)
    for filename in frontend_dirs:
        src = os.path.join(src_base, "frontend", filename)
        dst_filepath = os.path.join(dst, filename)
        if not os.path.exists(dst_filepath):
            shutil.copytree(src, dst_filepath)

    time.sleep(0.25)

    os.chdir(cwd)

    return (public_id, dst)
def setup_experiment(log,
                     debug=True,
                     verbose=False,
                     app=None,
                     exp_config=None):
    """Checks the experiment's python dependencies, then prepares a temp directory
    with files merged from the custom experiment and Dallinger.

    The resulting directory includes all the files necessary to deploy to
    Heroku.
    """

    # Verify that the Postgres server is running.
    try:
        db.check_connection()
    except Exception:
        log("There was a problem connecting to the Postgres database!")
        raise

    # Check that the demo-specific requirements are satisfied.
    try:
        with open("requirements.txt", "r") as f:
            dependencies = [r for r in f.readlines() if r[:3] != "-e "]
    except (OSError, IOError):
        dependencies = []
    pkg_resources.require(dependencies)

    # Generate a unique id for this experiment.
    from dallinger.experiment import Experiment

    experiment_uid = heroku_app_id = Experiment.make_uuid(app)
    log("Experiment UID: {}".format(experiment_uid))

    # Load and update the config
    config = get_config()
    if not config.ready:
        config.load()  #
    if exp_config:
        config.extend(exp_config)

    # If the user provided an app name, store it. We'll use it as the basis for
    # the Heroku app ID. We still have a fair amount of ambiguity around what
    # this value actually represents (it's not used as _only_ the Heroku app ID).
    if app:
        heroku_app_id = str(app)
        log("Using custom Heroku ID root: {}".format(heroku_app_id))

    config.extend({
        "id": six.text_type(experiment_uid),
        "heroku_app_id_root": six.text_type(heroku_app_id),
    })

    if not config.get("dashboard_password", None):
        config.set("dashboard_password",
                   fake.password(length=20, special_chars=False))

    temp_dir = assemble_experiment_temp_dir(config)
    log("Deployment temp directory: {}".format(temp_dir), chevrons=False)

    # Zip up the temporary directory and place it in the cwd.
    if not debug:
        log("Freezing the experiment package...")
        shutil.make_archive(
            os.path.join(os.getcwd(), "snapshots", heroku_app_id + "-code"),
            "zip",
            temp_dir,
        )

    return (heroku_app_id, temp_dir)
Exemple #8
0
def setup_experiment(log,
                     debug=True,
                     verbose=False,
                     app=None,
                     exp_config=None,
                     local_checks=True):
    """Checks the experiment's python dependencies, then prepares a temp directory
    with files merged from the custom experiment and Dallinger.

    The resulting directory includes all the files necessary to deploy to
    Heroku.
    """
    if local_checks:
        check_local_db_connection(log)
        check_experiment_dependencies(Path(os.getcwd()) / "requirements.txt")

    ensure_constraints_file_presence(os.getcwd())
    # Generate a unique id for this experiment.
    from dallinger.experiment import Experiment

    experiment_uid = heroku_app_id = Experiment.make_uuid(app)
    log("Experiment UID: {}".format(experiment_uid))

    # Load and update the config
    config = get_config()
    if not config.ready:
        config.load()  #
    if exp_config:
        config.extend(exp_config)

    # If the user provided an app name, store it. We'll use it as the basis for
    # the Heroku app ID. We still have a fair amount of ambiguity around what
    # this value actually represents (it's not used as _only_ the Heroku app ID).
    if app:
        heroku_app_id = str(app)
        log("Using custom Heroku ID root: {}".format(heroku_app_id))

    config.extend({
        "id": str(experiment_uid),
        "heroku_app_id_root": str(heroku_app_id),
    })

    if not config.get("dashboard_password", None):
        config.set("dashboard_password",
                   fake.password(length=20, special_chars=False))

    temp_dir = assemble_experiment_temp_dir(log,
                                            config,
                                            for_remote=not local_checks)
    log("Deployment temp directory: {}".format(temp_dir), chevrons=False)

    # Zip up the temporary directory and place it in the cwd.
    if not debug:
        log("Freezing the experiment package...")
        shutil.make_archive(
            os.path.join(os.getcwd(), "snapshots", heroku_app_id + "-code"),
            "zip",
            temp_dir,
        )

    return (heroku_app_id, temp_dir)