Beispiel #1
0
def test_run_json_dump(
    monkeypatch,
    mocker,
    mock_ensure_success,
    mock_user_config,
    template_name,
    context,
    replay_test_dir,
    replay_file,
):
    """Test that replay.dump runs json.dump under the hood and that the context \
    is correctly written to the expected file in the replay_dir."""
    test_dir = os.path.join(os.path.abspath(os.path.dirname(__file__)), '..')
    monkeypatch.chdir(test_dir)

    spy_get_replay_file = mocker.spy(replay, 'get_file_name')

    mock_json_dump = mocker.patch('json.dump', side_effect=json.dump)

    replay.dump(replay_test_dir, template_name, context)

    assert not mock_user_config.called
    mock_ensure_success.assert_called_once_with(replay_test_dir)
    spy_get_replay_file.assert_called_once_with(replay_test_dir, template_name)

    assert mock_json_dump.call_count == 1
    (dumped_context, outfile_handler), kwargs = mock_json_dump.call_args
    assert outfile_handler.name == replay_file
    assert dumped_context == context
Beispiel #2
0
def test_ioerror_if_replay_dir_creation_fails(mock_ensure_failure, mock_user_config, replay_test_dir):
    """Test that replay.dump raises when the replay_dir cannot be created."""

    with pytest.raises(IOError):
        replay.dump("foo", {"cookiecutter": {"hello": "world"}})

    mock_ensure_failure.assert_called_once_with(replay_test_dir)
Beispiel #3
0
def test_ioerror_if_replay_dir_creation_fails(mock_ensure_failure,
                                              mock_user_config,
                                              replay_test_dir):
    """Test that replay.dump raises when the replay_dir cannot be created."""

    with pytest.raises(IOError):
        replay.dump('foo', {'cookiecutter': {'hello': 'world'}})

    mock_ensure_failure.assert_called_once_with(replay_test_dir)
Beispiel #4
0
def test_ioerror_if_replay_dir_creation_fails(mock_ensure_failure,
                                              replay_test_dir):
    """Test that replay.dump raises when the replay_dir cannot be created."""
    with pytest.raises(IOError):
        replay.dump(replay_test_dir, "foo",
                    {"cookiecutter": {
                        "hello": "world"
                    }})

    mock_ensure_failure.assert_called_once_with(replay_test_dir)
Beispiel #5
0
def test_ioerror_if_replay_dir_creation_fails(
        mock_ensure_failure, replay_test_dir):
    """Test that replay.dump raises when the replay_dir cannot be created."""

    with pytest.raises(IOError):
        replay.dump(
            replay_test_dir,
            'foo', {'cookiecutter': {'hello': 'world'}}
        )

    mock_ensure_failure.assert_called_once_with(replay_test_dir)
Beispiel #6
0
def test_run_json_dump(mocker, mock_ensure_success, mock_user_config,
                       template_name, context, replay_test_dir, replay_file):
    """Test that replay.dump runs json.dump under the hood and that the context
    is correctly written to the expected file in the replay_dir.
    """
    spy_get_replay_file = mocker.spy(replay, 'get_file_name')

    mock_json_dump = mocker.patch('json.dump', side_effect=json.dump)

    replay.dump(replay_test_dir, template_name, context)

    assert not mock_user_config.called
    mock_ensure_success.assert_called_once_with(replay_test_dir)
    spy_get_replay_file.assert_called_once_with(replay_test_dir, template_name)

    assert mock_json_dump.call_count == 1
    (dumped_context, outfile_handler), kwargs = mock_json_dump.call_args
    assert outfile_handler.name == replay_file
    assert dumped_context == context
Beispiel #7
0
def test_type_error_if_not_dict_context(replay_test_dir, template_name):
    """Test that replay.dump raises if the context is not of type dict."""
    with pytest.raises(TypeError):
        replay.dump(replay_test_dir, template_name, 'not_a_dict')
Beispiel #8
0
def test_type_error_if_no_template_name(replay_test_dir, context):
    """Test that replay.dump raises if the template_name is not a valid str."""
    with pytest.raises(TypeError):
        replay.dump(replay_test_dir, None, context)
Beispiel #9
0
def test_value_error_if_key_missing_in_context(replay_test_dir, template_name):
    """Test that replay.dump raises if the context does not contain a key \
    named 'cookiecutter'."""
    with pytest.raises(ValueError):
        replay.dump(replay_test_dir, template_name, {'foo': 'bar'})
Beispiel #10
0
def cookiecutter(
    template,
    checkout=None,
    no_input=False,
    extra_context=None,
    replay=False,
    overwrite_if_exists=False,
    output_dir='.',
    config_file=None,
    default_config=False,
    password=None,
    directory=None,
    skip_if_file_exists=False,
):
    """
    Run Cookiecutter just as if using it from the command line.

    :param template: A directory containing a project template directory,
        or a URL to a git repository.
    :param checkout: The branch, tag or commit ID to checkout after clone.
    :param no_input: Prompt the user at command line for manual configuration?
    :param extra_context: A dictionary of context that overrides default
        and user configuration.
    :param overwrite_if_exists: Overwrite the contents of output directory
        if it exists
    :param output_dir: Where to output the generated project dir into.
    :param config_file: User configuration file path.
    :param default_config: Use default values rather than a config file.
    :param password: The password to use when extracting the repository.
    :param directory: Relative path to a cookiecutter template in a repository.
    """
    if replay and ((no_input is not False) or (extra_context is not None)):
        err_msg = ("You can not use both replay and no_input or extra_context "
                   "at the same time.")
        raise InvalidModeException(err_msg)

    config_dict = get_user_config(
        config_file=config_file,
        default_config=default_config,
    )

    repo_dir, cleanup = determine_repo_dir(
        template=template,
        abbreviations=config_dict['abbreviations'],
        clone_to_dir=config_dict['cookiecutters_dir'],
        checkout=checkout,
        no_input=no_input,
        password=password,
        directory=directory,
    )

    template_name = os.path.basename(os.path.abspath(repo_dir))

    if replay:
        context = load(config_dict['replay_dir'], template_name)
    else:
        context_file = os.path.join(repo_dir, 'cookiecutter.json')
        logger.debug('context_file is %s', context_file)

        context = generate_context(
            context_file=context_file,
            default_context=config_dict['default_context'],
            extra_context=extra_context,
        )

        # prompt the user to manually configure at the command line.
        # except when 'no-input' flag is set
        context['cookiecutter'] = prompt_for_config(context, no_input)

        # include template dir or url in the context dict
        context['cookiecutter']['_template'] = template

        dump(config_dict['replay_dir'], template_name, context)

    # Create project from local context and project template.
    result = generate_files(
        repo_dir=repo_dir,
        context=context,
        overwrite_if_exists=overwrite_if_exists,
        skip_if_file_exists=skip_if_file_exists,
        output_dir=output_dir,
    )

    # Cleanup (if required)
    if cleanup:
        rmtree(repo_dir)

    return result
Beispiel #11
0
def cookiecutter(
    template='.',
    checkout=None,
    no_input=False,
    context_file=None,
    context_key=None,
    existing_context=None,
    extra_context=None,
    replay=None,
    overwrite_if_exists=False,
    output_dir='.',
    config_file=None,
    default_config=False,
    password=None,
    directory=None,
    skip_if_file_exists=False,
    accept_hooks=True,
):
    """
    Run Cookiecutter just as if using it from the command line.

    :param template: A directory containing a project template directory,
        or a URL to a git repository.
    :param checkout: The branch, tag or commit ID to checkout after clone.
    :param no_input: Prompt the user at command line for manual configuration?
    :param context_file: The file to load to set the context, ie list of prompts.
        Defaults to nuki.yaml, nukikata.yml, then cookiecutter.json.
    :param context_key: The key to all the context under - defaults to the name
        of the context file minus the file extension.
    :param existing_context: An additional dictionary to use in rendering
        additional prompts.
    :param extra_context: A dictionary of context that overrides default
        and user configuration.
    :param replay: Do not prompt for input, instead read from saved json. If
        ``True`` read from the ``replay_dir``.
        if it exists
    :param output_dir: Where to output the generated project dir into.
    :param config_file: User configuration file path.
    :param default_config: Use default values rather than a config file.
    :param password: The password to use when extracting the repository.
    :param directory: Relative path to a cookiecutter template in a repository.
    :param accept_hooks: Accept pre and post hooks if set to `True`.

    :return Dictionary of output
    """
    global calling_directory  # Preserve this path for special variable usage
    calling_directory = os.getcwd()

    if replay and ((no_input is not False) or (extra_context is not None)):
        err_msg = ("You can not use both replay and no_input or extra_context "
                   "at the same time.")
        raise InvalidModeException(err_msg)

    config_dict = get_user_config(
        config_file=config_file,
        default_config=default_config,
    )

    repo_dir, context_file, cleanup = determine_repo_dir(
        template=template,
        abbreviations=config_dict['abbreviations'],
        clone_to_dir=config_dict['cookiecutters_dir'],
        checkout=checkout,
        no_input=no_input,
        context_file=context_file,
        password=password,
        directory=directory,
    )

    template_name = os.path.basename(os.path.abspath(repo_dir))
    if not context_key:
        context_key = os.path.basename(context_file).split('.')[0]

    if replay:
        if isinstance(replay, bool):
            context = load(config_dict['replay_dir'], template_name,
                           context_key)
        else:
            path, template_name = os.path.split(os.path.splitext(replay)[0])
            context = load(path, template_name, context_key)

    else:
        context_file_path = os.path.join(repo_dir, context_file)
        logger.debug('context_file is %s', context_file_path)

        context = generate_context(
            context_file=context_file_path,
            default_context=config_dict['default_context'],
            extra_context=extra_context,
            context_key=context_key,
        )

        # include template dir or url in the context dict
        context[context_key]['_template'] = repo_dir
        # include output+dir in the context dict
        context[context_key]['_output_dir'] = os.path.abspath(output_dir)

        # prompt the user to manually configure at the command line.pyth
        # except when 'no-input' flag is set
        context[context_key] = prompt_for_config(context, no_input,
                                                 context_key, existing_context)

        dump(config_dict['replay_dir'], template_name, context, context_key)

    # Create project from local context and project template.
    result = generate_files(
        repo_dir=repo_dir,
        context=context,
        overwrite_if_exists=overwrite_if_exists,
        skip_if_file_exists=skip_if_file_exists,
        output_dir=output_dir,
        context_key=context_key,
        accept_hooks=accept_hooks,
    )

    if result:
        logger.debug('Resulting project directory created at %s', result)
    else:
        logger.debug('No project directory was created')

    # Cleanup (if required)
    if cleanup:
        rmtree(repo_dir)

    if isinstance(context, OrderedDict):
        context = json.loads(json.dumps(context))

    return context[context_key]
Beispiel #12
0
def test_value_error_if_key_missing_in_context(replay_test_dir, template_name):
    """Test that replay.dump raises if the context does not contain a key
    named 'cookiecutter'.
    """
    with pytest.raises(ValueError):
        replay.dump(replay_test_dir, template_name, {'foo': 'bar'})
Beispiel #13
0
def test_type_error_if_not_dict_context(replay_test_dir, template_name):
    """Test that replay.dump raises if the context is not of type dict."""
    with pytest.raises(TypeError):
        replay.dump(replay_test_dir, template_name, 'not_a_dict')
Beispiel #14
0
def test_type_error_if_no_template_name(replay_test_dir, context):
    """Test that replay.dump raises if the template_name is not a valid str."""
    with pytest.raises(TypeError):
        replay.dump(replay_test_dir, None, context)