Ejemplo n.º 1
0
def test_raises_AttributeError_if_default_not_given(ctx, query):
    ctx.values = {
        'test1': {
            'sub': 'test value',
        }
    }

    with pytest.raises(AttributeError):
        context.get(query)
Ejemplo n.º 2
0
def clean(exclude: List[str]):
    """ Remove all unnecessary files.

    Args:
        exclude (list[str]):
            A list of path patterns to exclude from deletion.
    """
    pretend = context.get('pretend', False)
    exclude = list(exclude) + conf.get('clean.exclude', [])
    clean_patterns = conf.get('clean.patterns', [
        '*__pycache__*',
        '*.py[cod]',
        '*.swp',
        "*.mypy_cache",
        "*.pytest_cache",
        "*.build",
    ])

    if context.get('verbose'):
        log.info('Clean patterns:')
        for pattern in clean_patterns:
            log.info(f'  <90>{pattern}')

        log.info('Exclude:')
        for pattern in exclude:
            log.info(f'  <90>{pattern}')

    num_files = 0
    with util.timed_block() as t:
        files = fs.filtered_walk(conf.proj_path(), clean_patterns, exclude)
        log.info('')
        log.info('Deleting:')
        for path in files:
            try:
                num_files += 1

                if not isdir(path):
                    log.info('  <91>[file] <90>{}', path)
                    if not pretend:
                        os.remove(path)
                else:
                    log.info('  <91>[dir]  <90>{}', path)
                    if not pretend:
                        rmtree(path)

            except OSError:
                log.info("<33>Failed to remove <90>{}", path)

    if pretend:
        msg = "Would delete <33>{}<32> files. Took <33>{}<32>s"
    else:
        msg = "Deleted <33>{}<32> files in <33>{}<32>s"

    log.info(msg.format(num_files, t.elapsed_s))
Ejemplo n.º 3
0
def finish(fast_forward: bool):
    """ Merge current feature branch into develop. """
    pretend = context.get('pretend', False)

    if not pretend and (git.staged() or git.unstaged()):
        log.err("You have uncommitted changes in your repo!\n"
                "You need to stash them before you merge the feature branch")
        sys.exit(1)

    develop = conf.get('git.devel_branch', 'develop')
    branch = git.current_branch(refresh=True)

    common.assert_branch_type('feature')

    hooks.register.call('pre-feature-finish', branch)

    # Merge feature into develop
    common.git_checkout(develop)
    common.git_pull(develop)
    common.git_merge(develop, branch.name, no_ff=not fast_forward)

    # Cleanup
    common.git_branch_delete(branch.name)
    common.git_prune()

    common.git_checkout(develop)

    hooks.register.call('post-feature-finish', branch)
Ejemplo n.º 4
0
    def deploy(self, promote=False, quiet=False):
        # type: (bool, bool, bool) -> None
        """ Deploy the code to AppEngine.

        Args:
            promote (bool):
                Migrate the traffic to the deployed version.
            quiet (bool):
                Pass ``--quiet`` flag to gcloud command
        """
        args = [
            '--promote' if promote else '--no-promote',
            '--version {}'.format(self.app_version),
            '--project {}'.format(self.app_id),
        ]

        if quiet:
            args += ['--quiet']

        cmd = 'gcloud app deploy {args} {deployables}'.format(
            deployables=fs.wrap_paths(self.deployables), args=' '.join(args))

        if context.get('pretend', False):
            log.info("Would deploy version <35>{ver}<32> to <35>{app}".format(
                ver=self.app_version, app=self.app_id))
            shell.cprint('<90>{}', cmd)
        else:
            log.info("Deploying version <35>{ver}<32> to <35>{app}".format(
                ver=self.app_version,
                app=self.app_id,
            ))
            shell.run(cmd)
Ejemplo n.º 5
0
Archivo: cli.py Proyecto: novopl/peltak
def _manage_cmd(cmd, settings=None):
    # type: () -> None
    """ Run django ./manage.py command manually.

    This function eliminates the need for having ``manage.py`` (reduces file
    clutter).
    """
    import sys
    from os import environ
    from peltak.core import conf
    from peltak.core import context
    from peltak.core import log

    sys.path.insert(0, conf.get('src_dir'))

    settings = settings or conf.get('django.settings', None)
    environ.setdefault("DJANGO_SETTINGS_MODULE", settings)

    args = sys.argv[0:-1] + cmd

    if context.get('pretend', False):
        log.info("Would run the following manage command:\n<90>{}", args)
    else:
        from django.core.management import execute_from_command_line
        execute_from_command_line(args)
Ejemplo n.º 6
0
def test_return_default_when_provided_and_value_not_found(ctx, query):
    ctx.values = {
        'test1': {
            'sub': 'test value',
        }
    }
    assert context.get(query, -1) == -1
Ejemplo n.º 7
0
def init(quick: bool, blank: bool, force: bool):
    """ Create an empty pelconf.yaml from template """
    config_file = 'pelconf.yaml'
    prompt = "-- <35>{} <32>already exists. Wipe it?<0>".format(config_file)

    if not force and exists(config_file) and not click.confirm(
            shell.fmt(prompt)):
        log.info("Canceled")
        return

    ctx = dict(blank=blank)

    if not blank:
        form = InitForm().run(quick=quick)
        ctx.update(form.values)

    config_content = templates.Engine().render_file('pelconf.yaml', ctx)

    log.info('Writing <35>{}'.format(config_file))
    fs.write_file(config_file, config_content)

    if context.get('verbose') > 0:
        print(
            f"{'- ' * 40}\n{shell.highlight(config_content, 'yaml')}{'- ' * 40}"
        )
Ejemplo n.º 8
0
def git_merge(base: str, head: str, no_ff: bool = False):
    """ Merge *head* into *base*.

    Args:
        base (str):
            The base branch. *head* will be merged into this branch.
        head (str):
            The branch that will be merged into *base*.
        no_ff (bool):
            If set to **True** it will force git to create merge commit. If set
            to **False** (default) it will do a fast-forward merge if possible.
    """
    pretend = context.get('pretend', False)
    branch = git.current_branch(refresh=True)

    if branch.name != base and not pretend:
        git_checkout(base)

    args = []

    if no_ff:
        args.append('--no-ff')

    log.info("Merging <33>{}<32> into <33>{}<32>", head, base)
    shell.run('git merge {args} {branch}'.format(
        args=' '.join(args),
        branch=head,
    ))

    if branch.name != base and not pretend:
        git_checkout(branch.name)
Ejemplo n.º 9
0
def finish(fast_forward: bool):
    """ Merge current feature branch into develop. """
    pretend = context.get('pretend', False)

    if not pretend and (git.staged() or git.unstaged()):
        log.err("You have uncommitted changes in your repo!\n"
                "You need to stash them before you merge the hotfix branch")
        sys.exit(1)

    branch = git.current_branch(refresh=True)
    base = common.get_base_branch()

    prompt = "<32>Merge <33>{}<32> into <33>{}<0>?".format(branch.name, base)
    if not click.confirm(shell.fmt(prompt)):
        log.info("Cancelled")
        return

    common.assert_branch_type('task')

    hooks.register.call('pre-task-finish', branch, base)

    # Merge task into it's base feature branch
    common.git_checkout(base)
    common.git_pull(base)
    common.git_merge(base, branch.name, no_ff=not fast_forward)

    # Cleanup
    common.git_branch_delete(branch.name)
    common.git_prune()

    common.git_checkout(base)

    hooks.register.call('post-task-finish', branch, base)
Ejemplo n.º 10
0
def test_can_just_get_the_full_nested_object(ctx):
    ctx.values = {
        'test1': {
            'sub': 'test value',
        }
    }

    assert context.get('test1') == {'sub': 'test value'}
Ejemplo n.º 11
0
def test_get_existing_nested_value_works(ctx):
    ctx.values = {
        'test1': {
            'sub': 'test value',
        }
    }

    assert context.get('test1.sub') == 'test value'
Ejemplo n.º 12
0
def add_hooks(pre_commit: str, pre_push: str):
    """ Add git hooks for commit and push to run linting and tests. """

    # Detect virtualenv the hooks should use

    # Detect virtualenv
    virtual_env = conf.get_env('VIRTUAL_ENV')
    if virtual_env is None:
        log.err("You are not inside a virtualenv")
        confirm_msg = (
            "Are you sure you want to use global python installation "
            "to run your git hooks? [y/N] "
        )
        click.prompt(confirm_msg, default='')
        if not click.confirm(confirm_msg):
            log.info("Cancelling")
            return

        load_venv = ''
    else:
        load_venv = 'source "{}/bin/activate"'.format(virtual_env)

    commit_hook = conf.proj_path('.git/hooks/pre-commit')
    push_hook = conf.proj_path('.git/hooks/pre-push')

    # Write pre-commit hook
    log.info("Adding pre-commit hook <33>{}", commit_hook)
    fs.write_file(commit_hook, util.remove_indent('''
        #!/bin/bash
        PATH="/opt/local/libexec/gnubin:$PATH"
        
        {load_venv}
        
        {command}
        
    '''.format(load_venv=load_venv, command=pre_commit)))

    # Write pre-push hook
    log.info("Adding pre-push hook: <33>{}", push_hook)
    fs.write_file(push_hook, util.remove_indent('''
        #!/bin/bash
        PATH="/opt/local/libexec/gnubin:$PATH"
        
        {load_venv}
        
        peltak test --allow-empty
        
        {command}
        
    '''.format(load_venv=load_venv, command=pre_push)))

    log.info("Making hooks executable")
    if not context.get('pretend', False):
        os.chmod(conf.proj_path('.git/hooks/pre-commit'), 0o755)
        os.chmod(conf.proj_path('.git/hooks/pre-push'), 0o755)
Ejemplo n.º 13
0
def assert_on_branch(branch_name: str):
    """ Print error and exit if *branch_name* is not the current branch.

    Args:
        branch_name (str):
            The supposed name of the current branch.
    """
    branch = git.current_branch(refresh=True)

    if branch.name != branch_name:
        if context.get('pretend', False):
            log.info("Would assert that you're on a <33>{}<32> branch",
                     branch_name)
        else:
            log.err("You're not on a <33>{}<31> branch!", branch_name)
            sys.exit(1)
Ejemplo n.º 14
0
def extract_from_files(files: List[str]) -> List[Todo]:
    todos: List[Todo] = []

    for path in files:
        file_todos = _process_file(path)
        todos += file_todos

        if context.get('verbose') >= 1:
            if len(file_todos) > 0:
                shell.cprint(
                    "    <33>{:2} <32>TODOs in <90>{}".format(len(file_todos), path)
                )
            else:
                shell.cprint("    <32>No TODOs in <90>{}".format(path))

    return todos
Ejemplo n.º 15
0
def _render_todos(todos: List[Todo]) -> None:
    print('\n')
    for file_path, file_todos in itertools.groupby(todos,
                                                   key=lambda x: x.file):
        shell.cprint(f"<92>{file_path}\n")
        for todo in sorted(file_todos, key=lambda x: x.lines.start):
            if context.get('verbose') >= 1:
                shell.cprint(
                    f"<36>{todo.pretty_timestamp}  <33>{todo.author}<0>\n"
                    f"<95>{todo.file}:{todo.lines}  <90>{todo.sha1}<0>\n\n"
                    f"{textwrap.indent(todo.color_text, '  ')}\n\n")
            else:
                shell.cprint(
                    f"    <95>:{todo.lines}  <36>{todo.pretty_timestamp}  "
                    f"<33>{todo.author_email}  <90>{todo.sha1}<0><0>\n\n"
                    f"{textwrap.indent(todo.color_text, '        ')}\n")
        print()

    log.info(f"Found <33>{len(todos)}<32> TODOs")
Ejemplo n.º 16
0
def assert_branch_type(branch_type: str):
    """ Print error and exit if the current branch is not of a given type.

    Args:
        branch_type (str):
            The branch type. This assumes the branch is in the '<type>/<title>`
            format.
    """
    branch = git.current_branch(refresh=True)

    if branch.type != branch_type:
        if context.get('pretend', False):
            log.info("Would assert that you're on a <33>{}/*<32> branch",
                     branch_type)
        else:
            log.err("Not on a <33>{}<31> branch!", branch_type)
            fmt = ("The branch must follow <33>{required_type}/<name><31>"
                   "format and your branch is called <33>{name}<31>.")
            log.err(fmt, required_type=branch_type, name=branch.name)
            sys.exit(1)
Ejemplo n.º 17
0
Archivo: fs.py Proyecto: novopl/peltak
def write_file(path: str, content: Union[str, bytes], mode: str = 'w') -> None:
    """ --pretend aware file writing.

    You can always write files manually but you should always handle the
    --pretend case.

    Args:
        path (str):
        content (str):
        mode (str):
    """
    from peltak.core import context
    from peltak.core import log

    if context.get('pretend', False):
        log.info("Would overwrite <34>{path}<32> with:\n<90>{content}",
                 path=path,
                 content=content)
    else:
        with open(path, mode) as fp:
            fp.write(content)
Ejemplo n.º 18
0
def finish(fast_forward: bool):
    """ Merge current release into develop and master and tag it. """
    pretend = context.get('pretend', False)

    if not pretend and (git.staged() or git.unstaged()):
        log.err("You have uncommitted changes in your repo!\n"
                "You need to stash them before you merge the release branch")
        sys.exit(1)

    develop = conf.get('git.devel_branch', 'develop')
    master = conf.get('git.master_branch', 'master')
    branch = git.current_branch(refresh=True)

    common.assert_branch_type('release')

    hooks.register.call('pre-release-finish', branch)

    # Merge release into master
    common.git_checkout(develop)
    common.git_pull(develop)
    common.git_merge(develop, branch.name, no_ff=not fast_forward)

    # Merge release into develop
    common.git_checkout(master)
    common.git_pull(master)
    common.git_merge(master, branch.name, no_ff=not fast_forward)

    # Tag the release commit with version number
    tag(changelog())

    # Cleanup
    common.git_branch_delete(branch.name)
    common.git_prune()

    common.git_checkout(master)

    hooks.register.call('post-release-finish', branch)
Ejemplo n.º 19
0
def test_get_existing_root_value_works(ctx):
    ctx.values = {
        'test1': 'test value',
    }

    assert context.get('test1') == 'test value'