<commit_before>import getpass
import os
import textwrap
from typing import Sequence

import attr
import click

import releasetool.filehelpers
import releasetool.git
import releasetool.github
import releasetool.secrets


_CHANGELOG_TEMPLATE = """\
# Changelog

[PyPI History][1]

[1]: https://pypi.org/project/DISTRIBUTION NAME/#history

"""


@attr.s(auto_attribs=True, slots=True)
class Context:
    github: releasetool.github.GitHub = None
    github_repo: str = None
    package_name: str = None
    last_release_version: str = None
    last_release_committish: str = None
    changes: Sequence[str] = ()
    release_notes: str = None
    release_version: str = None
    release_branch: str = None
    pull_request: dict = None


def setup_context(ctx: Context) -> None:
    click.secho('> Determining basic context.', fg='cyan')
    github_token = releasetool.secrets.get_password('github')
    ctx.github = releasetool.github.GitHub(github_token)
    ctx.github_repo = releasetool.git.get_github_repo_name()
    click.secho(f'GitHub Repo: {ctx.github_repo}')


def determine_package_name(ctx: Context) -> None:
    click.secho('> Figuring out the package name.', fg='cyan')
    ctx.package_name = os.path.basename(os.getcwd())
    click.secho(
        f"Looks like we're releasing {ctx.package_name}.")


def determine_last_release(ctx: Context) -> None:
    click.secho('> Figuring out what the last release was.', fg='cyan')
    tags = releasetool.git.list_tags()
    candidates = [tag for tag in tags if tag.startswith(ctx.package_name)]

    if candidates is not None:
        ctx.last_release_committish = candidates[0]
        ctx.last_release_version = candidates[0].rsplit('-').pop()

    else:
        click.secho(
            f"I couldn't figure out the last release for {ctx.package_name}, "
            "so I'm assuming this is the first release. Can you tell me "
            "which git rev/sha to start the changelog at?",
            fg='yellow')
        ctx.last_release_committish = click.prompt('Committish')
        ctx.last_release_version = '0.0.0'

    click.secho(
        f"The last release was {ctx.last_release_version}.")


def gather_changes(ctx: Context) -> None:
    click.secho(
        f'> Gathering changes since {ctx.last_release_version}', fg='cyan')
    ctx.changes = releasetool.git.summary_log(ctx.last_release_committish)
    click.secho(f'Cool, {len(ctx.changes)} changes found.')


def edit_release_notes(ctx: Context) -> None:
    click.secho(
        f'> Opening your editor to finalize release notes.', fg='cyan')
    release_notes = '\n'.join(f'- {change}' for change in ctx.changes)
    ctx.release_notes = releasetool.filehelpers.open_editor_with_tempfile(
        release_notes,
        'release-notes.md').strip()


def determine_release_version(ctx: Context) -> None:
    click.secho(
        f"> Now it's time to pick a release version!", fg='cyan')
    release_notes = textwrap.indent(ctx.release_notes, '\t')
    click.secho(
        f"Here's the release notes you wrote:\n\n{release_notes}\n")

    parsed_version = [int(x) for x in ctx.last_release_version.split('.')]

    if parsed_version == [0, 0, 0]:
        ctx.release_version = '0.1.0'
        return

    selection = click.prompt(
        'Is this a major, minor, or patch update (or enter the new version '
        'directly)')
    if selection == 'major':
        parsed_version[0] += 1
        parsed_version[1] = 0
        parsed_version[2] = 0
    elif selection == 'minor':
        parsed_version[1] += 1
        parsed_version[2] = 0
    elif selection == 'patch':
        parsed_version[2] += 1
    else:
        ctx.release_version = selection
        return

    ctx.release_version = '{}.{}.{}'.format(*parsed_version)

    click.secho(f'Got it, releasing {ctx.release_version}.')


def create_release_branch(ctx) -> None:
    ctx.release_branch = f'release-{ctx.package_name}-{ctx.release_version}'
    click.secho(
        f"> Creating branch {ctx.release_branch}", fg='cyan')
    return releasetool.git.checkout_create_branch(ctx.release_branch)


def update_changelog(ctx: Context) -> None:
    changelog_filename = 'CHANGELOG.md'
    click.secho(
        f"> Updating {changelog_filename}.", fg='cyan')

    if not os.path.exists(changelog_filename):
        print(
            f'{changelog_filename} does not yet exist. Opening it for '
            'creation.')

        releasetool.filehelpers.open_editor_with_content(
            changelog_filename, _CHANGELOG_TEMPLATE)

    changelog_entry = (
        f'## {ctx.release_version}'
        f'\n\n'
        f'{ctx.release_notes}'
        f'\n\n')
    releasetool.filehelpers.insert_before(
        changelog_filename, changelog_entry, '^## (.+)$|\Z')


def update_setup_py(ctx: Context) -> None:
    click.secho(
        "> Updating setup.py.", fg='cyan')
    releasetool.filehelpers.replace(
        'setup.py', r"version='(.+?)',", f"version='{ctx.release_version}',")


def create_release_commit(ctx: Context) -> None:
    """Create a release commit."""
    click.secho(
        "> Comitting changes", fg='cyan')
    releasetool.git.commit(
        ['CHANGELOG.md', 'setup.py'],
        f'Release {ctx.release_version}')


def push_release_branch(ctx: Context) -> None:
    click.secho(
        "> Pushing release branch.", fg='cyan')
    releasetool.git.push(ctx.release_branch)


def create_release_pr(ctx: Context) -> None:
    click.secho(
        f"> Creating release pull request.", fg='cyan')
    ctx.pull_request = ctx.github.create_pull_request(
        ctx.github_repo,
        branch=ctx.release_branch,<commit_msg>Fix regex for release version<commit_after>import getpass
import os
import textwrap
from typing import Sequence

import attr
import click

import releasetool.filehelpers
import releasetool.git
import releasetool.github
import releasetool.secrets


_CHANGELOG_TEMPLATE = """\
# Changelog

[PyPI History][1]

[1]: https://pypi.org/project/DISTRIBUTION NAME/#history

"""


@attr.s(auto_attribs=True, slots=True)
class Context:
    github: releasetool.github.GitHub = None
    github_repo: str = None
    package_name: str = None
    last_release_version: str = None
    last_release_committish: str = None
    changes: Sequence[str] = ()
    release_notes: str = None
    release_version: str = None
    release_branch: str = None
    pull_request: dict = None


def setup_context(ctx: Context) -> None:
    click.secho('> Determining basic context.', fg='cyan')
    github_token = releasetool.secrets.get_password('github')
    ctx.github = releasetool.github.GitHub(github_token)
    ctx.github_repo = releasetool.git.get_github_repo_name()
    click.secho(f'GitHub Repo: {ctx.github_repo}')


def determine_package_name(ctx: Context) -> None:
    click.secho('> Figuring out the package name.', fg='cyan')
    ctx.package_name = os.path.basename(os.getcwd())
    click.secho(
        f"Looks like we're releasing {ctx.package_name}.")


def determine_last_release(ctx: Context) -> None:
    click.secho('> Figuring out what the last release was.', fg='cyan')
    tags = releasetool.git.list_tags()
    candidates = [tag for tag in tags if tag.startswith(ctx.package_name)]

    if candidates is not None:
        ctx.last_release_committish = candidates[0]
        ctx.last_release_version = candidates[0].rsplit('-').pop()

    else:
        click.secho(
            f"I couldn't figure out the last release for {ctx.package_name}, "
            "so I'm assuming this is the first release. Can you tell me "
            "which git rev/sha to start the changelog at?",
            fg='yellow')
        ctx.last_release_committish = click.prompt('Committish')
        ctx.last_release_version = '0.0.0'

    click.secho(
        f"The last release was {ctx.last_release_version}.")


def gather_changes(ctx: Context) -> None:
    click.secho(
        f'> Gathering changes since {ctx.last_release_version}', fg='cyan')
    ctx.changes = releasetool.git.summary_log(ctx.last_release_committish)
    click.secho(f'Cool, {len(ctx.changes)} changes found.')


def edit_release_notes(ctx: Context) -> None:
    click.secho(
        f'> Opening your editor to finalize release notes.', fg='cyan')
    release_notes = '\n'.join(f'- {change}' for change in ctx.changes)
    ctx.release_notes = releasetool.filehelpers.open_editor_with_tempfile(
        release_notes,
        'release-notes.md').strip()


def determine_release_version(ctx: Context) -> None:
    click.secho(
        f"> Now it's time to pick a release version!", fg='cyan')
    release_notes = textwrap.indent(ctx.release_notes, '\t')
    click.secho(
        f"Here's the release notes you wrote:\n\n{release_notes}\n")

    parsed_version = [int(x) for x in ctx.last_release_version.split('.')]

    if parsed_version == [0, 0, 0]:
        ctx.release_version = '0.1.0'
        return

    selection = click.prompt(
        'Is this a major, minor, or patch update (or enter the new version '
        'directly)')
    if selection == 'major':
        parsed_version[0] += 1
        parsed_version[1] = 0
        parsed_version[2] = 0
    elif selection == 'minor':
        parsed_version[1] += 1
        parsed_version[2] = 0
    elif selection == 'patch':
        parsed_version[2] += 1
    else:
        ctx.release_version = selection
        return

    ctx.release_version = '{}.{}.{}'.format(*parsed_version)

    click.secho(f'Got it, releasing {ctx.release_version}.')


def create_release_branch(ctx) -> None:
    ctx.release_branch = f'release-{ctx.package_name}-{ctx.release_version}'
    click.secho(
        f"> Creating branch {ctx.release_branch}", fg='cyan')
    return releasetool.git.checkout_create_branch(ctx.release_branch)


def update_changelog(ctx: Context) -> None:
    changelog_filename = 'CHANGELOG.md'
    click.secho(
        f"> Updating {changelog_filename}.", fg='cyan')

    if not os.path.exists(changelog_filename):
        print(
            f'{changelog_filename} does not yet exist. Opening it for '
            'creation.')

        releasetool.filehelpers.open_editor_with_content(
            changelog_filename, _CHANGELOG_TEMPLATE)

    changelog_entry = (
        f'## {ctx.release_version}'
        f'\n\n'
        f'{ctx.release_notes}'
        f'\n\n')
    releasetool.filehelpers.insert_before(
        changelog_filename, changelog_entry, '^## (.+)$|\Z')


def update_setup_py(ctx: Context) -> None:
    click.secho(
        "> Updating setup.py.", fg='cyan')
    releasetool.filehelpers.replace(
        'setup.py',
        r"version = '(.+?)',",
        f"version = '{ctx.release_version}',")


def create_release_commit(ctx: Context) -> None:
    """Create a release commit."""
    click.secho(
        "> Comitting changes", fg='cyan')
    releasetool.git.commit(
        ['CHANGELOG.md', 'setup.py'],
        f'Release {ctx.release_version}')


def push_release_branch(ctx: Context) -> None:
    click.secho(
        "> Pushing release branch.", fg='cyan')
    releasetool.git.push(ctx.release_branch)


def create_release_pr(ctx: Context) -> None:
    click.secho(
        f"> Creating release pull request.", fg='cyan')
    ctx.pull_request = ctx.github.create_pull_request(
        ctx.github_repo,
        branch=ctx.release_branch,
{'fraction_non_alphanumeric': 0.12741792369121563, 'fraction_numerical': 0.0044365572315882874, 'mean_word_length': 3.133113311331133, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 51, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4211652', 'n_tokens_mistral': 3764, 'n_tokens_neox': 3671, 'n_words': 814}