Completed
Pull Request — master (#666)
by Michael
01:01
created

cookiecutter.validate_extra_context()   A

Complexity

Conditions 3

Size

Total Lines 9

Duplication

Lines 0
Ratio 0 %
Metric Value
cc 3
dl 0
loc 9
rs 9.6666
1
#!/usr/bin/env python
2
# -*- coding: utf-8 -*-
3
4
"""
5
cookiecutter.cli
6
-----------------
7
8
Main `cookiecutter` CLI.
9
"""
10
11
import os
12
import sys
13
import logging
14
import json
15
16
import click
17
18
from cookiecutter import __version__
19
from cookiecutter.config import USER_CONFIG_PATH
20
from cookiecutter.main import cookiecutter
21
from cookiecutter.exceptions import (
22
    OutputDirExistsException,
23
    InvalidModeException,
24
    FailedHookException,
25
    UndefinedVariableInTemplate,
26
    UnknownExtension,
27
    RepositoryNotFound
28
)
29
30
logger = logging.getLogger(__name__)
31
32
33
def version_msg():
34
    python_version = sys.version[:3]
35
    location = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
36
    message = u'Cookiecutter %(version)s from {} (Python {})'
37
    return message.format(location, python_version)
38
39
40
def validate_extra_context(ctx, param, value):
41
    for s in value:
42
        if '=' not in s:
43
            raise click.BadParameter(
44
                "EXTRA_CONTEXT should contain items of form key=value; "
45
                "'%s' doesn't match that form"
46
                % (s,))
47
48
    return value
49
50
51
@click.command(context_settings=dict(help_option_names=[u'-h', u'--help']))
52
@click.version_option(__version__, u'-V', u'--version', message=version_msg())
53
@click.argument(u'template')
54
@click.argument(u'extra_context', nargs=-1, callback=validate_extra_context)
55
@click.option(
56
    u'--no-input', is_flag=True,
57
    help=u'Do not prompt for parameters and only use cookiecutter.json '
58
         u'file content',
59
)
60
@click.option(
61
    u'-c', u'--checkout',
62
    help=u'branch, tag or commit to checkout after git clone',
63
)
64
@click.option(
65
    '-v', '--verbose',
66
    is_flag=True, help='Print debug information', default=False
67
)
68
@click.option(
69
    u'--replay', is_flag=True,
70
    help=u'Do not prompt for parameters and only use information entered '
71
         u'previously',
72
)
73
@click.option(
74
    u'-f', u'--overwrite-if-exists', is_flag=True,
75
    help=u'Overwrite the contents of the output directory if it already exists'
76
)
77
@click.option(
78
    u'-o', u'--output-dir', default='.', type=click.Path(),
79
    help=u'Where to output the generated project dir into'
80
)
81
@click.option(
82
    u'--config-file', type=click.Path(), default=USER_CONFIG_PATH,
83
    help=u'User configuration file'
84
)
85
@click.option(
86
    u'--default-config', is_flag=True,
87
    help=u'Do not load a config file. Use the defaults instead'
88
)
89
def main(template, extra_context, no_input, checkout, verbose, replay,
90
         overwrite_if_exists, output_dir, config_file, default_config):
91
    """Create a project from a Cookiecutter project template (TEMPLATE)."""
92
    if verbose:
93
        logging.basicConfig(
94
            format=u'%(levelname)s %(filename)s: %(message)s',
95
            level=logging.DEBUG
96
        )
97
    else:
98
        # Log info and above to console
99
        logging.basicConfig(
100
            format=u'%(levelname)s: %(message)s',
101
            level=logging.INFO
102
        )
103
104
    if extra_context:
105
        # Convert tuple -- e.g.: (u'program_name=foobar', u'startsecs=66')
106
        # to dict -- e.g.: {'program_name': 'foobar', 'startsecs': '66'}
107
        extra_context = dict(s.split('=', 1) for s in extra_context)
108
    else:
109
        extra_context = None
110
111
    try:
112
        # If you _need_ to support a local template in a directory
113
        # called 'help', use a qualified path to the directory.
114
        if template == u'help':
115
            click.echo(click.get_current_context().get_help())
116
            sys.exit(0)
117
118
        user_config = None if default_config else config_file
119
120
        cookiecutter(
121
            template, checkout, no_input,
122
            extra_context=extra_context,
123
            replay=replay,
124
            overwrite_if_exists=overwrite_if_exists,
125
            output_dir=output_dir,
126
            config_file=user_config
127
        )
128
    except (OutputDirExistsException,
129
            InvalidModeException,
130
            FailedHookException,
131
            UnknownExtension,
132
            RepositoryNotFound) as e:
133
        click.echo(e)
134
        sys.exit(1)
135
    except UndefinedVariableInTemplate as undefined_err:
136
        click.echo('{}'.format(undefined_err.message))
137
        click.echo('Error message: {}'.format(undefined_err.error.message))
138
139
        context_str = json.dumps(
140
            undefined_err.context,
141
            indent=4,
142
            sort_keys=True
143
        )
144
        click.echo('Context: {}'.format(context_str))
145
        sys.exit(1)
146
147
148
if __name__ == "__main__":
149
    main()
150