git-pandas 2.1.0__tar.gz → 2.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {git_pandas-2.1.0 → git_pandas-2.2.0}/CHANGELOG.md +8 -0
- {git_pandas-2.1.0 → git_pandas-2.2.0}/PKG-INFO +1 -1
- git_pandas-2.2.0/docs/source/cache.rst +121 -0
- {git_pandas-2.1.0 → git_pandas-2.2.0}/docs/source/project.rst +19 -15
- {git_pandas-2.1.0 → git_pandas-2.2.0}/docs/source/repository.rst +17 -2
- {git_pandas-2.1.0 → git_pandas-2.2.0}/docs/source/usecases.rst +48 -34
- {git_pandas-2.1.0 → git_pandas-2.2.0}/gitpandas/project.py +188 -162
- {git_pandas-2.1.0 → git_pandas-2.2.0}/gitpandas/repository.py +116 -32
- {git_pandas-2.1.0 → git_pandas-2.2.0}/pyproject.toml +1 -1
- git_pandas-2.1.0/docs/source/cache.rst +0 -74
- {git_pandas-2.1.0 → git_pandas-2.2.0}/.cursor/rules/project_overview.mdc +0 -0
- {git_pandas-2.1.0 → git_pandas-2.2.0}/.cursor/rules/pytest_standards.mdc +0 -0
- {git_pandas-2.1.0 → git_pandas-2.2.0}/.cursor/rules/python_standards.mdc +0 -0
- {git_pandas-2.1.0 → git_pandas-2.2.0}/.cursor/rules/sphinx_docs_standards.mdc +0 -0
- {git_pandas-2.1.0 → git_pandas-2.2.0}/.cursor/rules/testing.mdc +0 -0
- {git_pandas-2.1.0 → git_pandas-2.2.0}/.github/ISSUE_TEMPLATE.md +0 -0
- {git_pandas-2.1.0 → git_pandas-2.2.0}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {git_pandas-2.1.0 → git_pandas-2.2.0}/.github/workflows/docs.yml +0 -0
- {git_pandas-2.1.0 → git_pandas-2.2.0}/.github/workflows/pypi-publish.yml +0 -0
- {git_pandas-2.1.0 → git_pandas-2.2.0}/.github/workflows/test-docs-build.yml +0 -0
- {git_pandas-2.1.0 → git_pandas-2.2.0}/.github/workflows/test-suite.yml +0 -0
- {git_pandas-2.1.0 → git_pandas-2.2.0}/.gitignore +0 -0
- {git_pandas-2.1.0 → git_pandas-2.2.0}/CONTRIBUTING.md +0 -0
- {git_pandas-2.1.0 → git_pandas-2.2.0}/LICENSE.md +0 -0
- {git_pandas-2.1.0 → git_pandas-2.2.0}/Makefile +0 -0
- {git_pandas-2.1.0 → git_pandas-2.2.0}/README.md +0 -0
- {git_pandas-2.1.0 → git_pandas-2.2.0}/docs/Makefile +0 -0
- {git_pandas-2.1.0 → git_pandas-2.2.0}/docs/make.bat +0 -0
- {git_pandas-2.1.0 → git_pandas-2.2.0}/docs/requirements.txt +0 -0
- {git_pandas-2.1.0 → git_pandas-2.2.0}/docs/source/conf.py +0 -0
- {git_pandas-2.1.0 → git_pandas-2.2.0}/docs/source/contributors.rst +0 -0
- {git_pandas-2.1.0 → git_pandas-2.2.0}/docs/source/index.rst +0 -0
- {git_pandas-2.1.0 → git_pandas-2.2.0}/examples/__init__.py +0 -0
- {git_pandas-2.1.0 → git_pandas-2.2.0}/examples/attributes.py +0 -0
- {git_pandas-2.1.0 → git_pandas-2.2.0}/examples/bus_analysis.py +0 -0
- {git_pandas-2.1.0 → git_pandas-2.2.0}/examples/cloud_repo.py +0 -0
- {git_pandas-2.1.0 → git_pandas-2.2.0}/examples/commit_history.py +0 -0
- {git_pandas-2.1.0 → git_pandas-2.2.0}/examples/cumulative_blame.py +0 -0
- {git_pandas-2.1.0 → git_pandas-2.2.0}/examples/definitions.py +0 -0
- {git_pandas-2.1.0 → git_pandas-2.2.0}/examples/file_change_rates.py +0 -0
- {git_pandas-2.1.0 → git_pandas-2.2.0}/examples/hours_estimate.py +0 -0
- {git_pandas-2.1.0 → git_pandas-2.2.0}/examples/img/cumulative_blame.png +0 -0
- {git_pandas-2.1.0 → git_pandas-2.2.0}/examples/img/cumulative_project_blame.png +0 -0
- {git_pandas-2.1.0 → git_pandas-2.2.0}/examples/img/githubblame.png +0 -0
- {git_pandas-2.1.0 → git_pandas-2.2.0}/examples/img/lifeline.png +0 -0
- {git_pandas-2.1.0 → git_pandas-2.2.0}/examples/img/stravalib_cumulative_blame.png +0 -0
- {git_pandas-2.1.0 → git_pandas-2.2.0}/examples/lifeline.py +0 -0
- {git_pandas-2.1.0 → git_pandas-2.2.0}/examples/parallel_blame.py +0 -0
- {git_pandas-2.1.0 → git_pandas-2.2.0}/examples/project_blame.py +0 -0
- {git_pandas-2.1.0 → git_pandas-2.2.0}/examples/punchcard.py +0 -0
- {git_pandas-2.1.0 → git_pandas-2.2.0}/examples/repo_file_detail.py +0 -0
- {git_pandas-2.1.0 → git_pandas-2.2.0}/gitpandas/__init__.py +0 -0
- {git_pandas-2.1.0 → git_pandas-2.2.0}/gitpandas/cache.py +0 -0
- {git_pandas-2.1.0 → git_pandas-2.2.0}/gitpandas/utilities/__init__.py +0 -0
- {git_pandas-2.1.0 → git_pandas-2.2.0}/gitpandas/utilities/check_api.py +0 -0
- {git_pandas-2.1.0 → git_pandas-2.2.0}/gitpandas/utilities/plotting.py +0 -0
- {git_pandas-2.1.0 → git_pandas-2.2.0}/img/cumulative_blame.png +0 -0
- {git_pandas-2.1.0 → git_pandas-2.2.0}/img/lifeline.png +0 -0
- {git_pandas-2.1.0 → git_pandas-2.2.0}/img/punchcard.png +0 -0
- {git_pandas-2.1.0 → git_pandas-2.2.0}/tests/__init__.py +0 -0
- {git_pandas-2.1.0 → git_pandas-2.2.0}/tests/conftest.py +0 -0
- {git_pandas-2.1.0 → git_pandas-2.2.0}/tests/test_Project/__init__.py +0 -0
- {git_pandas-2.1.0 → git_pandas-2.2.0}/tests/test_Project/test_advanced.py +0 -0
- {git_pandas-2.1.0 → git_pandas-2.2.0}/tests/test_Project/test_properties.py +0 -0
- {git_pandas-2.1.0 → git_pandas-2.2.0}/tests/test_Repository/__init__.py +0 -0
- {git_pandas-2.1.0 → git_pandas-2.2.0}/tests/test_Repository/test_advanced.py +0 -0
- {git_pandas-2.1.0 → git_pandas-2.2.0}/tests/test_Repository/test_bus_factor.py +0 -0
- {git_pandas-2.1.0 → git_pandas-2.2.0}/tests/test_Repository/test_file_detail.py +0 -0
- {git_pandas-2.1.0 → git_pandas-2.2.0}/tests/test_Repository/test_properties.py +0 -0
- {git_pandas-2.1.0 → git_pandas-2.2.0}/tests/test_Repository/test_punchcard.py +0 -0
- {git_pandas-2.1.0 → git_pandas-2.2.0}/tests/test_cache.py +0 -0
- {git_pandas-2.1.0 → git_pandas-2.2.0}/tests/test_examples.py +0 -0
- {git_pandas-2.1.0 → git_pandas-2.2.0}/tests/test_utilities/test_check_api.py +0 -0
- {git_pandas-2.1.0 → git_pandas-2.2.0}/tests/test_utilities/test_init.py +0 -0
- {git_pandas-2.1.0 → git_pandas-2.2.0}/tests/test_utilities/test_plotting.py +0 -0
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
v2.2.0
|
|
2
|
+
======
|
|
3
|
+
|
|
4
|
+
* Support for default branch setting instead of assuming master, will infer if not passed
|
|
5
|
+
* Better handling of ignore repos in project directory setup
|
|
6
|
+
* Added a branch exists helper in repository
|
|
7
|
+
* Docs corrections
|
|
8
|
+
|
|
1
9
|
v2.1.0
|
|
2
10
|
======
|
|
3
11
|
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
Caching
|
|
2
|
+
=======
|
|
3
|
+
|
|
4
|
+
Git-Pandas supports pluggable cache backends to optimize performance for expensive, repetitive operations. This is particularly useful for large repositories or when running multiple analyses.
|
|
5
|
+
|
|
6
|
+
Overview
|
|
7
|
+
--------
|
|
8
|
+
|
|
9
|
+
The caching system provides:
|
|
10
|
+
* In-memory caching for temporary results
|
|
11
|
+
* Redis-based caching for persistent storage
|
|
12
|
+
* Configurable cache durations
|
|
13
|
+
* Automatic cache invalidation
|
|
14
|
+
* Decorator-based caching for expensive operations
|
|
15
|
+
|
|
16
|
+
Available Cache Backends
|
|
17
|
+
----------------------
|
|
18
|
+
|
|
19
|
+
In-Memory Cache (EphemeralCache)
|
|
20
|
+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
21
|
+
|
|
22
|
+
The default in-memory cache is ephemeral and will be cleared when the process ends:
|
|
23
|
+
|
|
24
|
+
.. code-block:: python
|
|
25
|
+
|
|
26
|
+
from gitpandas import Repository
|
|
27
|
+
from gitpandas.cache import EphemeralCache
|
|
28
|
+
|
|
29
|
+
# Create an in-memory cache with default settings
|
|
30
|
+
cache = EphemeralCache()
|
|
31
|
+
|
|
32
|
+
# Or customize the cache size
|
|
33
|
+
cache = EphemeralCache(max_keys=500)
|
|
34
|
+
|
|
35
|
+
# Use the cache with a repository
|
|
36
|
+
repo = Repository('/path/to/repo', cache_backend=cache)
|
|
37
|
+
|
|
38
|
+
Redis Cache (RedisDFCache)
|
|
39
|
+
~~~~~~~~~~~~~~~~~~~~~~~
|
|
40
|
+
|
|
41
|
+
For persistent caching across sessions, use Redis:
|
|
42
|
+
|
|
43
|
+
.. code-block:: python
|
|
44
|
+
|
|
45
|
+
from gitpandas import Repository
|
|
46
|
+
from gitpandas.cache import RedisDFCache
|
|
47
|
+
|
|
48
|
+
# Create a Redis cache with default settings
|
|
49
|
+
cache = RedisDFCache()
|
|
50
|
+
|
|
51
|
+
# Or customize Redis connection and cache settings
|
|
52
|
+
cache = RedisDFCache(
|
|
53
|
+
host='localhost',
|
|
54
|
+
port=6379,
|
|
55
|
+
db=12,
|
|
56
|
+
max_keys=1000,
|
|
57
|
+
ttl=3600 # Cache entries expire after 1 hour
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
# Use the cache with a repository
|
|
61
|
+
repo = Repository('/path/to/repo', cache_backend=cache)
|
|
62
|
+
|
|
63
|
+
Using the Cache Decorator
|
|
64
|
+
----------------------
|
|
65
|
+
|
|
66
|
+
The `@multicache` decorator can be used to cache method results:
|
|
67
|
+
|
|
68
|
+
.. code-block:: python
|
|
69
|
+
|
|
70
|
+
from gitpandas.cache import multicache
|
|
71
|
+
|
|
72
|
+
@multicache(
|
|
73
|
+
key_prefix="method_name",
|
|
74
|
+
key_list=["param1", "param2"],
|
|
75
|
+
skip_if=lambda x: x.get("param1") is None
|
|
76
|
+
)
|
|
77
|
+
def expensive_method(self, param1, param2):
|
|
78
|
+
# Method implementation
|
|
79
|
+
pass
|
|
80
|
+
|
|
81
|
+
Configuration
|
|
82
|
+
------------
|
|
83
|
+
|
|
84
|
+
Cache backends can be configured with various parameters:
|
|
85
|
+
|
|
86
|
+
EphemeralCache:
|
|
87
|
+
* ``max_keys``: Maximum number of keys to store in memory (default: 1000)
|
|
88
|
+
|
|
89
|
+
RedisDFCache:
|
|
90
|
+
* ``host``: Redis host (default: 'localhost')
|
|
91
|
+
* ``port``: Redis port (default: 6379)
|
|
92
|
+
* ``db``: Redis database number (default: 12)
|
|
93
|
+
* ``max_keys``: Maximum number of keys to store (default: 1000)
|
|
94
|
+
* ``ttl``: Time-to-live in seconds for cache entries (default: None, no expiration)
|
|
95
|
+
* Additional keyword arguments are passed to redis.StrictRedis
|
|
96
|
+
|
|
97
|
+
API Reference
|
|
98
|
+
------------
|
|
99
|
+
|
|
100
|
+
.. currentmodule:: gitpandas.cache
|
|
101
|
+
|
|
102
|
+
.. autoclass:: CacheBackend
|
|
103
|
+
:members:
|
|
104
|
+
:undoc-members:
|
|
105
|
+
:show-inheritance:
|
|
106
|
+
:inherited-members:
|
|
107
|
+
:special-members: __init__, __getitem__, __setitem__, __delitem__, __contains__, __len__
|
|
108
|
+
|
|
109
|
+
.. autoclass:: EphemeralCache
|
|
110
|
+
:members:
|
|
111
|
+
:undoc-members:
|
|
112
|
+
:show-inheritance:
|
|
113
|
+
:inherited-members:
|
|
114
|
+
|
|
115
|
+
.. autoclass:: RedisDFCache
|
|
116
|
+
:members:
|
|
117
|
+
:undoc-members:
|
|
118
|
+
:show-inheritance:
|
|
119
|
+
:inherited-members:
|
|
120
|
+
|
|
121
|
+
.. autofunction:: multicache
|
|
@@ -26,15 +26,20 @@ Create a ProjectDirectory from a directory containing multiple repositories:
|
|
|
26
26
|
.. code-block:: python
|
|
27
27
|
|
|
28
28
|
from gitpandas import ProjectDirectory
|
|
29
|
-
project = ProjectDirectory(
|
|
29
|
+
project = ProjectDirectory(
|
|
30
|
+
working_dir='/path/to/dir/',
|
|
31
|
+
ignore_repos=['repo_to_ignore'],
|
|
32
|
+
verbose=True,
|
|
33
|
+
default_branch='main' # Optional, will auto-detect if not specified
|
|
34
|
+
)
|
|
30
35
|
|
|
31
|
-
The `
|
|
36
|
+
The `ignore_repos` parameter can be a list of repository names to exclude. This method uses `os.walk` to search for `.git` directories recursively.
|
|
32
37
|
|
|
33
38
|
To check which repositories are included:
|
|
34
39
|
|
|
35
40
|
.. code-block:: python
|
|
36
41
|
|
|
37
|
-
print(project.
|
|
42
|
+
print(project.repo_name())
|
|
38
43
|
|
|
39
44
|
Explicit Local Repositories
|
|
40
45
|
~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
@@ -46,8 +51,9 @@ Create a ProjectDirectory from a list of local repositories:
|
|
|
46
51
|
from gitpandas import ProjectDirectory
|
|
47
52
|
project = ProjectDirectory(
|
|
48
53
|
working_dir=['/path/to/repo1/', '/path/to/repo2/'],
|
|
49
|
-
|
|
50
|
-
verbose=True
|
|
54
|
+
ignore_repos=['repo_to_ignore'],
|
|
55
|
+
verbose=True,
|
|
56
|
+
default_branch='main' # Optional, will auto-detect if not specified
|
|
51
57
|
)
|
|
52
58
|
|
|
53
59
|
Explicit Remote Repositories
|
|
@@ -60,8 +66,9 @@ Create a ProjectDirectory from a list of remote repositories:
|
|
|
60
66
|
from gitpandas import ProjectDirectory
|
|
61
67
|
project = ProjectDirectory(
|
|
62
68
|
working_dir=['git://github.com/user/repo1.git', 'git://github.com/user/repo2.git'],
|
|
63
|
-
|
|
64
|
-
verbose=True
|
|
69
|
+
ignore_repos=['repo_to_ignore'],
|
|
70
|
+
verbose=True,
|
|
71
|
+
default_branch='main' # Optional, will auto-detect if not specified
|
|
65
72
|
)
|
|
66
73
|
|
|
67
74
|
Common Operations
|
|
@@ -72,7 +79,7 @@ Here are some common operations you can perform with a ProjectDirectory object:
|
|
|
72
79
|
.. code-block:: python
|
|
73
80
|
|
|
74
81
|
# Get commit history across all repositories
|
|
75
|
-
commits_df = project.commit_history(
|
|
82
|
+
commits_df = project.commit_history()
|
|
76
83
|
|
|
77
84
|
# Get blame information across all repositories
|
|
78
85
|
blame_df = project.blame()
|
|
@@ -85,6 +92,9 @@ Here are some common operations you can perform with a ProjectDirectory object:
|
|
|
85
92
|
|
|
86
93
|
# Get file change history across all repositories
|
|
87
94
|
changes_df = project.file_change_history()
|
|
95
|
+
|
|
96
|
+
# Get detailed repository information
|
|
97
|
+
repo_info = project.repo_information()
|
|
88
98
|
|
|
89
99
|
API Reference
|
|
90
100
|
------------
|
|
@@ -110,11 +120,5 @@ API Reference
|
|
|
110
120
|
~ProjectDirectory.tags
|
|
111
121
|
~ProjectDirectory.revs
|
|
112
122
|
~ProjectDirectory.bus_factor
|
|
113
|
-
~ProjectDirectory.
|
|
114
|
-
~ProjectDirectory.has_coverage
|
|
115
|
-
|
|
116
|
-
.. rubric:: Properties
|
|
117
|
-
|
|
118
|
-
.. autosummary::
|
|
119
|
-
:nosignatures:
|
|
123
|
+
~ProjectDirectory.repo_information
|
|
120
124
|
~ProjectDirectory.repo_name
|
|
@@ -26,7 +26,11 @@ Create a Repository from a local Git repository:
|
|
|
26
26
|
.. code-block:: python
|
|
27
27
|
|
|
28
28
|
from gitpandas import Repository
|
|
29
|
-
repo = Repository(
|
|
29
|
+
repo = Repository(
|
|
30
|
+
working_dir='/path/to/repo/',
|
|
31
|
+
verbose=True,
|
|
32
|
+
default_branch='main' # Optional, will auto-detect if not specified
|
|
33
|
+
)
|
|
30
34
|
|
|
31
35
|
The directory must contain a `.git` directory. Subdirectories are not searched.
|
|
32
36
|
|
|
@@ -38,7 +42,11 @@ Create a Repository from a remote Git repository:
|
|
|
38
42
|
.. code-block:: python
|
|
39
43
|
|
|
40
44
|
from gitpandas import Repository
|
|
41
|
-
repo = Repository(
|
|
45
|
+
repo = Repository(
|
|
46
|
+
working_dir='git://github.com/user/repo.git',
|
|
47
|
+
verbose=True,
|
|
48
|
+
default_branch='main' # Optional, will auto-detect if not specified
|
|
49
|
+
)
|
|
42
50
|
|
|
43
51
|
The repository will be cloned locally into a temporary directory. This can be slow for large repositories.
|
|
44
52
|
|
|
@@ -63,6 +71,9 @@ Here are some common operations you can perform with a Repository object:
|
|
|
63
71
|
|
|
64
72
|
# Get file change history
|
|
65
73
|
changes_df = repo.file_change_history()
|
|
74
|
+
|
|
75
|
+
# Get repository name
|
|
76
|
+
repo_name = repo.repo_name
|
|
66
77
|
|
|
67
78
|
API Reference
|
|
68
79
|
------------
|
|
@@ -90,12 +101,16 @@ API Reference
|
|
|
90
101
|
~Repository.bus_factor
|
|
91
102
|
~Repository.is_bare
|
|
92
103
|
~Repository.has_coverage
|
|
104
|
+
~Repository.has_branch
|
|
105
|
+
~Repository.get_branches_by_commit
|
|
106
|
+
~Repository.commits_in_tags
|
|
93
107
|
|
|
94
108
|
.. rubric:: Properties
|
|
95
109
|
|
|
96
110
|
.. autosummary::
|
|
97
111
|
:nosignatures:
|
|
98
112
|
~Repository.repo_name
|
|
113
|
+
~Repository.default_branch
|
|
99
114
|
|
|
100
115
|
.. autoclass:: GitFlowRepository
|
|
101
116
|
:members:
|
|
@@ -17,7 +17,7 @@ Get basic information about a repository:
|
|
|
17
17
|
repo = Repository('/path/to/repo')
|
|
18
18
|
|
|
19
19
|
# Get repository name
|
|
20
|
-
print(repo.
|
|
20
|
+
print(repo.repo_name)
|
|
21
21
|
|
|
22
22
|
# Check if repository is bare
|
|
23
23
|
print(repo.is_bare())
|
|
@@ -52,6 +52,9 @@ Analyze commit patterns and history:
|
|
|
52
52
|
|
|
53
53
|
# Filter by directory
|
|
54
54
|
src_changes = repo.file_change_history(include_globs=['src/*'])
|
|
55
|
+
|
|
56
|
+
# Get commits in tags
|
|
57
|
+
tag_commits = repo.commits_in_tags()
|
|
55
58
|
|
|
56
59
|
Project-Level Analysis
|
|
57
60
|
--------------------
|
|
@@ -71,17 +74,17 @@ Analyze multiple repositories simultaneously:
|
|
|
71
74
|
'git://github.com/user/repo2.git'
|
|
72
75
|
])
|
|
73
76
|
|
|
74
|
-
# Get
|
|
75
|
-
print(project.
|
|
77
|
+
# Get repository information
|
|
78
|
+
print(project.repo_information())
|
|
76
79
|
|
|
77
80
|
# Calculate bus factor
|
|
78
81
|
print(project.bus_factor())
|
|
79
82
|
|
|
80
|
-
# Get file change
|
|
81
|
-
print(project.
|
|
83
|
+
# Get file change history
|
|
84
|
+
print(project.file_change_history())
|
|
82
85
|
|
|
83
|
-
#
|
|
84
|
-
print(project.
|
|
86
|
+
# Get blame information
|
|
87
|
+
print(project.blame())
|
|
85
88
|
|
|
86
89
|
Advanced Analysis
|
|
87
90
|
---------------
|
|
@@ -96,7 +99,7 @@ Track code ownership over time:
|
|
|
96
99
|
# Get cumulative blame
|
|
97
100
|
blame_df = repo.cumulative_blame()
|
|
98
101
|
|
|
99
|
-
# Plot cumulative blame
|
|
102
|
+
# Plot cumulative blame using pandas plotting
|
|
100
103
|
import matplotlib.pyplot as plt
|
|
101
104
|
blame_df.plot(x='date', y='loc', title='Cumulative Blame Over Time')
|
|
102
105
|
plt.show()
|
|
@@ -108,14 +111,14 @@ Analyze project sustainability:
|
|
|
108
111
|
|
|
109
112
|
.. code-block:: python
|
|
110
113
|
|
|
111
|
-
# Calculate bus factor
|
|
112
|
-
bus_factor =
|
|
114
|
+
# Calculate bus factor for repository
|
|
115
|
+
bus_factor = repo.bus_factor()
|
|
113
116
|
|
|
114
|
-
# Get detailed
|
|
115
|
-
|
|
117
|
+
# Get detailed blame information
|
|
118
|
+
blame_df = repo.blame(by='file') # Get file-level blame details
|
|
116
119
|
|
|
117
|
-
# Analyze
|
|
118
|
-
|
|
120
|
+
# Analyze ownership patterns
|
|
121
|
+
ownership_patterns = repo.blame(committer=True, by='repository')
|
|
119
122
|
|
|
120
123
|
Performance Optimization
|
|
121
124
|
---------------------
|
|
@@ -127,33 +130,40 @@ Optimize performance with caching:
|
|
|
127
130
|
|
|
128
131
|
.. code-block:: python
|
|
129
132
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
# Use
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
133
|
+
from gitpandas import Repository
|
|
134
|
+
from gitpandas.cache import EphemeralCache, RedisDFCache
|
|
135
|
+
|
|
136
|
+
# Use in-memory caching
|
|
137
|
+
cache = EphemeralCache()
|
|
138
|
+
repo = Repository('/path/to/repo', cache_backend=cache)
|
|
139
|
+
|
|
140
|
+
# Or use Redis for persistent caching
|
|
141
|
+
redis_cache = RedisDFCache(
|
|
142
|
+
host='localhost',
|
|
143
|
+
port=6379,
|
|
144
|
+
db=12,
|
|
145
|
+
ttl=3600 # Cache entries expire after 1 hour
|
|
139
146
|
)
|
|
147
|
+
repo = Repository('/path/to/repo', cache_backend=redis_cache)
|
|
140
148
|
|
|
141
149
|
Visualization Examples
|
|
142
150
|
-------------------
|
|
143
151
|
|
|
144
|
-
Commit
|
|
152
|
+
Commit Analysis
|
|
145
153
|
~~~~~~~~~~~~~
|
|
146
154
|
|
|
147
155
|
Visualize commit patterns:
|
|
148
156
|
|
|
149
157
|
.. code-block:: python
|
|
150
158
|
|
|
151
|
-
#
|
|
152
|
-
|
|
159
|
+
# Get commit history
|
|
160
|
+
commit_df = repo.commit_history()
|
|
153
161
|
|
|
154
|
-
# Plot
|
|
155
|
-
|
|
156
|
-
|
|
162
|
+
# Plot commits over time using pandas
|
|
163
|
+
commit_df.resample('D').size().plot(
|
|
164
|
+
kind='bar',
|
|
165
|
+
title='Commits per Day'
|
|
166
|
+
)
|
|
157
167
|
plt.show()
|
|
158
168
|
|
|
159
169
|
File Change Analysis
|
|
@@ -166,17 +176,21 @@ Visualize file changes:
|
|
|
166
176
|
# Get file change history
|
|
167
177
|
changes_df = repo.file_change_history()
|
|
168
178
|
|
|
169
|
-
# Plot changes over time
|
|
170
|
-
changes_df.
|
|
179
|
+
# Plot changes over time using pandas
|
|
180
|
+
changes_df.groupby('filename')['insertions'].sum().plot(
|
|
181
|
+
kind='bar',
|
|
182
|
+
title='Lines Added by File'
|
|
183
|
+
)
|
|
171
184
|
plt.show()
|
|
172
185
|
|
|
173
186
|
Best Practices
|
|
174
187
|
------------
|
|
175
188
|
|
|
176
|
-
* Use caching for expensive operations
|
|
177
|
-
* Filter data early
|
|
189
|
+
* Use caching for expensive operations like blame analysis
|
|
190
|
+
* Filter data early using include_globs/ignore_globs
|
|
178
191
|
* Leverage pandas operations for analysis
|
|
179
192
|
* Consider memory usage with large repositories
|
|
180
|
-
* Use appropriate
|
|
193
|
+
* Use appropriate branch names (main/master)
|
|
194
|
+
* Handle repository cleanup properly when using remote repositories
|
|
181
195
|
|
|
182
196
|
For more examples and detailed API documentation, see the :doc:`repository` and :doc:`project` pages.
|