Skip to content

Commit 1b77054

Browse files
committed
ISSUE-011: Add development examples and README
- Add example scripts: basic_args.py, exceptions.py, classes_methods.py, recursion.py, generators_async.py, context_and_closures.py, threading.py, imports_side_effects.py, kwargs_nested.py. - Add examples/README.md with brief descriptions and CLI usage: `python -m codetracer_python_recorder --codetracer-format=json examples/<script>.py`. - Update issues.md to mark ISSUE-011 as Done with summary of changes.
1 parent 7fd416b commit 1b77054

File tree

11 files changed

+244
-1
lines changed

11 files changed

+244
-1
lines changed

examples/README.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
Examples for exercising the Rust‑backed recorder during development.
2+
3+
Run any script via the module CLI so tracing is consistently enabled:
4+
5+
python -m codetracer_python_recorder --codetracer-format=json examples/<script>.py
6+
7+
Scripts
8+
9+
- basic_args.py: Demonstrates positional‑only, pos‑or‑kw, kw‑only, *args, **kwargs.
10+
- exceptions.py: Raises, catches, and prints an exception in except.
11+
- classes_methods.py: Instance, @classmethod, @staticmethod, and a property.
12+
- recursion.py: Direct recursion (factorial) and mutual recursion.
13+
- generators_async.py: A generator, async function, and async generator.
14+
- context_and_closures.py: A context manager and a nested closure.
15+
- threading.py: Two threads invoking traced functions and joining.
16+
- imports_side_effects.py: Module‑level side effects vs main guard.
17+
- kwargs_nested.py: Nested kwargs structure to validate structured encoding.
18+
19+
All scripts are deterministic and print minimal output.
20+

examples/basic_args.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
"""Example: function with all Python argument kinds.
2+
3+
Covers positional-only, positional-or-keyword, keyword-only, *args, **kwargs.
4+
"""
5+
6+
def f(p, /, q, *args, r, **kwargs): # noqa: D401 - simple demo
7+
"""Return a tuple to keep behavior deterministic."""
8+
return (p, q, args, r, kwargs)
9+
10+
11+
def main() -> None:
12+
res = f(1, 2, 3, 4, 5, r=6, a=7, b=8)
13+
# Minimal stable output
14+
print("ok", res[0], res[1], len(res[2]), res[3], sorted(res[4].items()))
15+
16+
17+
if __name__ == "__main__":
18+
main()
19+

examples/classes_methods.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
"""Example: classes, instance/class/static methods, and a property."""
2+
3+
4+
class Counter:
5+
def __init__(self, start: int = 0) -> None:
6+
self._n = start
7+
8+
def inc(self, by: int = 1) -> int:
9+
self._n += by
10+
return self._n
11+
12+
@property
13+
def double(self) -> int:
14+
return self._n * 2
15+
16+
@classmethod
17+
def start_at(cls, n: int) -> "Counter":
18+
return cls(n)
19+
20+
@staticmethod
21+
def add(a: int, b: int) -> int:
22+
return a + b
23+
24+
25+
def main() -> None:
26+
c = Counter.start_at(2)
27+
x = c.inc()
28+
y = Counter.add(3, 4)
29+
print("ok", x, y, c.double)
30+
31+
32+
if __name__ == "__main__":
33+
main()
34+

examples/context_and_closures.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
"""Example: context manager and nested closures."""
2+
3+
from contextlib import contextmanager
4+
5+
6+
@contextmanager
7+
def tag(name: str):
8+
# Minimal context; no side effects beyond yielding
9+
yield f"<{name}>"
10+
11+
12+
def make_multiplier(factor: int):
13+
def mul(x: int) -> int:
14+
return x * factor
15+
16+
return mul
17+
18+
19+
def main() -> None:
20+
with tag("x") as t:
21+
mul3 = make_multiplier(3)
22+
print("ok", t, mul3(5))
23+
24+
25+
if __name__ == "__main__":
26+
main()
27+

examples/exceptions.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
"""Example: raising and handling an exception.
2+
3+
Print the exception inside the except block to exercise printing under tracing.
4+
"""
5+
6+
7+
def boom() -> None:
8+
raise ValueError("boom!")
9+
10+
11+
def main() -> None:
12+
try:
13+
boom()
14+
except Exception as e: # noqa: BLE001 - intentional for example
15+
# Printing inside except triggers additional Python activity
16+
print("handled", type(e).__name__)
17+
18+
19+
if __name__ == "__main__":
20+
main()
21+

examples/generators_async.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
"""Example: generator, async function, and async generator."""
2+
3+
from __future__ import annotations
4+
5+
import asyncio
6+
7+
8+
def gen(n: int):
9+
for i in range(n):
10+
yield i * i
11+
12+
13+
async def async_add(a: int, b: int) -> int:
14+
return a + b
15+
16+
17+
async def agen(n: int):
18+
for i in range(n):
19+
yield i + 1
20+
21+
22+
def main() -> None:
23+
s = sum(gen(5))
24+
total = asyncio.run(async_add(3, 4))
25+
26+
async def consume() -> int:
27+
acc = 0
28+
async for x in agen(3):
29+
acc += x
30+
return acc
31+
32+
acc = asyncio.run(consume())
33+
print("ok", s, total, acc)
34+
35+
36+
if __name__ == "__main__":
37+
main()
38+

examples/imports_side_effects.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
"""Example: module-level side effects vs main guard.
2+
3+
When imported, this module sets a constant; when run as __main__, it prints.
4+
"""
5+
6+
SIDE_EFFECT = "loaded" # module-level assignment (side effect)
7+
8+
9+
def main() -> None:
10+
print("ok", SIDE_EFFECT)
11+
12+
13+
if __name__ == "__main__":
14+
main()
15+

examples/kwargs_nested.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
"""Example: nested kwargs structure for structured encoding validation."""
2+
3+
4+
def accept(**kwargs): # noqa: D401 - simple demo
5+
"""Return kwargs verbatim to keep behavior observable and stable."""
6+
return kwargs
7+
8+
9+
def main() -> None:
10+
res = accept(a=1, b={"x": [1, 2], "y": {"z": 3}}, c=(4, 5))
11+
# Print a stable projection of nested structure
12+
print("ok", res["a"], sorted(res["b"].keys()), res["c"][0])
13+
14+
15+
if __name__ == "__main__":
16+
main()
17+

examples/recursion.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
"""Example: direct and mutual recursion."""
2+
3+
4+
def factorial(n: int) -> int:
5+
return 1 if n <= 1 else n * factorial(n - 1)
6+
7+
8+
def is_even(n: int) -> bool:
9+
return n == 0 or is_odd(n - 1)
10+
11+
12+
def is_odd(n: int) -> bool:
13+
return n != 0 and is_even(n - 1)
14+
15+
16+
def main() -> None:
17+
print("ok", factorial(5), is_even(4), is_odd(7))
18+
19+
20+
if __name__ == "__main__":
21+
main()
22+

examples/threading.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
"""Example: simple multithreading with join."""
2+
3+
from __future__ import annotations
4+
5+
import threading
6+
7+
8+
def worker(name: str, out: list[str]) -> None:
9+
out.append(name)
10+
11+
12+
def main() -> None:
13+
out: list[str] = []
14+
t1 = threading.Thread(target=worker, args=("t1", out))
15+
t2 = threading.Thread(target=worker, args=("t2", out))
16+
t1.start(); t2.start()
17+
t1.join(); t2.join()
18+
print("ok", sorted(out))
19+
20+
21+
if __name__ == "__main__":
22+
main()
23+

0 commit comments

Comments
 (0)