Python git.Actor() Examples

The following are 25 code examples of git.Actor(). You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may also want to check out all available functions/classes of the module git , or try the search function .
Example #1
Source File: test_hooks_slack.py    From crane with MIT License 6 votes vote down vote up
def test_generate_new_message(monkeypatch, repo, commits, expected):
    monkeypatch.setenv("CI_ENVIRONMENT_URL", "example.com")

    old_version = repo.head.commit.hexsha
    for commit in commits:
        repo.index.commit(commit, author=Actor("test_author", "test@test.com"))

    fake_deployment = Deployment(
        repo=repo,
        new_version="HEAD",
        old_version=old_version,
        stack=rancher.Stack("0st0", "foo"),
    )
    monkeypatch.setattr(uut, "deployment", fake_deployment)

    slack_hook = uut.Hook()
    slack_hook.get_changelog = lambda: ""
    slack_hook.users_by_email = {"picky@kiwi.com": "@picky"}

    msg = slack_hook.generate_new_message()
    expected["text"] = slack_hook.deployment_text
    assert msg == expected 
Example #2
Source File: test_rank.py    From wily with Apache License 2.0 6 votes vote down vote up
def test_rank_directory_default_unindexed_revision(builddir):
    """ Test the rank feature with an unindexed revision. """
    repo = Repo(builddir)
    with open(builddir / "test.py", "w") as test_txt:
        test_txt.write("import abc")

    index = repo.index
    index.add([str(builddir / "test.py")])

    author = Actor("An author", "author@example.com")
    committer = Actor("A committer", "committer@example.com")

    commit = index.commit(
        "unindexed commit",
        author=author,
        committer=committer,
        author_date="Thu, 28 Apr 2019 22:13:13 +0200",
        commit_date="Thu, 28 Apr 2019 22:13:13 +0200",
    )
    runner = CliRunner()
    result = runner.invoke(main.cli, ["--path", builddir, "rank", "-r", commit.hexsha])
    assert result.exit_code == 1, result.stdout 
Example #3
Source File: conftest.py    From renku-python with Apache License 2.0 6 votes vote down vote up
def data_repository(directory_tree):
    """Create a test repo."""
    from git import Repo, Actor
    # initialize
    repo = Repo.init(directory_tree.strpath)

    # add a file
    repo.index.add([directory_tree.join('file').strpath])
    repo.index.commit('test commit', author=Actor('me', 'me@example.com'))

    # commit changes to the same file with a different user
    directory_tree.join('file').write('5678')
    repo.index.add([directory_tree.join('file').strpath])
    repo.index.commit('test commit', author=Actor('me2', 'me2@example.com'))

    # commit a second file
    repo.index.add([directory_tree.join('dir2/file2').strpath])
    repo.index.commit('test commit', author=Actor('me', 'me@example.com'))

    # return the repo
    return repo 
Example #4
Source File: m_0005__2_cwl.py    From renku-python with Apache License 2.0 5 votes vote down vote up
def _migrate_old_workflows(client):
    """Migrates old cwl workflows to new jsonld format."""
    wf_path = '{}/*.cwl'.format(client.workflow_path)

    cwl_paths = glob.glob(wf_path)

    cwl_paths = [(p, _find_only_cwl_commit(client, p)) for p in cwl_paths]

    cwl_paths = sorted(cwl_paths, key=lambda p: p[1].committed_date)

    for cwl_file, commit in cwl_paths:
        path = _migrate_cwl(client, cwl_file, commit)
        os.remove(cwl_file)

        client.repo.git.add(cwl_file, path)

        if client.repo.is_dirty():
            commit_msg = ('renku migrate: ' 'committing migrated workflow')

            committer = Actor('renku {0}'.format(__version__), version_url)

            client.repo.index.commit(
                commit_msg,
                committer=committer,
                skip_hooks=True,
            ) 
Example #5
Source File: test_hooks_slack.py    From crane with MIT License 5 votes vote down vote up
def test_get_changelog_force_push(monkeypatch, repo, commits, expected):
    old_version = "0000000000000000000000000000000000000000"
    for commit in commits:
        repo.index.commit(commit, author=Actor("test_author", "test@test.com"))

    fake_deployment = Deployment(repo=repo, new_version="HEAD", old_version=old_version)
    monkeypatch.setattr(uut, "deployment", fake_deployment)

    slack_hook = uut.Hook()
    slack_hook.users_by_email = {}

    changelog = slack_hook.get_changelog()
    assert re.fullmatch(expected, changelog) 
Example #6
Source File: test_hooks_slack.py    From crane with MIT License 5 votes vote down vote up
def test_get_changelog(monkeypatch, repo, commits, expected):
    old_version = repo.head.commit.hexsha
    for commit in commits:
        repo.index.commit(commit, author=Actor("test_author", "test@test.com"))

    fake_deployment = Deployment(repo=repo, new_version="HEAD", old_version=old_version)
    monkeypatch.setattr(uut, "deployment", fake_deployment)

    slack_hook = uut.Hook()
    slack_hook.users_by_email = {}

    changelog = slack_hook.get_changelog()
    assert re.fullmatch(expected, changelog) 
Example #7
Source File: test_hooks_slack.py    From crane with MIT License 5 votes vote down vote up
def test_get_existing_messages(monkeypatch, mocker, repo, slack_response, result):
    old_version = repo.head.commit.hexsha
    for commit in ["1"]:
        repo.index.commit(commit, author=Actor("test_author", "test@test.com"))

    fake_deployment = Deployment(repo=repo, new_version="HEAD", old_version=old_version)
    monkeypatch.setattr(uut, "deployment", fake_deployment)
    slack_hook = uut.Hook()
    slack_hook.channel_ids = ["123", "asd"]
    fake_get = mocker.patch.object(uut.session, "get")
    fake_response = mocker.Mock()
    fake_response.json = lambda: {"messages": []}
    fake_get.return_value = fake_response

    with pytest.raises(KeyError):
        slack_hook.get_existing_messages()

    deployment_id = f"<{uut.deployment.id}.com| >"

    fake_response.json = lambda: {
        "messages": [
            {"text": deployment_id, "attachments": [{"fields": []}]},
            {"text": "colemak", "attachments": [{"fields": []}]},
        ]
    }
    messages = slack_hook.get_existing_messages()
    assert len(messages) == 2
    assert messages["123"]["text"] == deployment_id
    assert messages["asd"]["attachments"][0]["fields"] == uut.AttachmentFields([]) 
Example #8
Source File: test_hooks_slack.py    From crane with MIT License 5 votes vote down vote up
def test_get_existing_message(monkeypatch, mocker, repo, slack_response, result):
    old_version = repo.head.commit.hexsha
    for commit in ["1"]:
        repo.index.commit(commit, author=Actor("test_author", "test@test.com"))

    fake_deployment = Deployment(repo=repo, new_version="HEAD", old_version=old_version)
    monkeypatch.setattr(uut, "deployment", fake_deployment)
    slack_hook = uut.Hook()
    slack_hook.channel_ids = ["123"]
    fake_get = mocker.patch.object(uut.session, "get")
    fake_response = mocker.Mock()
    fake_response.json = lambda: {"messages": []}
    fake_get.return_value = fake_response

    with pytest.raises(KeyError):
        slack_hook.get_existing_message("123")

    deployment_id = f"<{uut.deployment.id}.com| >"

    fake_response.json = lambda: {
        "messages": [
            {"text": deployment_id, "attachments": [{"fields": []}]},
            {"text": "colemak", "attachments": [{"fields": []}]},
        ]
    }
    assert slack_hook.get_existing_message("123")["text"] == deployment_id
    assert slack_hook.get_existing_message("123")["attachments"][0][
        "fields"
    ] == uut.AttachmentFields([]) 
Example #9
Source File: test_hooks_slack.py    From crane with MIT License 5 votes vote down vote up
def repo():
    ts = datetime(2018, 1, 1, 0, 0, 0).isoformat()
    with tempfile.TemporaryDirectory() as repo_dir:
        repo = git.Repo.init(repo_dir)
        repo.index.commit(
            "Initial commit",
            author=Actor("test_author", "test@test.com"),
            commit_date=ts,
        )
        yield repo 
Example #10
Source File: utils.py    From fabric8-analytics-server with Apache License 2.0 5 votes vote down vote up
def push_repo(token, local_repo, remote_repo, author_name=None, author_email=None,
              user=None, organization=None, auto_remove=False):
    """Initialize a git repo and push the code to the target repo."""
    commit_msg = 'Initial commit'
    if not os.path.exists(local_repo):
        raise ValueError("Directory {} does not exist.".format(local_repo))
    repo = Repo.init(local_repo)
    repo.git.add(all=True)
    # TODO: "openshiftio-launchpad" -> config module
    # TODO: "obsidian-leadership@redhat.com" -> config module
    committer = Actor(author_name or os.getenv("GIT_COMMIT_AUTHOR_NAME", "openshiftio-launchpad"),
                      author_email or os.getenv("GIT_COMMIT_AUTHOR_EMAIL",
                                                "obsidian-leadership@redhat.com"))

    # TODO: refactor this code into new function
    if organization is None:
        # try to fetch user instead of organization
        try:
            organization = Github(token).get_user().login
        except RateLimitExceededException:
            raise HTTPError(403, "Github API rate limit exceeded")
        except BadCredentialsException:
            raise HTTPError(401, "Invalid github access token")
        except Exception as exc:
            raise HTTPError(500, "Unable to get the username {}".format(str(exc)))

    repo.index.commit(commit_msg, committer=committer, author=committer)
    remote_uri = 'https://{user}:{token}@github.com/{user}/{remote_repo}'\
        .format(user=organization, token=token, remote_repo=remote_repo)
    try:
        origin = repo.create_remote('origin', remote_uri)
        origin.push('master')
    except Exception as exc:
        raise HTTPError(500, "Unable to Push the code: {}".format(str(exc.stderr)))
    finally:
        if auto_remove and os.path.exists(local_repo):
            shutil.rmtree(local_repo) 
Example #11
Source File: gitutil.py    From cc-utils with Apache License 2.0 5 votes vote down vote up
def index_to_commit(self, message, parent_commits=None):
        '''moves all diffs from worktree to a new commit without modifying branches.
        The worktree remains unchanged after the method returns.

        @param parent_commits: optional iterable of parent commits; head is used if absent
        @return the git.Commit object representing the newly created commit
        '''
        if not parent_commits:
            parent_commits = [self.repo.head.commit]
        # add all changes
        git.cmd.Git(self.repo.working_tree_dir).add('.')
        tree = self.repo.index.write_tree()

        if self.github_cfg:
            credentials = self.github_cfg.credentials()
            author = git.objects.util.Actor(credentials.username(), credentials.email_address())
            committer = git.objects.util.Actor(credentials.username(), credentials.email_address())

            create_commit = functools.partial(
                git.Commit.create_from_tree,
                author=author,
                committer=committer,
            )
        else:
            create_commit = git.Commit.create_from_tree

        commit = create_commit(
            repo=self.repo,
            tree=tree,
            parent_commits=parent_commits,
            message=message
        )
        self.repo.index.reset()
        return commit 
Example #12
Source File: wiki.py    From redmine-gitlab-migrator with GNU General Public License v3.0 5 votes vote down vote up
def convert(self, redmine_page):
        title = (self.textile_converter.normalize(redmine_page["title"])
                 if 'parent' in redmine_page
                 else 'home')
        print("Converting {} ({} version {})".format(title, redmine_page["title"], redmine_page["version"]))

        text = redmine_page.get('text', "")

        # create a copy of the original page (for comparison, will not be committed)
        file_name = title + ".textile"
        with open(self.repo_path + "/" + file_name, mode='wt', encoding='utf-8') as fd:
            print(text, file=fd)

        # replace some contents
        text = text.replace("{{lastupdated_at}}", redmine_page["updated_on"])
        text = text.replace("{{lastupdated_by}}", redmine_page["author"]["name"])
        text = text.replace("[[PageOutline]]", "")
        text = text.replace("{{>toc}}", "")

        text = self.textile_converter.convert(text)

        # save file with author/date
        file_name = title + ".md"
        with open(self.repo_path + "/" + file_name, mode='wt', encoding='utf-8') as fd:
            print(text.replace('\n', "\n"), file=fd)

        # todo: check for attachments
        # todo: upload attachments

        if redmine_page["comments"]:
            commit_msg = redmine_page["comments"] + " (" + title + " v" + str(redmine_page["version"]) + ")";
        else:
            commit_msg = title + ", version " + str(redmine_page["version"]);

        author = Actor(redmine_page["author"]["name"], "")
        time   = redmine_page["updated_on"].replace("T", " ").replace("Z", " +0000")

        self.repo.index.add([file_name])
        self.repo.index.commit(commit_msg, author=author, committer=author, author_date=time, commit_date=time) 
Example #13
Source File: pr_from_new_release.py    From mattermost-openshift with GNU General Public License v3.0 5 votes vote down vote up
def patch_and_push(dfp, repository, target_branch, release_version):
    """patch the Dockerfile and push the created branch to origin"""

    # lets create a new branch
    new_branch = repository.create_head(target_branch)
    new_branch.checkout()

    # set dockerfile version to release version
    dfp.envs['MATTERMOST_VERSION'] = release_version
    dfp.envs['MATTERMOST_VERSION_SHORT'] = release_version.replace('.', '')

    # and write back the Dockerfile
    with open('./mattermost-openshift-workdir/Dockerfile', 'w') as f:
        f.write(dfp.content)
        f.close()

    # commit our work
    repository.index.add(['Dockerfile'])
    author = Actor('Mattermost Server Updater Bot', 'goern+bot@b4mad.net')
    committer = Actor('Mattermost Server Updater Bot', 'goern+bot@b4mad.net')
    repository.index.commit("Update to Mattermost " + release_version,
                            author=author, committer=committer)

    # and push to origin
    with repository.git.custom_environment(GIT_SSH_COMMAND=SSH_CMD):
        repository.remotes.origin.push(refspec='{}:{}'.format(
            target_branch, target_branch)) 
Example #14
Source File: repository.py    From builds with GNU General Public License v3.0 5 votes vote down vote up
def commit_changes(self, commit_message, committer_name, committer_email):
        """
        Commit all changes made to the repository.

        Args:
            commit_message (str): message describing the commit
            committer_name (str): committer name
            committer_email (str): committer email
        """
        LOG.info("Adding files to repository index")
        self.index.add(["*"])

        LOG.info("Committing changes to local repository")
        actor = git.Actor(committer_name, committer_email)
        self.index.commit(commit_message, author=actor, committer=actor) 
Example #15
Source File: test_submodule.py    From git-hammer with Apache License 2.0 5 votes vote down vote up
def setUp(self):
        super().setUp()
        git.Repo.clone_from(os.path.join(self.current_directory, 'data', 'repository'),
                            os.path.join(self.working_directory.name, 'worktree'))
        repository = git.Repo(os.path.join(self.working_directory.name, 'worktree'))
        git.Submodule.add(repository, 'subrepo', 'subrepo',
                          os.path.join(self.current_directory, 'data', 'subrepository'))
        author = git.Actor('Author A', 'a@example.com')
        repository.index.commit('Add subrepo', author=author) 
Example #16
Source File: test_archiver.py    From wily with Apache License 2.0 5 votes vote down vote up
def test_detached_head(tmpdir):
    """ Check that repo can initialize in detached head state"""
    repo = Repo.init(path=tmpdir)
    tmppath = pathlib.Path(tmpdir)

    index = repo.index
    author = Actor("An author", "author@example.com")
    committer = Actor("A committer", "committer@example.com")

    # First commit
    with open(tmppath / "test.py", "w") as ignore:
        ignore.write("print('hello world')")

    index.add(["test.py"])
    commit1 = index.commit("commit1", author=author, committer=committer)

    # Second commit
    with open(tmppath / "test.py", "w") as ignore:
        ignore.write("print('hello world')\nprint(1)")

    index.add(["test.py"])
    commit2 = index.commit("commit2", author=author, committer=committer)

    repo.git.checkout(commit2.hexsha)
    repo.close()

    config = DEFAULT_CONFIG
    config.path = tmpdir

    archiver = GitArchiver(config)
    assert archiver.revisions(tmpdir, 1) is not None 
Example #17
Source File: test_archiver.py    From wily with Apache License 2.0 5 votes vote down vote up
def test_dirty_git(tmpdir):
    """ Check that repository fails to initialise if unchecked files are in the repo """
    repo = Repo.init(path=tmpdir)
    tmppath = pathlib.Path(tmpdir)

    index = repo.index
    author = Actor("An author", "author@example.com")
    committer = Actor("A committer", "committer@example.com")

    # First commit
    with open(tmppath / ".gitignore", "w") as ignore:
        ignore.write(".wily/")

    index.add([".gitignore"])
    commit1 = index.commit("commit1", author=author, committer=committer)

    # Write a test file to the repo
    with open(tmppath / "blah.py", "w") as ignore:
        ignore.write("*.py[co]\n")
    index.add(["blah.py"])
    repo.close()

    config = DEFAULT_CONFIG
    config.path = tmpdir

    with pytest.raises(DirtyGitRepositoryError):
        archiver = GitArchiver(config)
        archiver.revisions(tmpdir, 2) 
Example #18
Source File: test_build.py    From wily with Apache License 2.0 5 votes vote down vote up
def test_build(tmpdir, cache_path):
    """
    Test that build works in a basic repository.
    """
    repo = Repo.init(path=tmpdir)
    tmppath = pathlib.Path(tmpdir)

    # Write a test file to the repo
    with open(tmppath / "test.py", "w") as test_txt:
        test_txt.write("import abc")

    index = repo.index
    index.add(["test.py"])

    author = Actor("An author", "author@example.com")
    committer = Actor("A committer", "committer@example.com")

    commit = index.commit("basic test", author=author, committer=committer)
    repo.close()

    runner = CliRunner()
    result = runner.invoke(
        main.cli,
        ["--debug", "--path", tmpdir, "--cache", cache_path, "build", "test.py"],
    )
    assert result.exit_code == 0, result.stdout

    cache_path = pathlib.Path(cache_path)
    assert cache_path.exists()
    index_path = cache_path / "git" / "index.json"
    assert index_path.exists()
    rev_path = cache_path / "git" / (commit.name_rev.split(" ")[0] + ".json")
    assert rev_path.exists() 
Example #19
Source File: test_build.py    From wily with Apache License 2.0 5 votes vote down vote up
def test_build_crash(tmpdir):
    """
    Simulate a runtime error in the build.
    """
    repo = Repo.init(path=tmpdir)
    tmppath = pathlib.Path(tmpdir)

    # Write a test file to the repo
    with open(tmppath / "test.py", "w") as test_txt:
        test_txt.write("import abc")

    index = repo.index
    index.add(["test.py"])

    author = Actor("An author", "author@example.com")
    committer = Actor("A committer", "committer@example.com")

    index.commit("basic test", author=author, committer=committer)
    repo.close()

    import wily.commands.build

    with patch.object(
        wily.commands.build.Bar, "finish", side_effect=RuntimeError("arggh")
    ) as bar_finish:
        runner = CliRunner()
        result = runner.invoke(main.cli, ["--path", tmpdir, "build", "test.py"])
        assert bar_finish.called_once
        assert result.exit_code == 1, result.stdout 
Example #20
Source File: githandler.py    From bioconda-utils with MIT License 5 votes vote down vote up
def set_user(self, user: str, email: str = None) -> None:
        """Set the user and email to use for committing"""
        self.actor = git.Actor(user, email) 
Example #21
Source File: githandler.py    From bioconda-utils with MIT License 5 votes vote down vote up
def __init__(self, repo: git.Repo,
                 dry_run: bool,
                 home='bioconda/bioconda-recipes',
                 fork=None,
                 allow_dirty=False) -> None:
        #: GitPython Repo object representing our repository
        self.repo: git.Repo = repo
        if not allow_dirty and self.repo.is_dirty():
            raise RuntimeError("Repository is in dirty state. Bailing out")
        #: Dry-Run mode - don't push or commit anything
        self.dry_run = dry_run
        #: Remote pointing to primary project repo
        self.home_remote = self.get_remote(home)
        if fork is not None:
            #: Remote to pull from
            self.fork_remote = self.get_remote(fork)
        else:
            self.fork_remote = self.home_remote

        #: Semaphore for things that mess with working directory
        self.lock_working_dir = asyncio.Semaphore(1)

        #: GPG key ID or bool, indicating whether/how to sign commits
        self._sign: Union[bool, str] = False

        #: Committer and Author
        self.actor: git.Actor = None 
Example #22
Source File: test_submodule.py    From git-hammer with Apache License 2.0 5 votes vote down vote up
def test_submodule_in_initial_commit_is_understood(self):
        submodule_repository = git.Repo.init(os.path.join(self.working_directory.name, 'initial_submodule'))
        git.Submodule.add(submodule_repository, 'subrepo', 'subrepo',
                          os.path.join(self.current_directory, 'data', 'subrepository'))
        author = git.Actor('Author B', 'b@example.com')
        submodule_repository.index.commit('Initial commit', author=author)
        self.hammer.add_repository(os.path.join(self.working_directory.name, 'initial_submodule'))
        commit = next(self.hammer.iter_individual_commits())
        self.assertEqual(commit.line_counts, {commit.author: 3}) 
Example #23
Source File: test_archiver.py    From wily with Apache License 2.0 4 votes vote down vote up
def test_git_end_to_end(tmpdir):
    """
    Complete end-to-end test of the git integration
    """
    repo = Repo.init(path=tmpdir)
    tmppath = pathlib.Path(tmpdir)

    index = repo.index
    author = Actor("An author", "author@example.com")
    committer = Actor("A committer", "committer@example.com")

    # First commit
    with open(tmppath / ".gitignore", "w") as ignore:
        ignore.write(".wily/")
    index.add([".gitignore"])
    commit1 = index.commit("commit1", author=author, committer=committer)

    # Second commit
    with open(tmppath / "test.py", "w") as file1:
        file1.write("print(1)")
    index.add(["test.py"])
    commit2 = index.commit("commit2", author=author, committer=committer)
    repo.close()

    config = DEFAULT_CONFIG
    config.path = tmpdir

    archiver = GitArchiver(config)
    assert archiver.config == config

    revisions = archiver.revisions(tmpdir, 3)
    assert len(revisions) == 2
    assert revisions[0].message == "commit2"
    assert revisions[0].author_email == "author@example.com"
    assert revisions[0].author_name == "An author"
    assert (
        revisions[0].key in commit2.name_rev
        and revisions[0].key not in commit1.name_rev
    )

    assert revisions[1].message == "commit1"
    assert revisions[1].author_email == "author@example.com"
    assert revisions[1].author_name == "An author"
    assert (
        revisions[1].key in commit1.name_rev
        and revisions[1].key not in commit2.name_rev
    )

    checkout = archiver.checkout(revisions[1], None)

    assert not (tmppath / "test.py").exists()

    finish = archiver.finish()

    assert (tmppath / "test.py").exists() 
Example #24
Source File: test_build.py    From wily with Apache License 2.0 4 votes vote down vote up
def test_build_with_config(tmpdir, cache_path):
    """
    Test that build works in a basic repository and a configuration file.
    """
    repo = Repo.init(path=tmpdir)
    tmppath = pathlib.Path(tmpdir)

    config = """
    [wily]
    path = test.py
    """
    config_path = tmppath / "wily.cfg"
    with open(config_path, "w") as config_f:
        config_f.write(config)

    # Write a test file to the repo
    with open(tmppath / "test.py", "w") as test_txt:
        test_txt.write("import abc")

    index = repo.index
    index.add(["test.py"])

    author = Actor("An author", "author@example.com")
    committer = Actor("A committer", "committer@example.com")

    commit = index.commit("basic test", author=author, committer=committer)
    repo.close()

    runner = CliRunner()
    result = runner.invoke(
        main.cli,
        [
            "--debug",
            "--config",
            config_path,
            "--path",
            tmpdir,
            "--cache",
            cache_path,
            "build",
        ],
    )
    assert result.exit_code == 0, result.stdout

    cache_path = pathlib.Path(cache_path)
    assert cache_path.exists()
    index_path = cache_path / "git" / "index.json"
    assert index_path.exists()
    rev_path = cache_path / "git" / (commit.name_rev.split(" ")[0] + ".json")
    assert rev_path.exists() 
Example #25
Source File: test_all_operators.py    From wily with Apache License 2.0 4 votes vote down vote up
def test_operator_on_code_with_metric_named_objects(operator, tmpdir):
    code_with_metric_named_objects = """

    # CyclomaticComplexity
    def complexity(): pass

    # Halstead
    def h1(): pass
    def h2(): pass
    def N1(): pass
    def N2(): pass
    def vocabulary(): pass
    def length(): pass
    def volume(): pass
    def difficulty(): pass
    def error(): pass

    # Maintainability
    def rank(): pass
    def mi(): pass

    # RawMetrics
    def loc(): pass
    def lloc(): pass
    def sloc(): pass
    def comments(): pass
    def multi(): pass
    def blank(): pass
    def single_comments(): pass

    """

    testpath = pathlib.Path(tmpdir) / "test.py"
    author = Actor("An author", "author@example.com")
    committer = Actor("A committer", "committer@example.com")

    with open(testpath, "w") as test_py:
        test_py.write(dedent(code_with_metric_named_objects))

    with Repo.init(path=tmpdir) as repo:
        repo.index.add(["test.py"])
        repo.index.commit("add test.py", author=author, committer=committer)

    runner = CliRunner()

    result = runner.invoke(
        main.cli,
        ["--debug", "--path", tmpdir, "build", str(testpath), "-o", operator],
        catch_exceptions=False,
    )
    assert result.exit_code == 0, result.stdout