Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

# This file is not mean to be used!!! 

# ONLY FOR INTERNAL DEBUG 

 

# wraps each method in a derived class of: 

# - VersionSourceInterface 

# - BuildHookInterface 

# etc. 

 

# wraps this: 

# site-packages\pyproject_hooks\_impl.py -> 

# def _call_hook(self, hook_name, kwargs): 

# ... 

# from hatch_ci._support import tracer 

# with tracer.decorator(_in_proc_script_path)() as script: 

 

# change the OUTPUT below 

from __future__ import annotations 

 

import functools 

import inspect 

import io 

import json 

import os 

import sys 

from pathlib import Path 

from typing import Any 

 

OUTPUT = None # eg. r"C:\Users\antonio\Projects\github\hatch-ci\NOTES.txt" 

 

 

def is_scm(path: Path) -> str: 

return "<git>" if (Path(path) / ".git").exists() else "<plain>" 

 

 

def jformat(data: Any, pre: str) -> str: 

return json.dumps(data, indent=2, sort_keys=True).replace( 

"\n", f"\n{' ' * len(pre)}" 

) 

 

 

class Tracer: 

def __init__(self, path: Path | str | None = None): 

self.path = Path(path) if path else None 

 

def decorator(self, fn): 

if fn.__name__ == "_in_proc_script_path": 

return self.wraps__in_proc_script_path(fn) 

else: 

return self.wraps_interface(fn) 

 

def append(self, txt): 

if not self.path: 

return 

with self.path.open("a") as fp: 

fp.write(txt.getvalue() if hasattr(txt, "getvalue") else txt) 

 

def wraps__in_proc_script_path(self, fn): 

# this is mean to wrap the _in_proc_script_path function 

@functools.wraps(fn) 

def _fn(*args, **kwargs): 

# ok, looking to wrap _call_hook in _impl.py 

frames = [ 

f 

for f in inspect.getouterframes(inspect.currentframe()) 

if "_impl.py" in f.filename and f.function == "_call_hook" 

] 

if len(frames) != 1: 

raise RuntimeError("cannot find _call_hook in _impl.py frame") 

variables = frames[0].frame.f_locals 

 

if not self.path: 

fp = io.StringIO() 

print("", file=fp) 

print(f"[pid={os.getpid()}]", file=fp) 

print(f"<hook> '{variables['hook_name']}'", file=fp) 

scm = ( 

"<git>" 

if (Path(variables["self"].source_dir) / ".git").exists() 

else "<plain>" 

) 

print( 

f" cwd (self.source_dir): {variables['self'].source_dir} {scm}", 

file=fp, 

) 

print(f" kwargs: {variables['kwargs']}", file=fp) 

print(f" extra_environ: {variables['extra_environ']}", file=fp) 

print(" input.json:", file=fp) 

pre = " input.json: " 

print(f"{pre}{jformat(variables['hook_input'], pre=pre)}", file=fp) 

self.append(fp) 

 

return fn(*args, **kwargs) 

 

return _fn 

 

def wraps_interface(self, method): 

# a method decorator 

# you should wrap methods of subclasses of: 

# - VersionSourceInterface 

# - BuildHookInterface 

# etc. 

@functools.wraps(method) 

def _fn(slf, *args, **kwargs): 

if self.path: 

fp = io.StringIO() 

print("", file=fp) 

print(f"[pid={os.getpid()}] {sys.argv=}", file=fp) 

print( 

f"!callback! '{method.__name__}' {slf.__class__.__name__}", file=fp 

) 

print(f" self.root: {slf.root} {is_scm(slf.root)}", file=fp) 

print(f" config: {jformat(slf.config, ' config: ')}", file=fp) 

self.append(fp) 

return method(slf, *args, **kwargs) 

 

return _fn if self.path else method 

 

 

tracer = Tracer() # r"C:\Users\antonio\Projects\github\hatch-ci\NOTES.txt")