def test_undefined_variable(context): """Verify `prompt.prompt_for_config` raises correct error.""" with pytest.raises(exceptions.UndefinedVariableInTemplate) as err: prompt.prompt_for_config(context, no_input=True) error = err.value assert error.message == "Unable to render variable 'foo'" assert error.context == context
def test_undefined_variable_in_cookiecutter_dict_with_choices(): context = {"cookiecutter": {"hello": "world", "foo": ["123", "{{cookiecutter.nope}}", "456"]}} with pytest.raises(exceptions.UndefinedVariableInTemplate) as err: prompt.prompt_for_config(context, no_input=True) error = err.value assert error.message == "Unable to render variable 'foo'" assert error.context == context
def test_undefined_variable_in_cookiecutter_dict_with_choices(): context = { 'cookiecutter': { 'hello': 'world', 'foo': ['123', '{{cookiecutter.nope}}', '456'] } } with pytest.raises(exceptions.UndefinedVariableInTemplate) as err: prompt.prompt_for_config(context, no_input=True) error = err.value assert error.message == "Unable to render variable 'foo'" assert error.context == context
def test_undefined_variable_in_cookiecutter_dict_with_choices(): context = { "cookiecutter": { "hello": "world", "foo": ["123", "{{cookiecutter.nope}}", "456"], } } with pytest.raises(exceptions.UndefinedVariableInTemplate) as err: prompt.prompt_for_config(context, no_input=True) error = err.value assert error.message == "Unable to render variable 'foo'" assert error.context == context
def test_undefined_variable_in_cookiecutter_dict_with_key_value(): context = { 'cookiecutter': { 'hello': 'world', 'foo': {'key': '{{cookiecutter.nope}}'} } } with pytest.raises(exceptions.UndefinedVariableInTemplate) as err: prompt.prompt_for_config(context, no_input=True) error = err.value assert error.message == "Unable to render variable 'foo'" assert error.context == context
def test_should_render_choices(self, mocker): read_choice = mocker.patch("cookiecutter.prompt.read_user_choice") read_choice.return_value = u"anewproject" read_variable = mocker.patch("cookiecutter.prompt.read_user_variable") read_variable.return_value = u"A New Project" RENDERED_CHOICES = [u"foo", u"anewproject", u"bar"] CONTEXT = { "cookiecutter": OrderedDict([ ("project_name", u"A New Project"), ( "pkg_name", [ u"foo", u'{{ cookiecutter.project_name|lower|replace(" ", "") }}', u"bar", ], ), ]) } EXP_COOKIECUTTER_DICT = { "project_name": u"A New Project", "pkg_name": u"anewproject", } cookiecutter_dict = prompt.prompt_for_config(CONTEXT) read_variable.assert_called_once_with("project_name", u"A New Project") read_choice.assert_called_once_with("pkg_name", RENDERED_CHOICES) assert cookiecutter_dict == EXP_COOKIECUTTER_DICT
def test_should_render_deep_dict(self): context = { 'cookiecutter': { 'project_name': "Slartibartfast", 'details': { "key": "value", "integer_key": 37, "other_name": '{{cookiecutter.project_name}}', "dict_key": { "deep_key": "deep_value", "deep_integer": 42, "deep_other_name": '{{cookiecutter.project_name}}', "deep_list": [ "deep value 1", "{{cookiecutter.project_name}}", "deep value 3", ] }, "list_key": [ "value 1", "{{cookiecutter.project_name}}", "value 3", ] } } } cookiecutter_dict = prompt.prompt_for_config(context, no_input=True) assert cookiecutter_dict == { 'project_name': "Slartibartfast", 'details': { "key": "value", "integer_key": "37", "other_name": "Slartibartfast", "dict_key": { "deep_key": "deep_value", "deep_integer": "42", "deep_other_name": "Slartibartfast", "deep_list": [ "deep value 1", "Slartibartfast", "deep value 3", ] }, "list_key": [ "value 1", "Slartibartfast", "value 3", ] } }
def test_prompt_for_config_empty_dict(self, monkeypatch): monkeypatch.setattr('cookiecutter.prompt.read_user_dict', lambda var, default: {}) context = {'cookiecutter': {'details': {}}} cookiecutter_dict = prompt.prompt_for_config(context) assert cookiecutter_dict == {'details': {}}
def test_should_render_choices(self, mocker): read_choice = mocker.patch('cookiecutter.prompt.read_user_choice') read_choice.return_value = u'anewproject' read_variable = mocker.patch('cookiecutter.prompt.read_user_variable') read_variable.return_value = u'A New Project' RENDERED_CHOICES = [ u'foo', u'anewproject', u'bar' ] CONTEXT = {'cookiecutter': OrderedDict([ ( 'project_name', u'A New Project' ), ( 'pkg_name', [ u'foo', u'{{ cookiecutter.project_name|lower|replace(" ", "") }}', u'bar' ] ) ])} EXP_COOKIECUTTER_DICT = { 'project_name': u'A New Project', 'pkg_name': u'anewproject' } cookiecutter_dict = prompt.prompt_for_config(CONTEXT) read_variable.assert_called_once_with('project_name', u'A New Project') read_choice.assert_called_once_with('pkg_name', RENDERED_CHOICES) assert cookiecutter_dict == EXP_COOKIECUTTER_DICT
def get_cookiecutter_config(template, default_config=None, version=None): """Obtains the configuration used for cookiecutter templating Args: template: Path to the template default_config (dict, optional): The default configuration version (str, optional): The git SHA or branch to use when checking out template. Defaults to latest version Returns: tuple: The cookiecutter repo directory and the config dict """ default_config = default_config or {} config_dict = cc_config.get_user_config() repo_dir, _ = cc_repository.determine_repo_dir( template=template, abbreviations=config_dict['abbreviations'], clone_to_dir=config_dict['cookiecutters_dir'], checkout=version, no_input=True) context_file = os.path.join(repo_dir, 'cookiecutter.json') context = cc_generate.generate_context( context_file=context_file, default_context={ **config_dict['default_context'], **default_config }) return repo_dir, cc_prompt.prompt_for_config(context)
def test_should_render_choices(self, mocker): """Verify Jinja2 templating engine works inside choices variables.""" read_user_choice = mocker.patch('cookiecutter.prompt.read_user_choice') read_user_choice.return_value = 'anewproject' read_user_variable = mocker.patch('cookiecutter.prompt.read_user_variable') read_user_variable.return_value = 'A New Project' rendered_choices = ['foo', 'anewproject', 'bar'] context = { 'cookiecutter': OrderedDict( [ ('project_name', 'A New Project'), ( 'pkg_name', [ 'foo', '{{ cookiecutter.project_name|lower|replace(" ", "") }}', 'bar', ], ), ] ) } expected = { 'project_name': 'A New Project', 'pkg_name': 'anewproject', } cookiecutter_dict = prompt.prompt_for_config(context) read_user_variable.assert_called_once_with('project_name', 'A New Project') read_user_choice.assert_called_once_with('pkg_name', rendered_choices) assert cookiecutter_dict == expected
def test_prompt_for_config_unicode(self, monkeypatch): monkeypatch.setattr('cookiecutter.prompt.read_user_variable', lambda var, default: u'Pizzä ïs Gööd') context = {'cookiecutter': {'full_name': 'Your Name'}} cookiecutter_dict = prompt.prompt_for_config(context) assert cookiecutter_dict == {'full_name': u'Pizzä ïs Gööd'}
def generate_cookiecutter_context( template_git_url: str, cookiecutter_template_dir: Path, config_file: Optional[Path] = None, default_config: bool = False, extra_context: Optional[Dict[str, Any]] = None, no_input: bool = False, ) -> CookiecutterContext: _validate_cookiecutter(cookiecutter_template_dir) context_file = cookiecutter_template_dir / "cookiecutter.json" config_dict = get_user_config( config_file=str(config_file) if config_file else None, default_config=default_config) 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) context["cookiecutter"]["_template"] = template_git_url return context
def test_should_render_private_variables_with_two_underscores(self): """Test rendering of private variables with two underscores. There are three cases: 1. Variables beginning with a single underscore are private and not rendered. 2. Variables beginning with a double underscore are private and are rendered. 3. Variables beginning with anything other than underscores are not private and are rendered. """ context = { 'cookiecutter': OrderedDict([ ('foo', 'Hello world'), ('bar', 123), ('rendered_foo', u'{{ cookiecutter.foo|lower }}'), ('rendered_bar', 123), ('_hidden_foo', u'{{ cookiecutter.foo|lower }}'), ('_hidden_bar', 123), ('__rendered_hidden_foo', u'{{ cookiecutter.foo|lower }}'), ('__rendered_hidden_bar', 123), ]) } cookiecutter_dict = prompt.prompt_for_config(context, no_input=True) assert cookiecutter_dict == OrderedDict([ ('foo', 'Hello world'), ('bar', '123'), ('rendered_foo', 'hello world'), ('rendered_bar', '123'), ('_hidden_foo', u'{{ cookiecutter.foo|lower }}'), ('_hidden_bar', 123), ('__rendered_hidden_foo', 'hello world'), ('__rendered_hidden_bar', '123'), ])
def test_should_render_choices(self, mocker): read_choice = mocker.patch('cookiecutter.prompt.read_user_choice') read_choice.return_value = u'anewproject' read_variable = mocker.patch('cookiecutter.prompt.read_user_variable') read_variable.return_value = u'A New Project' RENDERED_CHOICES = [u'foo', u'anewproject', u'bar'] CONTEXT = { 'cookiecutter': OrderedDict([ ('project_name', u'A New Project'), ('pkg_name', [ u'foo', u'{{ cookiecutter.project_name|lower|replace(" ", "") }}', u'bar' ]) ]) } EXP_COOKIECUTTER_DICT = { 'project_name': u'A New Project', 'pkg_name': u'anewproject' } cookiecutter_dict = prompt.prompt_for_config(CONTEXT) read_variable.assert_called_once_with('project_name', u'A New Project') read_choice.assert_called_once_with('pkg_name', RENDERED_CHOICES) assert cookiecutter_dict == EXP_COOKIECUTTER_DICT
def test_unicode_prompt_for_default_config_unicode(self, monkeypatch): monkeypatch.setattr('cookiecutter.prompt.read_user_variable', lambda var, default: default) context = {'cookiecutter': {'full_name': u'Řekni či napiš své jméno'}} cookiecutter_dict = prompt.prompt_for_config(context) assert cookiecutter_dict == {'full_name': u'Řekni či napiš své jméno'}
def create_project(args, _): context = generate_context( os.path.join(TEMPLATES_PATH, 'app', 'cookiecutter.json')) config = prompt_for_config(context) config['_app_dir'] = args.output_directory with open('.pywebui.yaml', 'w') as config_output: config_output.write( yaml.safe_dump(config, default_flow_style=False, encoding='utf-8')) cookiecutter(os.path.join(TEMPLATES_PATH, 'app'), no_input=True, extra_context=config) os.chdir(args.output_directory) if not args.without_electron: cookiecutter(os.path.join(TEMPLATES_PATH, 'electron'), no_input=True, extra_context=config) if not args.without_cordova: cookiecutter(os.path.join(TEMPLATES_PATH, 'cordova'), no_input=True, extra_context=config) if not args.without_flask: cookiecutter(os.path.join(TEMPLATES_PATH, 'flask'), no_input=True, extra_context=config) shell('npm install {} --no-save'.format( os.path.join(os.path.dirname(__file__), 'js')))
def test_dont_prompt_for_private_context_var(self, monkeypatch): monkeypatch.setattr( "cookiecutter.prompt.read_user_variable", lambda var, default: pytest.fail("Should not try to read a response for private context var"), ) context = {"cookiecutter": {"_copy_without_render": ["*.html"]}} cookiecutter_dict = prompt.prompt_for_config(context) assert cookiecutter_dict == {"_copy_without_render": ["*.html"]}
def test_prompt_for_config_simple(self): context = {"cookiecutter": {"full_name": "Your Name"}} if not PY3: sys.stdin = StringIO("Audrey Roy") cookiecutter_dict = prompt.prompt_for_config(context) self.assertEqual(cookiecutter_dict, {"full_name": "Audrey Roy"})
def test_dont_prompt_for_private_context_var(self, monkeypatch): monkeypatch.setattr( 'cookiecutter.prompt.read_user_variable', lambda var, default: pytest.fail('Should not try to read a response for private context var') ) context = {'cookiecutter': {'_copy_without_render': ['*.html']}} cookiecutter_dict = prompt.prompt_for_config(context) assert cookiecutter_dict == {'_copy_without_render': ['*.html']}
def test_dont_prompt_for_private_context_var(self, monkeypatch): monkeypatch.setattr( 'cookiecutter.prompt.read_user_variable', lambda var, default: pytest.fail( 'Should not try to read a response for private context var')) context = {'cookiecutter': {'_copy_without_render': ['*.html']}} cookiecutter_dict = prompt.prompt_for_config(context) assert cookiecutter_dict == {'_copy_without_render': ['*.html']}
def test_prompt_for_config(self, monkeypatch, context): """Verify `prompt_for_config` call `read_user_variable` on text request.""" monkeypatch.setattr( 'cookiecutter.prompt.read_user_variable', lambda var, default: default, ) cookiecutter_dict = prompt.prompt_for_config(context) assert cookiecutter_dict == context['cookiecutter']
def test_unicode_prompt_for_default_config_unicode(self, monkeypatch): monkeypatch.setattr( 'cookiecutter.prompt.read_response', lambda x=u'': u'\n' ) context = {"cookiecutter": {"full_name": u"Řekni či napiš své jméno"}} cookiecutter_dict = prompt.prompt_for_config(context) assert cookiecutter_dict == {"full_name": u"Řekni či napiš své jméno"}
def test_prompt_for_config_empty_dict(self, monkeypatch): monkeypatch.setattr( 'cookiecutter.prompt.read_user_dict', lambda var, default: {} ) context = {'cookiecutter': {'details': {}}} cookiecutter_dict = prompt.prompt_for_config(context) assert cookiecutter_dict == {'details': {}}
def test_prompt_for_config_unicode(self, monkeypatch): monkeypatch.setattr( 'cookiecutter.prompt.read_response', lambda x=u'': u'Pizzä ïs Gööd' ) context = {"cookiecutter": {"full_name": "Your Name"}} cookiecutter_dict = prompt.prompt_for_config(context) assert cookiecutter_dict == {"full_name": u"Pizzä ïs Gööd"}
def test_unicode_prompt_for_templated_config(self): context = {"cookiecutter": OrderedDict([ ("project_name", u"A New Project"), ("pkg_name", u"{{ cookiecutter.project_name|lower|replace(' ', '') }}") ])} cookiecutter_dict = prompt.prompt_for_config(context) self.assertEqual(cookiecutter_dict, {"project_name": u"A New Project", "pkg_name": u"anewproject"})
def create( template_git_url: str, output_dir: str = ".", config_file: Optional[str] = None, default_config: bool = False, extra_context: Optional[dict] = None, no_input: bool = False, overwrite_if_exists: bool = False, ) -> str: """Expand a Git based Cookiecutter template into a new project on disk.""" with TemporaryDirectory() as cookiecutter_template_dir_str: cookiecutter_template_dir = Path(cookiecutter_template_dir_str) try: repo = Repo.clone_from(template_git_url, cookiecutter_template_dir) last_commit = repo.head.object.hexsha except Exception as e: raise InvalidCookiecutterRepository(e) main_cookiecutter_directory: Optional[Path] = None for dir_item in cookiecutter_template_dir.glob("*cookiecutter.*"): if dir_item.is_dir( ) and "{{" in dir_item.name and "}}" in dir_item.name: main_cookiecutter_directory = dir_item break if not main_cookiecutter_directory: # pragma: no cover raise UnableToFindCookiecutterTemplate(cookiecutter_template_dir) context_file = cookiecutter_template_dir / "cookiecutter.json" config_dict = get_user_config(config_file=config_file, default_config=default_config) context = generate_context( context_file=str(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) context["cookiecutter"]["_template"] = template_git_url (main_cookiecutter_directory / ".cruft.json").write_text( json_dumps({ "template": template_git_url, "commit": last_commit, "context": context })) return generate_files( repo_dir=cookiecutter_template_dir, context=context, overwrite_if_exists=overwrite_if_exists, output_dir=output_dir, )
def test_dont_prompt_for_private_context_var(self, monkeypatch): monkeypatch.setattr( "cookiecutter.prompt.read_user_variable", lambda var, default: pytest.fail( "Should not try to read a response for private context var"), ) context = {"cookiecutter": {"_copy_without_render": ["*.html"]}} cookiecutter_dict = prompt.prompt_for_config(context) assert cookiecutter_dict == {"_copy_without_render": ["*.html"]}
def test_unicode_prompt_for_default_config_unicode(self, monkeypatch): monkeypatch.setattr( "cookiecutter.prompt.read_user_variable", lambda var, default: default, ) context = {"cookiecutter": {"full_name": u"Řekni či napiš své jméno"}} cookiecutter_dict = prompt.prompt_for_config(context) assert cookiecutter_dict == {"full_name": u"Řekni či napiš své jméno"}
def test_unicode_prompt_for_config_unicode(self, monkeypatch): monkeypatch.setattr( 'cookiecutter.prompt.read_response', lambda x=u'': u'Pizzä ïs Gööd' ) context = {'cookiecutter': {'full_name': u'Řekni či napiš své jméno'}} cookiecutter_dict = prompt.prompt_for_config(context) assert cookiecutter_dict == {'full_name': u'Pizzä ïs Gööd'}
def test_prompt_for_config_simple(self, monkeypatch): monkeypatch.setattr( 'cookiecutter.prompt.read_response', lambda x=u'': u'Audrey Roy' ) context = {'cookiecutter': {'full_name': 'Your Name'}} cookiecutter_dict = prompt.prompt_for_config(context) assert cookiecutter_dict == {'full_name': u'Audrey Roy'}
def test_prompt_for_config_unicode(self, monkeypatch): monkeypatch.setattr( "cookiecutter.prompt.read_user_variable", lambda var, default: u"Pizzä ïs Gööd", ) context = {"cookiecutter": {"full_name": "Your Name"}} cookiecutter_dict = prompt.prompt_for_config(context) assert cookiecutter_dict == {"full_name": u"Pizzä ïs Gööd"}
def render_file_template(template_path, use_defaults=False, extra_context=None): """Render a single-file template with Cookiecutter. Currently this function only renders a file using default values defined in a ``cookiecutter.json`` file. Parameters ---------- template_path : `str` Path to the file template. There should be a ``cookecutter.json`` in the same directory as the template file. This JSON file is used to define a provide defaults for the template's variables. use_defaults : `bool`, optional Disables Sphinx from interactively prompting for context variables, if `True`. extra_context : `dict`, optional Optional dictionary of key-value pairs that override defaults in the ``cookiecutter.json`` file. Returns ------- rendered_text : `str` Content rendered from the template and ``cookiecutter.json`` defaults. """ logger = logging.getLogger(__name__) logger.debug('Rendering file template %s', template_path) # Get variables for rendering the template template_dir = os.path.dirname(template_path) context_file = os.path.join(template_dir, 'cookiecutter.json') context = generate_context(context_file=context_file) context['cookiecutter'] = prompt_for_config(context, use_defaults) if extra_context is not None: context['cookiecutter'].update(extra_context) # Jinja2 template rendering environment env = StrictEnvironment( context=context, keep_trailing_newline=True, ) env.loader = FileSystemLoader(template_dir) try: tmpl = env.get_template(os.path.basename(template_path)) except TemplateSyntaxError as exception: # Disable translated so that printed exception contains verbose # information about syntax error location exception.translated = False raise rendered_text = tmpl.render(**context) return rendered_text
def test_prompt_for_config_dict(self, monkeypatch): """Verify `prompt_for_config` call `read_user_variable` on dict request.""" monkeypatch.setattr( 'cookiecutter.prompt.read_user_dict', lambda var, default: {"key": "value", "integer": 37}, ) context = {'cookiecutter': {'details': {}}} cookiecutter_dict = prompt.prompt_for_config(context) assert cookiecutter_dict == {'details': {'key': 'value', 'integer': 37}}
def test_should_render_deep_dict(self): """Verify nested structures like dict in dict, rendered correctly.""" context = { 'cookiecutter': { 'project_name': "Slartibartfast", 'details': { "key": "value", "integer_key": 37, "other_name": '{{cookiecutter.project_name}}', "dict_key": { "deep_key": "deep_value", "deep_integer": 42, "deep_other_name": '{{cookiecutter.project_name}}', "deep_list": [ "deep value 1", "{{cookiecutter.project_name}}", "deep value 3", ], }, "list_key": [ "value 1", "{{cookiecutter.project_name}}", "value 3", ], }, } } cookiecutter_dict = prompt.prompt_for_config(context, no_input=True) assert cookiecutter_dict == { 'project_name': "Slartibartfast", 'details': { "key": "value", "integer_key": "37", "other_name": "Slartibartfast", "dict_key": { "deep_key": "deep_value", "deep_integer": "42", "deep_other_name": "Slartibartfast", "deep_list": ["deep value 1", "Slartibartfast", "deep value 3"], }, "list_key": ["value 1", "Slartibartfast", "value 3"], }, }
def test_prompt_for_config_unicode(self): context = {"cookiecutter": {"full_name": "Your Name"}} if not PY3: sys.stdin = StringIO("Pizzä ïs Gööd") cookiecutter_dict = prompt.prompt_for_config(context) if PY3: self.assertEqual(cookiecutter_dict, {"full_name": "Pizzä ïs Gööd"}) else: self.assertEqual(cookiecutter_dict, {"full_name": u"Pizzä ïs Gööd"})
def test_unicode_prompt_for_default_config_unicode(self): context = {"cookiecutter": {"full_name": u"Řekni či napiš své jméno"}} if not PY3: sys.stdin = StringIO("\n") cookiecutter_dict = prompt.prompt_for_config(context) if PY3: self.assertEqual(cookiecutter_dict, {"full_name": "Řekni či napiš své jméno"}) else: self.assertEqual(cookiecutter_dict, {"full_name": u"Řekni či napiš své jméno"})
def test_unicode_prompt_for_templated_config(self, monkeypatch): monkeypatch.setattr("cookiecutter.prompt.read_user_variable", lambda var, default: default) context = { "cookiecutter": OrderedDict( [ ("project_name", u"A New Project"), ("pkg_name", u'{{ cookiecutter.project_name|lower|replace(" ", "") }}'), ] ) } exp_cookiecutter_dict = {"project_name": u"A New Project", "pkg_name": u"anewproject"} cookiecutter_dict = prompt.prompt_for_config(context) assert cookiecutter_dict == exp_cookiecutter_dict
def test_prompt_for_config_dict(self, monkeypatch): monkeypatch.setattr( 'cookiecutter.prompt.read_user_dict', lambda var, default: {"key": "value", "integer": 37} ) context = {'cookiecutter': {'details': {}}} cookiecutter_dict = prompt.prompt_for_config(context) assert cookiecutter_dict == { 'details': { 'key': u'value', 'integer': 37 } }
def test_should_not_invoke_read_user_variable(self, mocker): read_variable = mocker.patch("cookiecutter.prompt.read_user_variable") read_variable.return_value = u"Audrey Roy" prompt_choice = mocker.patch("cookiecutter.prompt.prompt_choice_for_config") read_choice = mocker.patch("cookiecutter.prompt.read_user_choice") CONTEXT = {"cookiecutter": {"full_name": "Your Name"}} cookiecutter_dict = prompt.prompt_for_config(CONTEXT) assert not prompt_choice.called assert not read_choice.called read_variable.assert_called_once_with("full_name", "Your Name") assert cookiecutter_dict == {"full_name": u"Audrey Roy"}
def test_unicode_prompt_for_templated_config(self, monkeypatch): monkeypatch.setattr('cookiecutter.prompt.read_user_variable', lambda var, default: default) context = { 'cookiecutter': OrderedDict( [('project_name', u'A New Project'), ('pkg_name', u'{{ cookiecutter.project_name|lower|replace(" ", "") }}')]) } exp_cookiecutter_dict = { 'project_name': u'A New Project', 'pkg_name': u'anewproject' } cookiecutter_dict = prompt.prompt_for_config(context) assert cookiecutter_dict == exp_cookiecutter_dict
def test_should_not_invoke_read_user_variable(self, mocker): read_variable = mocker.patch('cookiecutter.prompt.read_user_variable') read_variable.return_value = u'Audrey Roy' prompt_choice = mocker.patch( 'cookiecutter.prompt.prompt_choice_for_config') read_choice = mocker.patch('cookiecutter.prompt.read_user_choice') CONTEXT = {'cookiecutter': {'full_name': 'Your Name'}} cookiecutter_dict = prompt.prompt_for_config(CONTEXT) assert not prompt_choice.called assert not read_choice.called read_variable.assert_called_once_with('full_name', 'Your Name') assert cookiecutter_dict == {'full_name': u'Audrey Roy'}
def test_should_render_dict(self): context = { 'cookiecutter': { 'project_name': 'Slartibartfast', 'details': { 'other_name': '{{cookiecutter.project_name}}' } } } cookiecutter_dict = prompt.prompt_for_config(context, no_input=True) assert cookiecutter_dict == { 'project_name': 'Slartibartfast', 'details': { 'other_name': u'Slartibartfast', } }
def test_prompt_for_config_deep_dict(self, monkeypatch): monkeypatch.setattr( 'cookiecutter.prompt.read_user_dict', lambda var, default: { "key": "value", "integer_key": 37, "dict_key": { "deep_key": "deep_value", "deep_integer": 42, "deep_list": [ "deep value 1", "deep value 2", "deep value 3", ] }, "list_key": [ "value 1", "value 2", "value 3", ] } ) context = {'cookiecutter': {'details': {}}} cookiecutter_dict = prompt.prompt_for_config(context) assert cookiecutter_dict == { 'details': { "key": "value", "integer_key": 37, "dict_key": { "deep_key": "deep_value", "deep_integer": 42, "deep_list": [ "deep value 1", "deep value 2", "deep value 3", ] }, "list_key": [ "value 1", "value 2", "value 3", ] } }
def test_should_invoke_read_user_choice(self, mocker): prompt_choice = mocker.patch( "cookiecutter.prompt.prompt_choice_for_config", wraps=prompt.prompt_choice_for_config ) read_choice = mocker.patch("cookiecutter.prompt.read_user_choice") read_choice.return_value = "all" read_variable = mocker.patch("cookiecutter.prompt.read_user_variable") CHOICES = ["landscape", "portrait", "all"] CONTEXT = {"cookiecutter": {"orientation": CHOICES}} cookiecutter_dict = prompt.prompt_for_config(CONTEXT) assert not read_variable.called assert prompt_choice.called read_choice.assert_called_once_with("orientation", CHOICES) assert cookiecutter_dict == {"orientation": "all"}
def test_should_invoke_read_user_choice(self, mocker): prompt_choice = mocker.patch( 'cookiecutter.prompt.prompt_choice_for_config', wraps=prompt.prompt_choice_for_config) read_choice = mocker.patch('cookiecutter.prompt.read_user_choice') read_choice.return_value = 'all' read_variable = mocker.patch('cookiecutter.prompt.read_user_variable') CHOICES = ['landscape', 'portrait', 'all'] CONTEXT = {'cookiecutter': {'orientation': CHOICES}} cookiecutter_dict = prompt.prompt_for_config(CONTEXT) assert not read_variable.called assert prompt_choice.called read_choice.assert_called_once_with('orientation', CHOICES) assert cookiecutter_dict == {'orientation': 'all'}
def test_unicode_prompt_for_templated_config(self, monkeypatch): monkeypatch.setattr( 'cookiecutter.prompt.read_response', lambda x=u'': u'\n' ) context = {"cookiecutter": OrderedDict([ ( "project_name", u"A New Project" ), ( "pkg_name", u"{{ cookiecutter.project_name|lower|replace(' ', '') }}" ) ])} exp_cookiecutter_dict = { "project_name": u"A New Project", "pkg_name": u"anewproject" } cookiecutter_dict = prompt.prompt_for_config(context) assert cookiecutter_dict == exp_cookiecutter_dict
def test_should_render_choices(self, mocker): read_choice = mocker.patch("cookiecutter.prompt.read_user_choice") read_choice.return_value = u"anewproject" read_variable = mocker.patch("cookiecutter.prompt.read_user_variable") read_variable.return_value = u"A New Project" RENDERED_CHOICES = [u"foo", u"anewproject", u"bar"] CONTEXT = { "cookiecutter": OrderedDict( [ ("project_name", u"A New Project"), ("pkg_name", [u"foo", u'{{ cookiecutter.project_name|lower|replace(" ", "") }}', u"bar"]), ] ) } EXP_COOKIECUTTER_DICT = {"project_name": u"A New Project", "pkg_name": u"anewproject"} cookiecutter_dict = prompt.prompt_for_config(CONTEXT) read_variable.assert_called_once_with("project_name", u"A New Project") read_choice.assert_called_once_with("pkg_name", RENDERED_CHOICES) assert cookiecutter_dict == EXP_COOKIECUTTER_DICT
def test_unicode_prompt_for_default_config_unicode(self): context = {"cookiecutter": {"full_name": u"Řekni či napiš své jméno"}} cookiecutter_dict = prompt.prompt_for_config(context) self.assertEqual(cookiecutter_dict, {"full_name": u"Řekni či napiš své jméno"})
def cookiepatch(): parser = argparse.ArgumentParser(description='Tool to apply / create patch from ' 'cookiecutter templates') parser.add_argument('--template', type=str, help='an integer for the accumulator') parser.add_argument('--diff', type=str, nargs='+', help='versions passed for git diff') parser.add_argument('--show', action='store_true', help='Just print diff') args = parser.parse_args() conf_file = None if os.path.exists(CONF_PATH): with open(CONF_PATH) as f: conf_file = json.load(f) if args.template: template = args.template elif conf_file and 'template' in conf_file: template = conf_file['template'] else: template = input('Input template repository url: ') if args.diff: diff = args.diff elif conf_file and 'revision' in conf_file: diff = [conf_file['revision']] else: cur = input('Input template version applied currently: ') to = input('Input version to follow [master]: ') or 'master' diff = [cur, to] no_input = False config_dict = get_user_config(config_file=USER_CONFIG_PATH) parsed_template = expand_abbreviations(template, config_dict) repo_dir = clone(repo_url=parsed_template, clone_to_dir=config_dict['cookiecutters_dir'], checkout=None, no_input=no_input) patch_bytes = subprocess.check_output(['git', 'diff'] + diff + ['--', '{{cookiecutter.repo_name}}'], cwd=repo_dir) patch_str = patch_bytes.decode() context_file = os.path.join(repo_dir, 'cookiecutter.json') context = generate_context( context_file=context_file, default_context=config_dict['default_context'], extra_context={}, ) if conf_file: context['cookiecutter'] = conf_file['variables'] else: # 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) rendered = Template(patch_str).render(**context) if args.show: print(rendered) return p = subprocess.Popen(['patch', '-Np1', '--no-backup-if-mismatch'], stdin=subprocess.PIPE, cwd='..') p.communicate(rendered.encode()) # Generate cookiepatcher JSON if len(diff) == 1: rev = 'HEAD' else: rev = diff[-1] revision_bytes = subprocess.check_output(['git', 'rev-parse'] + [rev], cwd=repo_dir) revision_str = revision_bytes.decode().rstrip('\n') json_content = { 'revision': revision_str, 'variables': context['cookiecutter'], 'template': template } with open(CONF_PATH, 'w') as f: json.dump(json_content, f, ensure_ascii=False, indent=2, sort_keys=True)