Skip to content

Commit 7e650f0

Browse files
committed
docs(readme): add documentation about filename templates and call filtering
1 parent 400cf0a commit 7e650f0

File tree

1 file changed

+133
-0
lines changed

1 file changed

+133
-0
lines changed

README.md

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,139 @@ poetry add pydoctrace
7373
pipenv install pydoctrace
7474
```
7575

76+
## Usage
77+
78+
Import a decorator and apply it to the functions whom execution you want to trace:
79+
80+
```python
81+
# in my_package/my_module.py
82+
from pydoctrace.doctrace import trace_to_component_puml, trace_to_sequence_puml
83+
84+
def main(parameter):
85+
validate(parameter)
86+
do_something(parameter)
87+
88+
@trace_to_component_puml
89+
def validate(parameter):
90+
validate_is_not_none(parameter)
91+
validate_is_in_database(parameter)
92+
93+
@trace_to_sequence_puml
94+
def do_something(parameter):
95+
stuff = load_stuff(parameter)
96+
save_work(process_job(stuff))
97+
```
98+
99+
Executing `main()` will create 2 diagram files in the current working directory:
100+
101+
* `validate-component.puml`: a PlantUML **component** diagram showing the interactions between `validate()` as the start, and `validate_is_not_none()` and `validate_is_in_database()` (and all their inner function calls, if any)
102+
* `do_something-sequence.puml`: a PlantUML **sequence** diagram showing the interactions between `do_something()` as the start, and `load_stuff()`, `process_job()` and `save_work()` (and all their inner function calls, if any)
103+
104+
You can then view these files either:
105+
106+
* using an extension for your IDE: `jebbs.plantuml` for Codium / vsCode, `7017-plantuml-integration` for PyCharm
107+
* online at www.plantuml.com/plantuml/uml/
108+
109+
### Customize the filename
110+
111+
The `export_file_path_tpl` attribute of the decorators allows you to define another file path and name:
112+
113+
```python
114+
# in my_package/my_module.py
115+
from pydoctrace.doctrace import trace_to_component_puml, trace_to_sequence_puml
116+
117+
# will create a 'validate-component.puml' file in the 'doc/my_package-my_module' folder
118+
# (pydoctrace will create the subdirectories if necessary)
119+
@trace_to_component_puml(
120+
export_file_path_tpl='doc/my_package-my_module/validate-component.puml'
121+
)
122+
def validate(parameter):
123+
...
124+
125+
# will create a 'my_package.my_module/do_something-2024-02-27_19.16.09_473-sequence.puml' file
126+
@trace_to_sequence_puml(
127+
export_file_path_tpl='${function_module}/${function_name}-${datetime_millis}-sequence.puml'
128+
)
129+
def do_something(parameter):
130+
...
131+
```
132+
133+
As you can see, you can use the following template tags in the file name:
134+
135+
* `${function_module}`: which resolves to `do_something.__module__`, `'my_package.my_module'` in the example
136+
* `${function_name}`: which resolves to `do_something.__name__`, `'do_something'` in the example
137+
* `${datetime_millis}`: the datetime in ISO-ish format compatible with filenames (Windows does not support `':'` in filenames).
138+
If the traced function is called several times during the execution, including `${datetime_millis}` in the filename template will generate different files that won't overwrite themselves
139+
140+
### Filter what is traced
141+
142+
To keep the generated diagrams useful and legible, you probably want to exclude some calls from the tracing (such as calls to `print(...)` or `json.load(...)`).
143+
`pydoctrace` comes with ready-to-use [presets](pydoctrace/callfilter/presets.py) that you can combine to filter out some calls you do not want to document:
144+
145+
* `EXCLUDE_BUILTINS_PRESET`: prevents from tracing calls to [built-in functions](https://docs.python.org/3/library/functions.html) (`print`, `len`, `all`, `any`, etc.)
146+
* `EXCLUDE_STDLIB_PRESET`: prevents from tracing calls to all [the standard library modules](https://docs.python.org/3/library/index.html) (`csv`, `json`, `dataclass`, etc.)
147+
* `EXCLUDE_TESTS_PRESET`: prevents from tracing calls to functions belonging to the `tests`, `_pytest`, `pytest`, `unittest`, `doctest` modules.
148+
This one is particularly useful when you want to generate some documentation from an automated tests
149+
* `EXCLUDE_DEPTH_BELOW_5_PRESET`: prevents from tracing any calls that involve a call stack of more than five levels after the traced function
150+
151+
By default, `EXCLUDE_STDLIB_PRESET` and `EXCLUDE_TESTS_PRESET` are activated.
152+
Specify something else at the decorator level to change the call filtering.
153+
154+
```python
155+
from pydoctrace.doctrace import trace_to_component_puml
156+
from pydoctrace.callfilter.presets import (
157+
EXCLUDE_BUILTINS_PRESET,
158+
EXCLUDE_CALL_DEPTH_PRESET_FACTORY,
159+
EXCLUDE_DEPTH_BELOW_5_PRESET,
160+
EXCLUDE_STDLIB_PRESET,
161+
EXCLUDE_TESTS_PRESET,
162+
TRACE_ALL_PRESET,
163+
)
164+
165+
# an empty presets list traces everything
166+
@trace_to_component_puml(filter_presets=[])
167+
def validate(parameter):
168+
...
169+
# or you can be explicit
170+
from pydoctrace.callfilter.presets import TRACE_ALL_PRESET
171+
@trace_to_component_puml(filter_presets=[TRACE_ALL_PRESET])
172+
def validate(parameter):
173+
...
174+
175+
# filter at a custom callstack level
176+
from pydoctrace.callfilter.presets import EXCLUDE_CALL_DEPTH_PRESET_FACTORY
177+
ABOVE_3_PRESET = EXCLUDE_CALL_DEPTH_PRESET_FACTORY(3)
178+
@trace_to_component_puml(filter_presets=[ABOVE_3_PRESET])
179+
def call():
180+
call_1()
181+
182+
def call_1():
183+
call_2()
184+
185+
def call_2():
186+
call_3()
187+
188+
def call_3(): # will not be traced in the diagram
189+
...
190+
191+
# documents the behavior of do_something without the noise of
192+
# the test framework nor the standard libray
193+
from my_package.my_module import do_something
194+
from pydoctrace.callfilter.presets import EXCLUDE_STDLIB_PRESET, EXCLUDE_TESTS_PRESET
195+
@trace_to_component_puml(filter_presets=[EXCLUDE_STDLIB_PRESET, EXCLUDE_TESTS_PRESET])
196+
def test_do_something():
197+
assert do_something('param') is not None
198+
199+
# for test-generated documentation, you can also use the decorator programmatically
200+
def test_do_something():
201+
traceable_do_something = trace_to_component_puml(
202+
export_file_path_tpl='doc/${function_module}/${function_name}-component.puml',
203+
filter_presets=[EXCLUDE_STDLIB_PRESET, EXCLUDE_TESTS_PRESET, ABOVE_3_PRESET]
204+
)(do_something)
205+
206+
assert traceable_do_something('param') is not None
207+
```
208+
76209
## Purposes and mechanisms
77210

78211
The purpose of `pydoctrace` is to document the execution of some code to illustrate the behavior and the structure of the code base.

0 commit comments

Comments
 (0)