def make_registrations(): def make_date(p: Callable) -> datetime.date: year, month, day = p(int), p(int), p(int) # This condition isn't technically required, but it develops useful # symbolic inequalities before the realization below: if not (1 <= year <= 9999 and 1 <= month <= 12 and 1 <= day <= 31): raise IgnoreAttempt('Invalid date') try: return datetime.date(realize(year), realize(month), realize(day)) except ValueError: raise IgnoreAttempt('Invalid date') register_type(datetime.date, make_date) def make_timedelta(p: Callable) -> datetime.timedelta: microseconds, seconds, days = p(int), p(int), p(int) # the normalized ranges, per the docs: if not (0 <= microseconds < 1000000 and 0 <= seconds < 3600 * 24 and -999999999 <= days <= 999999999): raise IgnoreAttempt('Invalid timedelta') try: return datetime.timedelta(days=realize(days), seconds=realize(seconds), microseconds=realize(microseconds)) except OverflowError: raise IgnoreAttempt('Invalid timedelta') register_type(datetime.timedelta, make_timedelta)
def make_registrations(): # NOTE: defaultdict could be symbolic (but note the default_factory is changable/stateful): register_type(collections.defaultdict, lambda p, kt=Any, vt=Any: collections.defaultdict( p(Callable[[], vt]), p(Dict[kt, vt]))) # type: ignore register_type(collections.ChainMap, lambda p, kt=Any, vt=Any: collections.ChainMap(*p(Tuple[Dict[ kt, vt], ...]))) # type: ignore register_type(collections.abc.Mapping, lambda p, kt=Any, vt=Any: p(Dict[kt, vt])) # type: ignore register_type(collections.abc.MutableMapping, lambda p, kt=Any, vt=Any: p(Dict[kt, vt])) # type: ignore register_type(collections.OrderedDict, lambda p, kt=Any, vt=Any: collections.OrderedDict( p(Dict[kt, vt]))) # type: ignore register_type( collections.Counter, lambda p, t=Any: collections.Counter(p(Dict[t, int]))) # type: ignore # TODO: MappingView is missing register_type( collections.abc.ItemsView, lambda p, kt=Any, vt=Any: p(Set[Tuple[kt, vt]])) # type: ignore register_type(collections.abc.KeysView, lambda p, t=Any: p(Set[t])) # type: ignore register_type(collections.abc.ValuesView, lambda p, t=Any: p(Set[t])) # type: ignore register_type(collections.abc.Container, lambda p, t=Any: p(Tuple[t, ...])) register_type(collections.abc.Collection, lambda p, t=Any: p(Tuple[t, ...])) register_type(collections.deque, lambda p, t=Any: collections.deque(p(Tuple[t, ...]))) # TODO: When ready, use custom deque class instead: # register_type(collections.deque, lambda p, t=Any: ListBasedDeque(p(List[t, ...]))) # type: ignore register_type(collections.abc.Iterable, lambda p, t=Any: p(Tuple[t, ...])) register_type(collections.abc.Iterator, lambda p, t=Any: iter(p(Iterable[t]))) # type: ignore register_type(collections.abc.MutableSequence, lambda p, t=Any: p(List[t])) # type: ignore register_type(collections.abc.Reversible, lambda p, t=Any: p(Tuple[t, ...])) register_type(collections.abc.Sequence, lambda p, t=Any: p(Tuple[t, ...])) register_type(collections.abc.Sized, lambda p, t=Any: p(Tuple[t, ...])) register_type(collections.abc.MutableSet, lambda p, t=Any: p(Set[t])) # type: ignore register_type(collections.abc.ByteString, lambda p: bytes(b % 256 for b in p(List[int]))) register_type(collections.abc.Hashable, lambda p: p(int))
def make_registrations(): # WARNING: This is destructive for the datetime module. # It disables the C implementation for the entire interpreter. sys.modules["_datetime"] = None # type: ignore importlib.reload(datetime) # Default pickling will realize the symbolic args; avoid this: datetime.date.__deepcopy__ = lambda s, _memo: datetime.date( s.year, s.month, s.day) datetime.time.__deepcopy__ = lambda s, _memo: datetime.time( s.hour, s.minute, s.second, s.microsecond, s.tzinfo) datetime.datetime.__deepcopy__ = lambda s, _memo: datetime.datetime( s.year, s.month, s.day, s.hour, s.minute, s.second, s.microsecond, s. tzinfo) datetime.timedelta.__deepcopy__ = lambda d, _memo: _timedelta_skip_construct( d.days, d.seconds, d.microseconds) # Mokey patch validation so that we can defer it. orig_check_date_fields = datetime._check_date_fields orig_check_time_fields = datetime._check_time_fields datetime._check_date_fields = lambda y, m, d: (y, m, d) datetime._check_time_fields = lambda h, m, s, u, f: (h, m, s, u, f) # TODO: `timezone` never makes a tzinfo with DST, so this is incomplete. # A complete solution would require generating a symbolc dst() member function. register_type(datetime.tzinfo, lambda p: p(datetime.timezone)) # NOTE: these bounds have changed over python versions (e.g. [1]), so we pull the # following private constants from the runtime directly. # [1] https://github.com/python/cpython/commit/92c7e30adf5c81a54d6e5e555a6bdfaa60157a0d#diff-2a8962dcecb109859cedd81ddc5729bea57d156e0947cb8413f99781a0860fd1R2272 _max_tz_offset = datetime.timezone._maxoffset _min_tz_offset = datetime.timezone._minoffset def make_timezone(p: Any) -> datetime.timezone: if p.space.smt_fork(desc="use explicit timezone"): delta = p(datetime.timedelta, "_offset") with ResumedTracing(): if _min_tz_offset < delta < _max_tz_offset: return datetime.timezone(delta, realize(p(str, "_name"))) else: raise IgnoreAttempt("Invalid timezone offset") else: return datetime.timezone.utc register_type(datetime.timezone, make_timezone) def make_date(p: Any) -> datetime.date: year, month, day = p(int, "_year"), p(int, "_month"), p(int, "_day") try: p.space.defer_assumption( "Invalid date", lambda: (not _raises_value_error(orig_check_date_fields, (year, month, day))), ) return datetime.date(year, month, day) except ValueError: raise IgnoreAttempt("Invalid date") register_type(datetime.date, make_date) def make_time(p: Any) -> datetime.time: hour = p(int, "_hour") minute = p(int, "_minute") sec = p(int, "_sec") usec = p(int, "_usec") tzinfo = p(Optional[datetime.timezone], "_tzinfo") try: p.space.defer_assumption( "Invalid datetime", lambda: (not _raises_value_error(orig_check_time_fields, (hour, minute, sec, usec, 0))), ) return datetime.time(hour, minute, sec, usec, tzinfo) except ValueError: raise IgnoreAttempt("Invalid datetime") register_type(datetime.time, make_time) def make_datetime(p: Any) -> datetime.datetime: year, month, day, hour, minute, sec, usec = ( p(int, "_year"), p(int, "_month"), p(int, "_day"), p(int, "_hour"), p(int, "_minute"), p(int, "_sec"), p(int, "usec"), ) tzinfo = p(Optional[datetime.timezone], "_tz") try: p.space.defer_assumption( "Invalid datetime", lambda: (not _raises_value_error(orig_check_date_fields, (year, month, day)) and not _raises_value_error(orig_check_time_fields, (hour, minute, sec, usec, 0))), ) return datetime.datetime(year, month, day, hour, minute, sec, usec, tzinfo) except ValueError: raise IgnoreAttempt("Invalid datetime") register_type(datetime.datetime, make_datetime) def make_timedelta(p: Callable) -> datetime.timedelta: microseconds, seconds, days = p(int, "_usec"), p(int, "_sec"), p(int, "_days") with ResumedTracing(): # the normalized ranges, per the docs: if not (0 <= microseconds < 1000000 and 0 <= seconds < 3600 * 24 and -999999999 <= days <= 999999999): raise IgnoreAttempt("Invalid timedelta") try: return _timedelta_skip_construct(days, seconds, microseconds) except OverflowError: raise IgnoreAttempt("Invalid timedelta") register_type(datetime.timedelta, make_timedelta)
def __array__(self): if any(size < 0 for size in self.shape): raise IgnoreAttempt('ndarray disallows negative dimensions') concrete_shape = tuple(map(int, self.shape)) concrete_dtype = realize(self.dtype) # For the contents, we just construct it with ones. This makes it much # less complete in terms of finding counterexamples, but is sufficient # for array dimension and type reasoning. If we were more ambitious, # we would rewrite a (slow) implementation of numpy in terms of native # Python types. return np.ones(concrete_shape, concrete_dtype) # Make crosshair use our custom class whenever it needs a symbolic # ndarray instance: register_type(np.ndarray, SymbolicNdarray) def matrix_multiply(image1: np.ndarray, image2: np.ndarray) -> np.ndarray: ''' pre: image1.dtype == image2.dtype == np.float64 pre: len(image1.shape) == len(image2.shape) == 2 pre: image1.shape[1] == image2.shape[0] post: __return__.shape == (image1.shape[0], image2.shape[1]) ''' return image1 @ image2 def unit_normalize(a: np.ndarray) -> np.ndarray: ''' >>> unit_normalize(np.arange(-1, 2))
def make_registrations() -> None: register_type(random.Random, lambda p: random.Random(p(int)))
def make_registrations(): register_type(collections.defaultdict, lambda p, kt=Any, vt=Any: PureDefaultDict( p(Optional[Callable[[], vt]], "_initalizer"), p(Dict[kt, vt]))) # type: ignore register_type(collections.ChainMap, lambda p, kt=Any, vt=Any: collections.ChainMap(*p(Tuple[Dict[ kt, vt], ...]))) # type: ignore register_type(collections.abc.Mapping, lambda p, kt=Any, vt=Any: p(Dict[kt, vt])) # type: ignore register_type(collections.abc.MutableMapping, lambda p, kt=Any, vt=Any: p(Dict[kt, vt])) # type: ignore register_type(collections.OrderedDict, lambda p, kt=Any, vt=Any: collections.OrderedDict( p(Dict[kt, vt]))) # type: ignore register_type( collections.Counter, lambda p, t=Any: collections.Counter(p(Dict[t, int]))) # type: ignore # TODO: MappingView is missing register_type( collections.abc.ItemsView, lambda p, kt=Any, vt=Any: p(Set[Tuple[kt, vt]])) # type: ignore register_type(collections.abc.KeysView, lambda p, t=Any: p(Set[t])) # type: ignore register_type(collections.abc.ValuesView, lambda p, t=Any: p(List[t])) # type: ignore register_type(collections.abc.Container, lambda p, t=Any: p(Tuple[t, ...])) register_type(collections.abc.Collection, lambda p, t=Any: p(Tuple[t, ...])) register_type(collections.deque, lambda p, t=Any: ListBasedDeque(p(List[t]))) # type: ignore register_type(collections.abc.Iterable, lambda p, t=Any: p(Tuple[t, ...])) register_type(collections.abc.Iterator, lambda p, t=Any: iter(p(Iterable[t]))) # type: ignore register_type(collections.abc.MutableSequence, lambda p, t=Any: p(List[t])) # type: ignore register_type(collections.abc.Reversible, lambda p, t=Any: p(Tuple[t, ...])) register_type(collections.abc.Sequence, lambda p, t=Any: p(Tuple[t, ...])) register_type(collections.abc.Sized, lambda p, t=Any: p(Tuple[t, ...])) register_type(collections.abc.MutableSet, lambda p, t=Any: p(Set[t])) # type: ignore register_type(collections.abc.ByteString, make_byte_string) register_type(collections.abc.Hashable, lambda p: p(int))
def make_registrations(): # WARNING: This is destructive for the datetime module. # It disables the C implementation for the entire interpreter. sys.modules['_datetime'] = None # type: ignore importlib.reload(datetime) # Default pickling will realize the symbolic args; avoid this: datetime.date.__deepcopy__ = lambda s, _memo: datetime.date( s.year, s.month, s.day) datetime.time.__deepcopy__ = lambda s, _memo: datetime.time( s.hour, s.minute, s.second, s.microsecond, s.tzinfo) datetime.datetime.__deepcopy__ = lambda s, _memo: datetime.datetime( s.year, s.month, s.day, s.hour, s.minute, s.second, s.microsecond, s. tzinfo) datetime.timedelta.__deepcopy__ = lambda d, _memo: _timedelta_skip_construct( d.days, d.seconds, d.microseconds) # Mokey patch validation so that we can defer it. orig_check_date_fields = datetime._check_date_fields orig_check_time_fields = datetime._check_time_fields datetime._check_date_fields = lambda y, m, d: (y, m, d) datetime._check_time_fields = lambda h, m, s, u, f: (h, m, s, u, f) # TODO: `timezone` never makes a tzinfo with DST, so this is incomplete. # A complete solution would require generating a symbolc dst() member function. register_type(datetime.tzinfo, lambda p: p(datetime.timezone)) _min_tz_offset, _max_tz_offset = -datetime.timedelta( hours=24), datetime.timedelta(hours=24) def make_timezone(p: Any) -> datetime.timezone: if p.space.smt_fork(): delta = p(datetime.timedelta) if _min_tz_offset < delta < _max_tz_offset: return datetime.timezone(delta, p(str)) else: raise IgnoreAttempt('Invalid timezone offset') else: return datetime.timezone.utc register_type(datetime.timezone, make_timezone) def make_date(p: Any) -> datetime.date: year, month, day = p(int), p(int), p(int) try: p.space.defer_assumption( 'Invalid date', lambda: (not _raises_value_error(orig_check_date_fields, (year, month, day)))) return datetime.date(year, month, day) except ValueError: raise IgnoreAttempt('Invalid date') register_type(datetime.date, make_date) def make_time(p: Any) -> datetime.time: hour, minute, sec, usec = p(int), p(int), p(int), p(int) tzinfo = p(datetime.timezone) if p.space.smt_fork() else None try: p.space.defer_assumption( 'Invalid datetime', lambda: (not _raises_value_error(orig_check_time_fields, (hour, minute, sec, usec, 0)))) return datetime.time(hour, minute, sec, usec, tzinfo) except ValueError: raise IgnoreAttempt('Invalid datetime') register_type(datetime.time, make_time) def make_datetime(p: Any) -> datetime.datetime: year, month, day, hour, minute, sec, usec = p(int), p(int), p(int), p( int), p(int), p(int), p(int) tzinfo = p(datetime.tzinfo) if p.space.smt_fork() else None try: p.space.defer_assumption( 'Invalid datetime', lambda: (not _raises_value_error(orig_check_date_fields, (year, month, day)) and not _raises_value_error(orig_check_time_fields, (hour, minute, sec, usec, 0)))) return datetime.datetime(year, month, day, hour, minute, sec, usec, tzinfo) except ValueError: raise IgnoreAttempt('Invalid datetime') register_type(datetime.datetime, make_datetime) def make_timedelta(p: Callable) -> datetime.timedelta: microseconds, seconds, days = p(int), p(int), p(int) # the normalized ranges, per the docs: if not (0 <= microseconds < 1000000 and 0 <= seconds < 3600 * 24 and -999999999 <= days <= 999999999): raise IgnoreAttempt('Invalid timedelta') try: return _timedelta_skip_construct(days, seconds, microseconds) except OverflowError: raise IgnoreAttempt('Invalid timedelta') register_type(datetime.timedelta, make_timedelta)