def test_expand_abbreviations():
    template = 'gh:audreyr/cookiecutter-pypackage'

    # This is not a valid repo url just yet!
    # First `main.expand_abbreviations` needs to translate it
    assert is_repo_url(template) is False

    expanded_template = expand_abbreviations(template, {})
    assert is_repo_url(expanded_template) is True
Exemple #2
0
def test_expand_abbreviations():
    template = 'gh:audreyr/cookiecutter-pypackage'

    # This is not a valid repo url just yet!
    # First `main.expand_abbreviations` needs to translate it
    assert is_repo_url(template) is False

    expanded_template = expand_abbreviations(template, {})
    assert is_repo_url(expanded_template) is True
Exemple #3
0
def cookiecutter(template, checkout=None, no_input=False, extra_context=None):
    """
    Replacement for cookiecutter's own cookiecutter.

    The difference with cookiecutter's cookiecutter function
    is that this one doesn't automatically str() all the values
    passed along to the template.

    :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.
    """

    # Get user config from ~/.cookiecutterrc or equivalent
    # If no config file, sensible defaults from config.DEFAULT_CONFIG are used
    config_dict = get_user_config()

    template = expand_abbreviations(template, config_dict)

    # TODO: find a better way to tell if it's a repo URL
    if 'git@' in template or 'https://' in template:
        repo_dir = clone(
            repo_url=template,
            checkout=checkout,
            clone_to_dir=config_dict['cookiecutters_dir'],
            no_input=no_input
        )
    else:
        # If it's a local repo, no need to clone or copy to your
        # cookiecutters_dir
        repo_dir = template

    context_file = os.path.join(repo_dir, 'cookiecutter.json')
    logging.debug('context_file is {0}'.format(context_file))

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

    # Create project from local context and project template.
    generate_files(
        repo_dir=repo_dir,
        context=context
    )
Exemple #4
0
def cookiecutter(template, checkout=None, no_input=False, extra_context=None):
    """
    Replacement for cookiecutter's own cookiecutter.

    The difference with cookiecutter's cookiecutter function
    is that this one doesn't automatically str() all the values
    passed along to the template.

    :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.
    """

    # Get user config from ~/.cookiecutterrc or equivalent
    # If no config file, sensible defaults from config.DEFAULT_CONFIG are used
    config_dict = get_user_config()

    template = expand_abbreviations(template, config_dict)

    # TODO: find a better way to tell if it's a repo URL
    if 'git@' in template or 'https://' in template:
        repo_dir = clone(repo_url=template,
                         checkout=checkout,
                         clone_to_dir=config_dict['cookiecutters_dir'],
                         no_input=no_input)
    else:
        # If it's a local repo, no need to clone or copy to your
        # cookiecutters_dir
        repo_dir = template

    context_file = os.path.join(repo_dir, 'cookiecutter.json')
    logging.debug('context_file is {0}'.format(context_file))

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

    # Create project from local context and project template.
    generate_files(repo_dir=repo_dir, context=context)
Exemple #5
0
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)
def test_abbreviation_expansion_not_an_abbreviation():
    input_dir = main.expand_abbreviations(
        'baz', {'abbreviations': {'foo': 'bar'}}
    )
    assert input_dir == 'baz'
Exemple #7
0
def test_abbreviation_expansion_not_an_abbreviation():
    input_dir = main.expand_abbreviations('baz',
                                          {'abbreviations': {
                                              'foo': 'bar'
                                          }})
    assert input_dir == 'baz'
Exemple #8
0
 def test_abbreviation_expansion(self):
     template = main.expand_abbreviations('foo',
                                          {'abbreviations': {
                                              'foo': 'bar'
                                          }})
     self.assertEqual(template, 'bar')
def test_abbreviation_expansion_prefix_not_0_in_braces():
    with pytest.raises(IndexError):
        main.expand_abbreviations('xx:a', {'abbreviations': {'xx': '{1}'}})
Exemple #10
0
def test_abbreviation_expansion_override_builtin():
    input_dir = main.expand_abbreviations('gh:a',
                                          {'abbreviations': {
                                              'gh': '<{0}>'
                                          }})
    assert input_dir == '<a>'
Exemple #11
0
 def test_abbreviation_expansion_override_builtin(self):
     input_dir = main.expand_abbreviations(
         'gh:a', {'abbreviations': {
             'gh': '<{0}>'
         }})
     self.assertEqual(input_dir, '<a>')
def test_abbreviation_expansion_override_builtin():
    input_dir = main.expand_abbreviations(
        'gh:a', {'abbreviations': {'gh': '<{0}>'}}
    )
    assert input_dir == '<a>'
Exemple #13
0
 def test_abbreviation_expansion_not_an_abbreviation(self):
     input_dir = main.expand_abbreviations(
         'baz', {'abbreviations': {
             'foo': 'bar'
         }})
     self.assertEqual(input_dir, 'baz')
Exemple #14
0
 def test_abbreviation_expansion_builtin(self):
     input_dir = main.expand_abbreviations('gh:a', {})
     self.assertEqual(input_dir, 'https://github.com/a.git')
Exemple #15
0
def test_abbreviation_expansion_prefix():
    input_dir = main.expand_abbreviations('xx:a',
                                          {'abbreviations': {
                                              'xx': '<{0}>'
                                          }})
    assert input_dir == '<a>'
Exemple #16
0
def test_abbreviation_expansion_prefix_not_0_in_braces():
    with pytest.raises(IndexError):
        main.expand_abbreviations('xx:a', {'abbreviations': {'xx': '{1}'}})
Exemple #17
0
def test_abbreviation_expansion_prefix_ignores_suffix():
    input_dir = main.expand_abbreviations('xx:a',
                                          {'abbreviations': {
                                              'xx': '<>'
                                          }})
    assert input_dir == '<>'
def test_abbreviation_expansion_prefix():
    input_dir = main.expand_abbreviations(
        'xx:a', {'abbreviations': {'xx': '<{0}>'}}
    )
    assert input_dir == '<a>'
Exemple #19
0
def Command(path=None,
            template=None,
            flavor=None,
            prompt=False,
            author=None,
            license_years=None,
            module_version=None,
            website=None):
    """Initialise a module by populating a directory

    Will populate specified path (or current path if not
    specified) with OpenERP/Odoo modules files and directory
    structure.

    Usage:
      %(std_usage)s
      %(surcmd)s [PATH] [--template=TEMPLATE] [--flavor=FLAVOR]
          [--prompt|-p] [--author=AUTHOREMAIL] [--license-years=YEARS]
          [--module-version VERSION] [--website WEBSITE]

    Options:
      %(std_options)s
      PATH                If not specified, equivalent to "."
      --template TEMPLATE      Advanced cookiecutter template.
      --flavor FLAVOR          Target template version (ie: 8.0, 7.0)
                               (default: master)
      --prompt, -p             Prompt for all values, except those provided on
                               the command line. And values from config files.
      --author AUTHOREMAIL     Author name and email. Default taken in config.
                               (ie: 'Robert Dubois <*****@*****.**>')
      --license-years YEARS    License applicable years. (ie: 2010-2012, 2013)
                               (defaults to current year)
      --module-version VERSION Starting version number
      --website WEBSITE        Website of the module.

    """

    cfg = kids.cfg.load()

    path = os.getcwd() if path is None else os.path.abspath(path)
    root = common.find_root(path)

    if root:
        msg.die("Module %r already initialized." % root)

    name = os.path.basename(path)
    output_dir = os.path.dirname(path)

    if not os.path.isdir(output_dir):
        msg.die("Destination directory %r doesn't exists." % (output_dir, ))

    if template is None:
        template = mdict(cfg).get("init.template", DEFAULT_TEMPLATE)

    ## Command line provided values
    cli_values = {"name": name}
    default_values = {}

    dct = default_values if author is None else cli_values
    if author is None:
        author = mdict(cfg).get("author")
        if author is None and not os.environ.get("NO_GIT_CONFIG", ""):
            author = get_git_author(path)
        if author is None:
            msg.die(
                "No author found on command line nor in config files.\n"
                "Please provide an author with '--author=', for instance:\n\n"
                "  oem init --author='Robert Dubois <*****@*****.**>'"
                "\n\nor set a default author in your config file before "
                "running this command:\n\n"
                "  oem config set author 'Robert Dubois <*****@*****.**>'"
                "\n\nor set a default author in your git config like this:"
                "\n\n"
                "  git config --global user.name 'Robert Dubois'\n"
                "  git config --global user.email '*****@*****.**'\n")

    match = AUTHOR_REGEX.search(author)
    if not match:
        msg.die("Your value %r for 'author' doesn't match specs.\n"
                "You should try to match this example:\n\n"
                "    Robert Dubois <*****@*****.**>" % (author, ))
    match = match.groupdict()
    dct["author"] = match["name"].strip()
    dct["email"] = match["email"]

    if license_years is None:
        license_years = sact.epoch.Time.now().strftime('%Y')
        default_values["license_years"] = license_years
    else:
        cli_values["license_years"] = license_years

    if module_version is None:
        module_version = '0.1'
        default_values["version"] = module_version
    else:
        cli_values["version"] = module_version

    if website is not None:
        cli_values["website"] = website

    ## A big part of the following code comes directly from
    ## cookiecutter, and I would be glad that some of the
    ## functionality I implemented would come in a way or another
    ## in cookiecutter itslef.

    # Get user config from ~/.cookiecutterrc or equivalent
    # If no config file, sensible defaults from config.DEFAULT_CONFIG are used
    config_dict = cc.get_user_config()

    template = cc.expand_abbreviations(template, config_dict)

    # TODO: find a better way to tell if it's a repo URL
    if 'git@' in template or 'https://' in template:
        repo_dir = cc.clone(repo_url=template,
                            checkout=flavor,
                            clone_to_dir=config_dict['cookiecutters_dir'],
                            no_input=True)
    else:
        # If it's a local repo, no need to clone or copy to your
        # cookiecutters_dir
        repo_dir = template

    context_file = cc.find_cfg_file(repo_dir)

    default_context = config_dict.get('default_context', {})
    if default_values:
        default_context.update(default_values)
    context = cc.generate_context(
        context_file=context_file,
        default_context=default_context,
        extra_context=config_dict,
    )

    context = cc.prompt_for_config(context,
                                   no_input=False,
                                   values=cli_values,
                                   only_missing=not prompt,
                                   with_optional=prompt)

    ## XXXvlab: missing no-overwrite mode
    # Create project from local context and project template.
    if not os.environ.get("OEM_DRY_RUN", ""):
        cc.generate_files(repo_dir=repo_dir,
                          context=context,
                          output_dir=output_dir)
def test_abbreviation_expansion_builtin():
    input_dir = main.expand_abbreviations(
        'gh:a', {}
    )
    assert input_dir == 'https://github.com/a.git'
 def test_abbreviation_expansion_builtin(self):
     input_dir = main.expand_abbreviations('gh:a', {})
     self.assertEqual(input_dir, 'https://github.com/a.git')
def test_abbreviation_expansion_prefix_ignores_suffix():
    input_dir = main.expand_abbreviations(
        'xx:a', {'abbreviations': {'xx': '<>'}}
    )
    assert input_dir == '<>'
 def test_abbreviation_expansion_prefix_ignores_suffix(self):
     input_dir = main.expand_abbreviations('xx:a', {'abbreviations': {'xx': '<>'}})
     self.assertEqual(input_dir, '<>')
Exemple #24
0
 def test_abbreviation_expansion_prefix_ignores_suffix(self):
     input_dir = main.expand_abbreviations('xx:a',
                                           {'abbreviations': {
                                               'xx': '<>'
                                           }})
     self.assertEqual(input_dir, '<>')
Exemple #25
0
def test_abbreviation_expansion_builtin():
    input_dir = main.expand_abbreviations('gh:a', {})
    assert input_dir == 'https://github.com/a.git'
 def test_abbreviation_expansion_not_an_abbreviation(self):
     input_dir = main.expand_abbreviations('baz', {'abbreviations': {'foo': 'bar'}})
     self.assertEqual(input_dir, 'baz')
Exemple #27
0
 def test_abbreviation_expansion_builtin(self):
     template = main.expand_abbreviations('gh:a', {})
     self.assertEqual(template, 'https://github.com/a.git')
 def test_abbreviation_expansion_override_builtin(self):
     input_dir = main.expand_abbreviations('gh:a', {'abbreviations': {'gh': '<{0}>'}})
     self.assertEqual(input_dir, '<a>')
Exemple #29
0
 def test_abbreviation_expansion_override_builtin(self):
     template = main.expand_abbreviations(
         'gh:a', {'abbreviations': {
             'gh': '<{0}>'
         }})
     self.assertEqual(template, '<a>')
Exemple #30
0
 def test_abbreviation_expansion_prefix_ignores_suffix(self):
     template = main.expand_abbreviations('xx:a',
                                          {'abbreviations': {
                                              'xx': '<>'
                                          }})
     self.assertEqual(template, '<>')
Exemple #31
0
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)