Skip to content

Commit

Permalink
Merge branch 'master' of github.com:ishepard/pydriller
Browse files Browse the repository at this point in the history
  • Loading branch information
ishepard committed Mar 19, 2020
2 parents cd50857 + c0e29b2 commit e602aa5
Show file tree
Hide file tree
Showing 18 changed files with 315 additions and 40 deletions.
18 changes: 18 additions & 0 deletions docs/processmetrics.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ Process Metrics
Process metrics capture aspects of the development process rather than aspects about the code itself.
From release 1.11 PyDriller can calculate ``change_set``, ``code churn``, ``commits count``, ``contributors count``, ``contributors experience``, ``history complexity``, ``hunks count``, ``lines count`` and ``minor contributors``. Everything in just one line!

The metrics can be run between two commits (setting up the parameters ``from_commit`` and ``to_commit``) or between two dates (setting up the parameters ``since`` and ``to``)

Below an example of how call the metrics.


Expand Down Expand Up @@ -37,6 +39,22 @@ will print the maximum and average number of files committed together in the evo
**Note:** differently from the other metrics below, the scope of this metrics is the evolution period rather than the single files.


It is possible to specify the dates as follows::

from datetime import datetime
from pydriller.metrics.process.change_set import ChangeSet
metric = ChangeSet(path_to_repo='path/to/the/repo',
since=datetime(2019, 1, 1),
to=datetime(2019, 12, 31))
maximum = metric.max()
average = metric.avg()
print('Maximum number of files committed together: {}'.format(maximum))
print('Average number of files committed together: {}'.format(average))

The code above will print the maximum and average number of files committed together between the ``1st January 2019`` and ``31st December 2019``.


Code Churn
==========

Expand Down
9 changes: 6 additions & 3 deletions pydriller/metrics/process/change_set.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,12 @@ class ChangeSet(ProcessMetric):
"""

def __init__(self, path_to_repo: str,
from_commit: str,
to_commit: str):
super().__init__(path_to_repo, from_commit, to_commit)
since = None,
to = None,
from_commit: str = None,
to_commit: str = None):

super().__init__(path_to_repo, since=since, to=to, from_commit=from_commit, to_commit=to_commit)
self._initialize()

def _initialize(self):
Expand Down
9 changes: 6 additions & 3 deletions pydriller/metrics/process/code_churn.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,12 @@ class CodeChurn(ProcessMetric):
"""

def __init__(self, path_to_repo: str,
from_commit: str,
to_commit: str):
super().__init__(path_to_repo, from_commit, to_commit)
since = None,
to = None,
from_commit: str = None,
to_commit: str = None):

super().__init__(path_to_repo, since=since, to=to, from_commit=from_commit, to_commit=to_commit)
self._initialize()

def _initialize(self):
Expand Down
9 changes: 6 additions & 3 deletions pydriller/metrics/process/contributors_count.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,12 @@ class ContributorsCount(ProcessMetric):
"""

def __init__(self, path_to_repo: str,
from_commit: str,
to_commit: str):
super().__init__(path_to_repo, from_commit, to_commit)
since = None,
to = None,
from_commit: str = None,
to_commit: str = None):

super().__init__(path_to_repo, since=since, to=to, from_commit=from_commit, to_commit=to_commit)
self._initialize()

def _initialize(self):
Expand Down
9 changes: 6 additions & 3 deletions pydriller/metrics/process/lines_count.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,12 @@ class LinesCount(ProcessMetric):
"""

def __init__(self, path_to_repo: str,
from_commit: str,
to_commit: str):
super().__init__(path_to_repo, from_commit, to_commit)
since = None,
to = None,
from_commit: str = None,
to_commit: str = None):

super().__init__(path_to_repo, since=since, to=to, from_commit=from_commit, to_commit=to_commit)
self._initialize()

def _initialize(self):
Expand Down
34 changes: 24 additions & 10 deletions pydriller/metrics/process/process_metric.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
This module contains the abstract class to implement process metrics.
"""

from datetime import datetime
from pydriller import RepositoryMining

class ProcessMetric:
Expand All @@ -10,22 +11,35 @@ class ProcessMetric:
"""

def __init__(self, path_to_repo: str,
from_commit: str,
to_commit: str):
since: datetime = None,
to: datetime = None,
from_commit: str = None,
to_commit: str = None):
"""
:path_to_repo: path to a single repo
:to_commit: the SHA of the commit to stop counting. If None, the
analysis starts from the latest commit
:from_commit: the SHA of the commit to start counting. If None, the
analysis ends to the first commit
:param datetime since: starting date
:param datetime to: ending date
:param str from_commit: starting commit (only if `since` is None)
:param str to_commit: ending commit (only if `to` is None)
"""
if not from_commit or not to_commit:
raise TypeError

self.repo_miner = RepositoryMining(path_to_repo, single=from_commit)
if not since and not from_commit:
raise TypeError('You must pass one between since and from_commit')

if not to and not to_commit:
raise TypeError('You must pass one between to and to_commit')

if from_commit and to_commit and from_commit == to_commit: # Use 'single' param to avoid Warning
self.repo_miner = RepositoryMining(path_to_repo, single=from_commit)

if from_commit != to_commit:
else:
self.repo_miner = RepositoryMining(path_to_repo=path_to_repo,
since=since,
to=to,
from_commit=from_commit,
to_commit=to_commit,
order='reverse')
Expand Down
20 changes: 19 additions & 1 deletion tests/metrics/process/test_change_set.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import pytest
from datetime import datetime
from pydriller.metrics.process.change_set import ChangeSet

TEST_DATA = [
('test-repos/pydriller', 'ab36bf45859a210b0eae14e17683f31d19eea041', '71e053f61fc5d31b3e31eccd9c79df27c31279bf', 13, 8)
]

@pytest.mark.parametrize('path_to_repo, from_commit, to_commit, expected_max, expected_avg', TEST_DATA)
def test(path_to_repo, from_commit, to_commit, expected_max, expected_avg):
def test_with_commits(path_to_repo, from_commit, to_commit, expected_max, expected_avg):
metric = ChangeSet(path_to_repo=path_to_repo,
from_commit=from_commit,
to_commit=to_commit)
Expand All @@ -16,3 +17,20 @@ def test(path_to_repo, from_commit, to_commit, expected_max, expected_avg):

assert actual_max == expected_max
assert actual_avg == expected_avg


TEST_DATA = [
('test-repos/pydriller', datetime(2018, 3, 21), datetime(2018, 3, 27), 13, 8)
]

@pytest.mark.parametrize('path_to_repo, since, to, expected_max, expected_avg', TEST_DATA)
def test_with_dates(path_to_repo, since, to, expected_max, expected_avg):
metric = ChangeSet(path_to_repo=path_to_repo,
since=since,
to=to)

actual_max = metric.max()
actual_avg = metric.avg()

assert actual_max == expected_max
assert actual_avg == expected_avg
29 changes: 27 additions & 2 deletions tests/metrics/process/test_code_churn.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
import pytest
from pathlib import Path
from datetime import datetime

import pytest

from pydriller.metrics.process.code_churn import CodeChurn

TEST_DATA = [
('test-repos/pydriller', 'domain/commit.py', 'ab36bf45859a210b0eae14e17683f31d19eea041', '71e053f61fc5d31b3e31eccd9c79df27c31279bf', 47, 34, 16)
]

@pytest.mark.parametrize('path_to_repo, filepath, from_commit, to_commit, expected_count, expected_max, expected_avg', TEST_DATA)
def test(path_to_repo, filepath, from_commit, to_commit, expected_count, expected_max, expected_avg):
def test_with_commits(path_to_repo, filepath, from_commit, to_commit, expected_count, expected_max, expected_avg):
metric = CodeChurn(path_to_repo=path_to_repo,
from_commit=from_commit,
to_commit=to_commit)
Expand All @@ -21,3 +24,25 @@ def test(path_to_repo, filepath, from_commit, to_commit, expected_count, expecte
assert actual_count[filepath] == expected_count
assert actual_max[filepath] == expected_max
assert actual_avg[filepath] == expected_avg


TEST_DATA = [
('test-repos/pydriller', 'domain/commit.py', datetime(2018, 3, 21), datetime(2018, 3, 27), 47, 34, 16)
]

@pytest.mark.parametrize('path_to_repo, filepath, since, to, expected_count, expected_max, expected_avg', TEST_DATA)
def test_with_dates(path_to_repo, filepath, since, to, expected_count, expected_max, expected_avg):
metric = CodeChurn(path_to_repo=path_to_repo,
since=since,
to=to)

actual_count = metric.count()
actual_max = metric.max()
actual_avg = metric.avg()

filepath = str(Path(filepath))

assert actual_count[filepath] == expected_count
assert actual_max[filepath] == expected_max
assert actual_avg[filepath] == expected_avg

18 changes: 16 additions & 2 deletions tests/metrics/process/test_commits_count.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from pathlib import Path
from datetime import datetime

import pytest

Expand All @@ -9,13 +10,26 @@
('test-repos/pydriller', 'domain/developer.py', 'ab36bf45859a210b0eae14e17683f31d19eea041', 'fdf671856b260aca058e6595a96a7a0fba05454b', 2)
]


@pytest.mark.parametrize('path_to_repo, filepath, from_commit, '
'to_commit, expected', TEST_DATA)
def test(path_to_repo, filepath, from_commit, to_commit, expected):
def test_with_commits(path_to_repo, filepath, from_commit, to_commit, expected):
metric = CommitsCount(path_to_repo=path_to_repo,
from_commit=from_commit,
to_commit=to_commit)
count = metric.count()
filepath = str(Path(filepath))
assert count[filepath] == expected


TEST_DATA = [
('test-repos/pydriller', 'domain/developer.py', datetime(2018, 3, 21), datetime(2018, 3, 23), 2)
]
@pytest.mark.parametrize('path_to_repo, filepath, since, '
'to, expected', TEST_DATA)
def test_with_dates(path_to_repo, filepath, since, to, expected):
metric = CommitsCount(path_to_repo=path_to_repo,
since=since,
to=to)
count = metric.count()
filepath = str(Path(filepath))
assert count[filepath] == expected
18 changes: 17 additions & 1 deletion tests/metrics/process/test_contributors_count.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from pathlib import Path
from datetime import datetime

import pytest

Expand All @@ -10,11 +11,26 @@
]

@pytest.mark.parametrize('path_to_repo, filepath, from_commit, to_commit, expected', TEST_DATA)
def test(path_to_repo, filepath, from_commit, to_commit, expected):
def test_with_commits(path_to_repo, filepath, from_commit, to_commit, expected):
metric = ContributorsCount(path_to_repo=path_to_repo,
from_commit=from_commit,
to_commit=to_commit)

count = metric.count()
filepath = str(Path(filepath))
assert count[filepath] == expected

TEST_DATA = [
('test-repos/pydriller', 'pydriller/git_repository.py', datetime(2019, 12, 17), datetime(2019, 12, 24), 2),
('test-repos/pydriller', 'domain/modification.py', datetime(2018, 3, 21), datetime(2018, 3, 27), 1)
]

@pytest.mark.parametrize('path_to_repo, filepath, since, to, expected', TEST_DATA)
def test_with_dates(path_to_repo, filepath, since, to, expected):
metric = ContributorsCount(path_to_repo=path_to_repo,
since=since,
to=to)

count = metric.count()
filepath = str(Path(filepath))
assert count[filepath] == expected
19 changes: 18 additions & 1 deletion tests/metrics/process/test_contributors_experience_count.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from pathlib import Path
from datetime import datetime

import pytest

Expand All @@ -12,10 +13,26 @@
]

@pytest.mark.parametrize('path_to_repo, filepath, from_commit, to_commit, expected', TEST_DATA)
def test(path_to_repo, filepath, from_commit, to_commit, expected):
def test_with_commits(path_to_repo, filepath, from_commit, to_commit, expected):
metric = ContributorsExperience(path_to_repo=path_to_repo,
from_commit=from_commit,
to_commit=to_commit)
count = metric.count()
filepath = str(Path(filepath))
assert count[filepath] == expected


TEST_DATA = [
('test-repos/pydriller', 'domain/modification.py', datetime(2018, 3, 21), datetime(2018, 3, 23), 100.0),
('test-repos/pydriller', 'pydriller/git_repository.py', datetime(2018, 8, 1), datetime(2018, 8, 2), 100.0),
('test-repos/pydriller', 'pydriller/git_repository.py', datetime(2018, 7, 23), datetime(2018, 8, 2), round(100*28/30, 2))
]

@pytest.mark.parametrize('path_to_repo, filepath, since, to, expected', TEST_DATA)
def test_with_dates(path_to_repo, filepath, since, to, expected):
metric = ContributorsExperience(path_to_repo=path_to_repo,
since=since,
to=to)
count = metric.count()
filepath = str(Path(filepath))
assert count[filepath] == expected
20 changes: 18 additions & 2 deletions tests/metrics/process/test_history_complexity_count.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from pathlib import Path
from datetime import datetime

import pytest

from pydriller.metrics.process.history_complexity import HistoryComplexity

TEST_DATA = [
Expand All @@ -11,11 +11,27 @@
]

@pytest.mark.parametrize('path_to_repo, filepath, from_commit, to_commit, expected', TEST_DATA)
def test(path_to_repo, filepath, from_commit, to_commit, expected):
def test_with_commits(path_to_repo, filepath, from_commit, to_commit, expected):
metric = HistoryComplexity(path_to_repo=path_to_repo,
from_commit=from_commit,
to_commit=to_commit)

count = metric.count()
filepath = str(Path(filepath))
assert count[filepath] == expected


TEST_DATA = [
('test-repos/pydriller', 'scm/git_repository.py', datetime(2018, 3, 22, 11, 30), datetime(2018, 3, 23), 40.49),
('test-repos/pydriller', 'scm/git_repository.py', datetime(2018, 3, 22, 11, 30), datetime(2018, 3, 27), 47.05),
]

@pytest.mark.parametrize('path_to_repo, filepath, since, to, expected', TEST_DATA)
def test_with_dates(path_to_repo, filepath, since, to, expected):
metric = HistoryComplexity(path_to_repo=path_to_repo,
since=since,
to=to)

count = metric.count()
filepath = str(Path(filepath))
assert count[filepath] == expected
Loading

0 comments on commit e602aa5

Please sign in to comment.