20
20
prefix_selection_order ,
21
21
random_selection_order ,
22
22
)
23
- from hypothesis .internal .conjecture .data import ConjectureData , ConjectureResult , Status
23
+ from hypothesis .internal .conjecture .data import (
24
+ ConjectureData ,
25
+ ConjectureResult ,
26
+ Status ,
27
+ bits_to_bytes ,
28
+ ir_value_permitted ,
29
+ )
24
30
from hypothesis .internal .conjecture .dfa import ConcreteDFA
25
31
from hypothesis .internal .conjecture .floats import is_simple
26
32
from hypothesis .internal .conjecture .junkdrawer import (
@@ -377,7 +383,6 @@ def calls(self):
377
383
378
384
def consider_new_tree (self , tree ):
379
385
data = self .engine .ir_tree_to_data (tree )
380
-
381
386
return self .consider_new_buffer (data .buffer )
382
387
383
388
def consider_new_buffer (self , buffer ):
@@ -825,12 +830,10 @@ def pass_to_descendant(self, chooser):
825
830
)
826
831
827
832
ls = self .examples_by_label [label ]
828
-
829
833
i = chooser .choose (range (len (ls ) - 1 ))
830
-
831
834
ancestor = ls [i ]
832
835
833
- if i + 1 == len (ls ) or ls [i + 1 ].start >= ancestor .end :
836
+ if i + 1 == len (ls ) or ls [i + 1 ].ir_start >= ancestor .ir_end :
834
837
return
835
838
836
839
@self .cached (label , i )
@@ -839,22 +842,22 @@ def descendants():
839
842
hi = len (ls )
840
843
while lo + 1 < hi :
841
844
mid = (lo + hi ) // 2
842
- if ls [mid ].start >= ancestor .end :
845
+ if ls [mid ].ir_start >= ancestor .ir_end :
843
846
hi = mid
844
847
else :
845
848
lo = mid
846
- return [t for t in ls [i + 1 : hi ] if t .length < ancestor .length ]
849
+ return [t for t in ls [i + 1 : hi ] if t .ir_length < ancestor .ir_length ]
847
850
848
- descendant = chooser .choose (descendants , lambda ex : ex .length > 0 )
851
+ descendant = chooser .choose (descendants , lambda ex : ex .ir_length > 0 )
849
852
850
- assert ancestor .start <= descendant .start
851
- assert ancestor .end >= descendant .end
852
- assert descendant .length < ancestor .length
853
+ assert ancestor .ir_start <= descendant .ir_start
854
+ assert ancestor .ir_end >= descendant .ir_end
855
+ assert descendant .ir_length < ancestor .ir_length
853
856
854
- self .incorporate_new_buffer (
855
- self .buffer [: ancestor .start ]
856
- + self .buffer [descendant .start : descendant .end ]
857
- + self .buffer [ancestor .end :]
857
+ self .consider_new_tree (
858
+ self .nodes [: ancestor .ir_start ]
859
+ + self .nodes [descendant .ir_start : descendant .ir_end ]
860
+ + self .nodes [ancestor .ir_end :]
858
861
)
859
862
860
863
def lower_common_block_offset (self ):
@@ -1221,7 +1224,6 @@ def minimize_floats(self, chooser):
1221
1224
and not is_simple (node .value ),
1222
1225
)
1223
1226
1224
- i = self .nodes .index (node )
1225
1227
# the Float shrinker was only built to handle positive floats. We'll
1226
1228
# shrink the positive portion and reapply the sign after, which is
1227
1229
# equivalent to this shrinker's previous behavior. We'll want to refactor
@@ -1231,9 +1233,9 @@ def minimize_floats(self, chooser):
1231
1233
Float .shrink (
1232
1234
abs (node .value ),
1233
1235
lambda val : self .consider_new_tree (
1234
- self .nodes [:i ]
1236
+ self .nodes [: node . index ]
1235
1237
+ [node .copy (with_value = sign * val )]
1236
- + self .nodes [i + 1 :]
1238
+ + self .nodes [node . index + 1 :]
1237
1239
),
1238
1240
random = self .random ,
1239
1241
node = node ,
@@ -1245,32 +1247,56 @@ def redistribute_block_pairs(self, chooser):
1245
1247
to exceed some bound, lowering one of them requires raising the
1246
1248
other. This pass enables that."""
1247
1249
1248
- block = chooser .choose (self .blocks , lambda b : not b .all_zero )
1250
+ node = chooser .choose (
1251
+ self .nodes , lambda node : node .ir_type == "integer" and not node .trivial
1252
+ )
1249
1253
1250
- for j in range (block .index + 1 , len (self .blocks )):
1251
- next_block = self .blocks [j ]
1252
- if next_block .length == block .length :
1254
+ # The preconditions for this pass are that the two integer draws are only
1255
+ # separated by non-integer nodes, and have the same size value in bytes.
1256
+ #
1257
+ # This isn't particularly principled. For instance, this wouldn't reduce
1258
+ # e.g. @given(integers(), integers(), integers()) where the sum property
1259
+ # involves the first and last integers.
1260
+ #
1261
+ # A better approach may be choosing *two* such integer nodes arbitrarily
1262
+ # from the list, instead of conditionally scanning forward.
1263
+
1264
+ for j in range (node .index + 1 , len (self .nodes )):
1265
+ next_node = self .nodes [j ]
1266
+ if next_node .ir_type == "integer" and bits_to_bytes (
1267
+ node .value .bit_length ()
1268
+ ) == bits_to_bytes (next_node .value .bit_length ()):
1253
1269
break
1254
1270
else :
1255
1271
return
1256
1272
1257
- buffer = self .buffer
1273
+ if next_node .was_forced :
1274
+ # avoid modifying a forced node. Note that it's fine for next_node
1275
+ # to be trivial, because we're going to explicitly make it *not*
1276
+ # trivial by adding to its value.
1277
+ return
1258
1278
1259
- m = int_from_bytes ( buffer [ block . start : block . end ])
1260
- n = int_from_bytes ( buffer [ next_block . start : next_block . end ])
1279
+ m = node . value
1280
+ n = next_node . value
1261
1281
1262
1282
def boost (k ):
1263
1283
if k > m :
1264
1284
return False
1265
- attempt = bytearray (buffer )
1266
- attempt [block .start : block .end ] = int_to_bytes (m - k , block .length )
1267
- try :
1268
- attempt [next_block .start : next_block .end ] = int_to_bytes (
1269
- n + k , next_block .length
1270
- )
1271
- except OverflowError :
1285
+
1286
+ node_value = m - k
1287
+ next_node_value = n + k
1288
+ if (not ir_value_permitted (node_value , "integer" , node .kwargs )) or (
1289
+ not ir_value_permitted (next_node_value , "integer" , next_node .kwargs )
1290
+ ):
1272
1291
return False
1273
- return self .consider_new_buffer (attempt )
1292
+
1293
+ return self .consider_new_tree (
1294
+ self .nodes [: node .index ]
1295
+ + [node .copy (with_value = node_value )]
1296
+ + self .nodes [node .index + 1 : next_node .index ]
1297
+ + [next_node .copy (with_value = next_node_value )]
1298
+ + self .nodes [next_node .index + 1 :]
1299
+ )
1274
1300
1275
1301
find_integer (boost )
1276
1302
0 commit comments