@@ -43,21 +43,22 @@ def pretty(name: str) -> str:
43
43
return name .replace ("_" , " " ).lower ()
44
44
45
45
46
- class Stats ( dict ) :
46
+ class Stats :
47
47
def __init__ (self , input : Path ):
48
48
super ().__init__ ()
49
49
50
50
if input .is_file ():
51
51
with open (input , "r" ) as fd :
52
- self .update ( json .load (fd ) )
52
+ self ._data = json .load (fd )
53
53
54
- self ["_stats_defines" ] = {
54
+ self . _data ["_stats_defines" ] = {
55
55
int (k ): v for k , v in self ["_stats_defines" ].items ()
56
56
}
57
- self ["_defines" ] = {int (k ): v for k , v in self ["_defines" ].items ()}
57
+ self . _data ["_defines" ] = {int (k ): v for k , v in self ["_defines" ].items ()}
58
58
59
59
elif input .is_dir ():
60
- stats : collections .Counter = collections .Counter ()
60
+ stats = collections .Counter ()
61
+
61
62
for filename in input .iterdir ():
62
63
with open (filename ) as fd :
63
64
for line in fd :
@@ -72,15 +73,35 @@ def __init__(self, input: Path):
72
73
stats [key .strip ()] += int (value )
73
74
stats ["__nfiles__" ] += 1
74
75
75
- self .update (stats )
76
-
76
+ self ._data = dict (stats )
77
77
self ._load_metadata_from_source ()
78
78
79
79
else :
80
80
raise ValueError (f"{ input :r} is not a file or directory path" )
81
81
82
82
self ._opcode_stats : dict [str , OpcodeStats ] = {}
83
83
84
+ def __getitem__ (self , key ):
85
+ return self ._data [key ]
86
+
87
+ def __contains__ (self , key ):
88
+ return key in self ._data
89
+
90
+ def get (self , key , default = None ):
91
+ return self ._data .get (key , default )
92
+
93
+ def items (self ):
94
+ return self ._data .items ()
95
+
96
+ def keys (self ):
97
+ return self ._data .keys ()
98
+
99
+ def values (self ):
100
+ return self ._data .values ()
101
+
102
+ def save (self , json_output : TextIO ):
103
+ json .dump (self ._data , json_output )
104
+
84
105
def _load_metadata_from_source (self ):
85
106
def get_defines (filepath : Path , prefix : str = "SPEC_FAIL" ) -> Defines :
86
107
with open (SOURCE_DIR / filepath ) as spec_src :
@@ -97,27 +118,27 @@ def get_defines(filepath: Path, prefix: str = "SPEC_FAIL") -> Defines:
97
118
98
119
import opcode
99
120
100
- self ["_specialized_instructions" ] = [
121
+ self . _data ["_specialized_instructions" ] = [
101
122
op
102
123
for op in opcode ._specialized_opmap .keys () # type: ignore
103
124
if "__" not in op
104
125
]
105
- self ["_stats_defines" ] = get_defines (
126
+ self . _data ["_stats_defines" ] = get_defines (
106
127
Path ("Include" ) / "cpython" / "pystats.h" , "EVAL_CALL"
107
128
)
108
- self ["_defines" ] = get_defines (Path ("Python" ) / "specialize.c" )
129
+ self . _data ["_defines" ] = get_defines (Path ("Python" ) / "specialize.c" )
109
130
110
131
@property
111
132
def defines (self ) -> Defines :
112
- return self ["_defines" ]
133
+ return self . _data ["_defines" ]
113
134
114
135
@property
115
136
def pystats_defines (self ) -> Defines :
116
- return self ["_stats_defines" ]
137
+ return self . _data ["_stats_defines" ]
117
138
118
139
@property
119
140
def specialized_instructions (self ) -> list [str ]:
120
- return self ["_specialized_instructions" ]
141
+ return self . _data ["_specialized_instructions" ]
121
142
122
143
def get_opcode_stats (self , prefix : str ) -> OpcodeStats :
123
144
if prefix in self ._opcode_stats :
@@ -803,7 +824,8 @@ def calculate_rows(self, stats: Stats) -> Rows:
803
824
"Trace too short" ,
804
825
Count (trace_too_short ),
805
826
Ratio (trace_too_short , created ),
806
- )("Inner loop found" , Count (inner_loop ), Ratio (inner_loop , created )),
827
+ ),
828
+ ("Inner loop found" , Count (inner_loop ), Ratio (inner_loop , created )),
807
829
(
808
830
"Recursive call" ,
809
831
Count (recursive_call ),
@@ -976,11 +998,11 @@ def output_markdown(out: TextIO, base_stats: Stats, head_stats: Stats | None = N
976
998
print ("Stats gathered on:" , date .today (), file = out )
977
999
978
1000
979
- def output_stats (inputs : list [Path ], json_output = None ):
1001
+ def output_stats (inputs : list [Path ], json_output = TextIO | None ):
980
1002
if len (inputs ) == 1 :
981
1003
stats = Stats (Path (inputs [0 ]))
982
1004
if json_output is not None :
983
- json . dump ( stats , json_output )
1005
+ stats . save ( json_output )
984
1006
output_markdown (sys .stdout , stats )
985
1007
elif len (inputs ) == 2 :
986
1008
if json_output is not None :
0 commit comments