Skip to content

Commit f50185d

Browse files
authored
Revise README with usage and custom metrics examples
Updated README to enhance usage instructions and add custom metrics section with examples.
1 parent 820a2d7 commit f50185d

File tree

1 file changed

+92
-1
lines changed

1 file changed

+92
-1
lines changed

README.md

Lines changed: 92 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ See more examples: [gitevo-examples](https://github.com/andrehora/gitevo-example
2424
pip install gitevo
2525
```
2626

27-
## Usage
27+
## Usage via command-line
2828

2929
Analyzing the evolution of a Git repository:
3030

@@ -80,3 +80,94 @@ options:
8080
-m, --month Set to analyze commits by month.
8181
-v, --version Show the GitEvo version.
8282
```
83+
84+
## Defining Custom Metrics
85+
86+
GitEvo can be used to define custom code evolution metrics at the level of the concrete syntax tree (CST).
87+
GitEvo provides three key classes that can be used in the scripts: `GitEvo`, `ParsedCommit`, and `ParsedFile`.
88+
89+
- `GitEvo` is the main class, the entry point to use the tool.
90+
It receives as input the repository, file extension, date unit for analysis, and start/end year for analysis.
91+
92+
- Metrics are defined in functions decorated with `@evo.metric()`.
93+
94+
- `ParsedCommit` represents a parsed commit and contains (1) a list of `ParsedFile` and (2) a list of [`tree_sitter.Node`](https://tree-sitter.github.io/py-tree-sitter/classes/tree_sitter.Node.html).
95+
96+
- `ParsedFile` represents a parsed file in a commit, including properties as name, path, and tree-sitter nodes.
97+
98+
### Examples
99+
100+
#### Basic metrics
101+
102+
```python
103+
from gitevo import GitEvo, ParsedCommit
104+
105+
remote = 'https://github.com/pallets/flask'
106+
evo = GitEvo(repo=remote, extension='.py')
107+
108+
@evo.metric('Lines of code (LOC)')
109+
def loc(commit: ParsedCommit):
110+
return commit.loc
111+
112+
@evo.metric('Python files')
113+
def python_files(commit: ParsedCommit):
114+
return len(commit.parsed_files)
115+
116+
@evo.metric('Test files')
117+
def test_files(commit: ParsedCommit):
118+
test_files = [f for f in commit.parsed_files if 'test_' in f.name.lower()]
119+
return len(test_files)
120+
121+
@evo.metric('LOC / Python files')
122+
def loc_per_file(commit: ParsedCommit):
123+
python_files = len(commit.parsed_files)
124+
if python_files == 0: return 0
125+
return commit.loc / python_files
126+
127+
evo.run()
128+
```
129+
130+
#### Metrics based on node types
131+
132+
```python
133+
from gitevo import GitEvo, ParsedCommit
134+
135+
remote = 'https://github.com/pallets/flask'
136+
evo = GitEvo(repo=remote, extension='.py')
137+
138+
@evo.metric('Data structures', categorical=True)
139+
def data_structures(commit: ParsedCommit):
140+
data_structure_types = ['dictionary', 'list', 'set', 'tuple']
141+
return commit.find_node_types(data_structure_types)
142+
143+
@evo.metric('Loops', categorical=True)
144+
def loops(commit: ParsedCommit):
145+
loop_types = ['for_statement', 'while_statement', 'for_in_clause']
146+
return commit.find_node_types(loop_types)
147+
148+
evo.run()
149+
```
150+
151+
#### Metrics based on node content
152+
153+
```python
154+
from gitevo import GitEvo, ParsedCommit
155+
156+
remote = 'https://github.com/pallets/flask'
157+
evo = GitEvo(repo=remote, extension='.py')
158+
159+
@evo.metric('Async functions')
160+
def async_functions(commit: ParsedCommit):
161+
functions = commit.find_nodes_by_type(['function_definition'])
162+
async_functions = [f for f in functions if as_str(f.child(0).text) == 'async']
163+
return len(async_functions)
164+
165+
@evo.metric('@pytest decorated functions')
166+
def decorated_functions(commit: ParsedCommit):
167+
decorators = commit.find_nodes_by_type(['decorated_definition'])
168+
decorated_functions = [d for d in decorators if d.child_by_field_name('definition').type == 'function_definition']
169+
pytest_decorated = [dc for dc in decorated_functions if as_str(dc.child(0).text).startswith('@pytest')]
170+
return len(pytest_decorated)
171+
172+
evo.run()
173+
```

0 commit comments

Comments
 (0)