Hello community,
here is the log from the commit of package python-hypothesis for openSUSE:Factory checked in at 2018-07-21 10:09:37
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-hypothesis (Old)
and /work/SRC/openSUSE:Factory/.python-hypothesis.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-hypothesis"
Sat Jul 21 10:09:37 2018 rev:24 rq:624329 version:3.66.4
Changes:
--------
--- /work/SRC/openSUSE:Factory/python-hypothesis/python-hypothesis.changes 2018-07-13 10:17:55.834210845 +0200
+++ /work/SRC/openSUSE:Factory/.python-hypothesis.new/python-hypothesis.changes 2018-07-21 10:09:38.775178581 +0200
@@ -1,0 +2,6 @@
+Fri Jul 20 15:28:09 UTC 2018 - arun@gmx.de
+
+- update to version 3.66.4:
+ * This release improves the shrinker’s ability to reorder examples.
+
+-------------------------------------------------------------------
Old:
----
hypothesis-python-3.66.1.tar.gz
New:
----
hypothesis-python-3.66.4.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-hypothesis.spec ++++++
--- /var/tmp/diff_new_pack.ouL3w1/_old 2018-07-21 10:09:39.167178491 +0200
+++ /var/tmp/diff_new_pack.ouL3w1/_new 2018-07-21 10:09:39.171178490 +0200
@@ -28,7 +28,7 @@
%endif
%bcond_without python2
Name: python-hypothesis
-Version: 3.66.1
+Version: 3.66.4
Release: 0
Summary: A library for property based testing
License: MPL-2.0
++++++ hypothesis-python-3.66.1.tar.gz -> hypothesis-python-3.66.4.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hypothesis-hypothesis-python-3.66.1/CONTRIBUTING.rst new/hypothesis-hypothesis-python-3.66.4/CONTRIBUTING.rst
--- old/hypothesis-hypothesis-python-3.66.1/CONTRIBUTING.rst 2018-07-09 01:06:33.000000000 +0200
+++ new/hypothesis-hypothesis-python-3.66.4/CONTRIBUTING.rst 2018-07-20 15:37:18.000000000 +0200
@@ -158,6 +158,7 @@
* `Alex Stapleton https://www.github.com/public`_
* `Alex Willmer https://github.com/moreati`_ (alex@moreati.org.uk)
* `Ben Peterson https://github.com/killthrush`_ (killthrush@hotmail.com)
+* `Bill Tucker https://github.com/imbilltucker`_ (imbilltucker@gmail.com)
* `Buck Evan, copyright Google LLC https://github.com/bukzor`_
* `Charles O'Farrell https://www.github.com/charleso`_
* `Charlie Tanksley https://www.github.com/charlietanksley`_
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hypothesis-hypothesis-python-3.66.1/conjecture-rust/CHANGELOG.md new/hypothesis-hypothesis-python-3.66.4/conjecture-rust/CHANGELOG.md
--- old/hypothesis-hypothesis-python-3.66.1/conjecture-rust/CHANGELOG.md 2018-07-09 01:06:33.000000000 +0200
+++ new/hypothesis-hypothesis-python-3.66.4/conjecture-rust/CHANGELOG.md 2018-07-20 15:37:18.000000000 +0200
@@ -1,3 +1,10 @@
+# Conjecture for Rust 0.3.0 (2018-07-16)
+
+This release adds support for annotating interesting examples
+to indicate that they are logically distinct. When multiple distinct
+reasons for being interesting are found, Conjecture will attempt to
+shrink all of them.
+
# Conjecture for Rust 0.2.1 (2018-06-25)
This release fixes an occasional assertion failure that could occur
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hypothesis-hypothesis-python-3.66.1/conjecture-rust/Cargo.toml new/hypothesis-hypothesis-python-3.66.4/conjecture-rust/Cargo.toml
--- old/hypothesis-hypothesis-python-3.66.1/conjecture-rust/Cargo.toml 2018-07-09 01:06:33.000000000 +0200
+++ new/hypothesis-hypothesis-python-3.66.4/conjecture-rust/Cargo.toml 2018-07-20 15:37:18.000000000 +0200
@@ -1,6 +1,6 @@
[package]
name = "conjecture"
-version = '0.2.1'
+version = '0.3.0'
authors = ["David R. MacIver "]
homepage = "https://github.com/HypothesisWorks/hypothesis/tree/master/conjecture-rust"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hypothesis-hypothesis-python-3.66.1/conjecture-rust/src/data.rs new/hypothesis-hypothesis-python-3.66.4/conjecture-rust/src/data.rs
--- old/hypothesis-hypothesis-python-3.66.1/conjecture-rust/src/data.rs 2018-07-09 01:06:33.000000000 +0200
+++ new/hypothesis-hypothesis-python-3.66.4/conjecture-rust/src/data.rs 2018-07-20 15:37:18.000000000 +0200
@@ -3,6 +3,7 @@
use rand::{ChaChaRng, Rng};
use std::collections::HashSet;
+use std::cmp::Ordering;
pub type DataStream = Vec<u64>;
@@ -167,7 +168,7 @@
// This was an interesting test execution! (Usually this
// means failing, but for things like find it may not).
- Interesting,
+ Interesting(u64),
}
// Once a data source is finished it "decays" to a
@@ -182,3 +183,25 @@
pub sizes: Vec<u64>,
pub written_indices: HashSet<usize>,
}
+
+
+impl Ord for TestResult {
+ fn cmp(&self, other: &TestResult) -> Ordering {
+ self.record.len().cmp(&other.record.len()).
+ then(self.record.cmp(&other.record))
+ }
+}
+
+impl PartialOrd for TestResult {
+ fn partial_cmp(&self, other: &TestResult) -> Option<Ordering> {
+ Some(self.cmp(other))
+ }
+}
+
+impl PartialEq for TestResult {
+ fn eq(&self, other: &TestResult) -> bool {
+ self.record == other.record
+ }
+}
+
+impl Eq for TestResult { }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hypothesis-hypothesis-python-3.66.1/conjecture-rust/src/engine.rs new/hypothesis-hypothesis-python-3.66.4/conjecture-rust/src/engine.rs
--- old/hypothesis-hypothesis-python-3.66.1/conjecture-rust/src/engine.rs 2018-07-09 01:06:33.000000000 +0200
+++ new/hypothesis-hypothesis-python-3.66.4/conjecture-rust/src/engine.rs 2018-07-20 15:37:18.000000000 +0200
@@ -4,7 +4,7 @@
use rand::{ChaChaRng, Rng, SeedableRng};
use std::cmp::Reverse;
-use std::collections::HashMap;
+use std::collections::{HashMap, HashSet};
use std::mem;
use std::sync::mpsc::{sync_channel, Receiver, SyncSender};
use std::thread;
@@ -33,6 +33,8 @@
random: ChaChaRng,
best_example: Option<TestResult>,
+ minimized_examples: HashMap,
+ fully_minimized: HashSet<u64>,
valid_examples: u64,
invalid_examples: u64,
@@ -59,13 +61,36 @@
}
fn loop_body(&mut self) -> StepResult {
- let interesting_example = self.generate_examples()?;
+ self.generate_examples()?;
- let mut shrinker = Shrinker::new(self, interesting_example, |r| {
- r.status == Status::Interesting
- });
+ // At the start of this loop we can only have example in
+ // self.minimized_examples, but as we shrink we may find other ones.
+ // The reason why we loop is twofold:
+ // a) This allows us to include newly discovered examples. Labels that
+ // are not found in self.minimized_examples at the beginning of the
+ // loop will be added for the next iteration around.
+ // b) If we've previously marked a label as finished it can become
+ // unfinished again if when shrinking another label, as when trying
+ // to shrink one label we might accidentally find an improved shrink
+ // for another.
+ //
+ // In principle this might cause us to loop for a very long time before
+ // eventually settling on a fixed point, but when that happens we
+ // should hit limits on shrinking (which we haven't implemented yet).
+ while self.minimized_examples.len() > self.fully_minimized.len() {
+ let keys: Vec<u64> = self.minimized_examples.keys().map(|i| *i).collect();
+ for label in keys.iter() {
+ if self.fully_minimized.insert(*label) {
+ let target = self.minimized_examples[label].clone();
+ let mut shrinker = Shrinker::new(
+ self, target, |r| {
+ r.status == Status::Interesting(*label)
+ });
- shrinker.run()?;
+ shrinker.run()?;
+ }
+ }
+ }
return Err(LoopExitReason::Complete);
}
@@ -76,8 +101,9 @@
{
let r = self.random.gen();
let result = self.execute(DataSource::from_random(r))?;
- if result.status == Status::Interesting {
- return Ok(result);
+ match result.status {
+ Status::Interesting(_) => return Ok(result),
+ _ => (),
}
}
return Err(LoopExitReason::MaxExamples);
@@ -95,8 +121,19 @@
Status::Overflow => (),
Status::Invalid => self.invalid_examples += 1,
Status::Valid => self.valid_examples += 1,
- Status::Interesting => {
+ Status::Interesting(n) => {
self.best_example = Some(result.clone());
+ let mut changed = false;
+ self.minimized_examples.entry(n).or_insert_with(|| {result.clone()});
+ self.minimized_examples.entry(n).and_modify(|e| {
+ if result < *e {
+ changed = true;
+ *e = result.clone()
+ };
+ });
+ if changed {
+ self.fully_minimized.remove(&n);
+ }
self.interesting_examples += 1;
}
}
@@ -497,6 +534,8 @@
sender: send_remote,
receiver: recv_remote,
best_example: None,
+ minimized_examples: HashMap::new(),
+ fully_minimized: HashSet::new(),
valid_examples: 0,
invalid_examples: 0,
interesting_examples: 0,
@@ -541,6 +580,23 @@
}
}
+ pub fn list_minimized_examples(&self) -> Vec<TestResult> {
+ match &self.loop_response {
+ &Some(LoopCommand::Finished(
+ _,
+ MainGenerationLoop {
+ ref minimized_examples,
+ ..
+ },
+ )) => {
+ let mut results: Vec<TestResult> = minimized_examples.values().map(|v| v.clone()).collect();
+ results.sort();
+ results
+ },
+ _ => Vec::new(),
+ }
+ }
+
pub fn best_source(&self) -> Option<DataSource> {
match &self.loop_response {
&Some(LoopCommand::Finished(
@@ -554,6 +610,7 @@
}
}
+
fn consume_test_result(&mut self, result: TestResult) -> () {
assert!(self.state == EngineState::AwaitingCompletion);
self.state = EngineState::ReadyToProvide;
@@ -623,3 +680,40 @@
}
}
}
+
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use data::FailedDraw;
+
+ fn run_to_results<F>(mut f: F) -> Vec<TestResult>
+ where F: FnMut(&mut DataSource) -> Result {
+ let seed: [u32; 2] = [0, 0];
+ let mut engine = Engine::new(1000, &seed);
+ while let Some(mut source) = engine.next_source() {
+ if let Ok(status) = f(&mut source) {
+ engine.mark_finished(source, status);
+ } else {
+ engine.mark_finished(source, Status::Overflow);
+ }
+ }
+ engine.list_minimized_examples()
+ }
+
+ #[test]
+ fn minimizes_all_examples(){
+ let results = run_to_results(|source| {
+ let n = source.bits(64)?;
+ if n >= 100 {
+ Ok(Status::Interesting(n % 2))
+ } else {
+ Ok(Status::Valid)
+ }
+ });
+
+ assert!(results.len() == 2);
+ assert_eq!(results[0].record[0], 100);
+ assert_eq!(results[1].record[0], 101);
+ }
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hypothesis-hypothesis-python-3.66.1/hypothesis-python/docs/changes.rst new/hypothesis-hypothesis-python-3.66.4/hypothesis-python/docs/changes.rst
--- old/hypothesis-hypothesis-python-3.66.1/hypothesis-python/docs/changes.rst 2018-07-09 01:06:33.000000000 +0200
+++ new/hypothesis-hypothesis-python-3.66.4/hypothesis-python/docs/changes.rst 2018-07-20 15:37:18.000000000 +0200
@@ -21,6 +21,71 @@
You should generally assume that an API is internal unless you have specific
information to the contrary.
+.. _v3.66.4:
+
+-------------------
+3.66.4 - 2018-07-20
+-------------------
+
+This release improves the shrinker's ability to reorder examples.
+
+For example, consider the following test:
+
+.. code-block:: python
+
+ import hypothesis.strategies as st
+ from hypothesis import given
+
+ @given(st.text(), st.text())
+ def test_non_equal(x, y):
+ assert x != y
+
+Previously this could have failed with either of ``x="", y="0"`` or
+``x="0", y=""``. Now it should always fail with ``x="", y="0"``.
+
+This will allow the shrinker to produce more consistent results, especially in
+cases where test cases contain some ordered collection whose actual order does
+not matter.
+
+.. _v3.66.3:
+
+-------------------
+3.66.3 - 2018-07-20
+-------------------
+
+This patch fixes inference in the :func:`~hypothesis.strategies.builds`
+strategy with subtypes of :class:`python:typing.NamedTuple`, where the
+``__init__`` method is not useful for introspection. We now use the
+field types instead - thanks to James Uther for identifying this bug.
+
+.. _v3.66.2:
+
+-------------------
+3.66.2 - 2018-07-19
+-------------------
+
+This release improves the shrinker's ability to handle situations where there
+is an additive constraint between two values.
+
+For example, consider the following test:
+
+
+.. code-block:: python
+
+ import hypothesis.strategies as st
+ from hypothesis import given
+
+ @given(st.integers(), st.integers())
+ def test_does_not_exceed_100(m, n):
+ assert m + n < 100
+
+Previously this could have failed with almost any pair ``(m, n)`` with
+``0 <= m <= n`` and ``m + n == 100``. Now it should almost always fail with
+``m=0, n=100``.
+
+This is a relatively niche specialisation, but can be useful in situations
+where e.g. a bug is triggered by an integer overflow.
+
.. _v3.66.1:
-------------------
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hypothesis-hypothesis-python-3.66.1/hypothesis-python/docs/endorsements.rst new/hypothesis-hypothesis-python-3.66.4/hypothesis-python/docs/endorsements.rst
--- old/hypothesis-hypothesis-python-3.66.1/hypothesis-python/docs/endorsements.rst 2018-07-09 01:06:33.000000000 +0200
+++ new/hypothesis-hypothesis-python-3.66.4/hypothesis-python/docs/endorsements.rst 2018-07-20 15:37:18.000000000 +0200
@@ -185,6 +185,18 @@
__ https://github.com/merchise/xoutil/commit/0a4a0f529812fed363efb653f3ade2d2bc...
+----------------------------------------------
+`Florian Kromer https://github.com/fkromer`_
+----------------------------------------------
+
+At `Roboception GmbH https://roboception.com/en/`_ I use Hypothesis to
+implement fully automated stateless and stateful reliability tests for the
+`3D sensor rc_visard https://roboception.com/en/rc_visard-en/`_ and
+`robotic software components https://roboception.com/en/rc_reason-en/`_ .
+
+Thank you very much for creating the (probably) most powerful property-based
+testing framework.
+
-------------------------------------------
`Your name goes here http://example.com`_
-------------------------------------------
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hypothesis-hypothesis-python-3.66.1/hypothesis-python/docs/examples.rst new/hypothesis-hypothesis-python-3.66.4/hypothesis-python/docs/examples.rst
--- old/hypothesis-hypothesis-python-3.66.1/hypothesis-python/docs/examples.rst 2018-07-09 01:06:33.000000000 +0200
+++ new/hypothesis-hypothesis-python-3.66.4/hypothesis-python/docs/examples.rst 2018-07-20 15:37:18.000000000 +0200
@@ -94,7 +94,7 @@
.. code:: python
- from hypothesis import settings, strategy
+ from hypothesis import settings, strategies
import hypothesis.strategies as s
NodeStrategy = s.builds(
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hypothesis-hypothesis-python-3.66.1/hypothesis-python/src/hypothesis/internal/compat.py new/hypothesis-hypothesis-python-3.66.4/hypothesis-python/src/hypothesis/internal/compat.py
--- old/hypothesis-hypothesis-python-3.66.1/hypothesis-python/src/hypothesis/internal/compat.py 2018-07-09 01:06:33.000000000 +0200
+++ new/hypothesis-hypothesis-python-3.66.4/hypothesis-python/src/hypothesis/internal/compat.py 2018-07-20 15:37:18.000000000 +0200
@@ -25,6 +25,7 @@
import time
import array
import codecs
+import inspect
import platform
import importlib
from base64 import b64encode
@@ -277,7 +278,6 @@
'kwonlyargs, kwonlydefaults, annotations')
def getfullargspec(func):
- import inspect
args, varargs, varkw, defaults = inspect.getargspec(func)
return FullArgSpec(args, varargs, varkw, defaults, [], None,
getattr(func, '__annotations__', {}))
@@ -296,9 +296,10 @@
except TypeError:
return {}
else:
+ import typing
+
def get_type_hints(thing):
try:
- import typing
return typing.get_type_hints(thing)
except TypeError:
return {}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hypothesis-hypothesis-python-3.66.1/hypothesis-python/src/hypothesis/internal/conjecture/engine.py new/hypothesis-hypothesis-python-3.66.4/hypothesis-python/src/hypothesis/internal/conjecture/engine.py
--- old/hypothesis-hypothesis-python-3.66.1/hypothesis-python/src/hypothesis/internal/conjecture/engine.py 2018-07-09 01:06:33.000000000 +0200
+++ new/hypothesis-hypothesis-python-3.66.4/hypothesis-python/src/hypothesis/internal/conjecture/engine.py 2018-07-20 15:37:18.000000000 +0200
@@ -1335,10 +1335,12 @@
if not run_expensive_shrinks:
continue
+ self.reorder_examples()
self.shrink_offset_pairs()
self.interval_deletion_with_block_lowering()
self.pass_to_interval()
self.reorder_bytes()
+ self.minimize_block_pairs_retaining_sum()
@property
def blocks(self):
@@ -2279,3 +2281,104 @@
break
else:
i += 1
+
+ def minimize_block_pairs_retaining_sum(self):
+ """This pass minimizes pairs of blocks subject to the constraint that
+ their sum when interpreted as integers remains the same. This allow us
+ to normalize a number of examples that we would otherwise struggle on.
+ e.g. consider the following:
+
+ m = data.draw_bits(8)
+ n = data.draw_bits(8)
+ if m + n >= 256:
+ data.mark_interesting()
+
+ The ideal example for this is m=1, n=255, but we will almost never
+ find that without a pass like this - we would only do so if we
+ happened to draw n=255 by chance.
+
+ This kind of scenario comes up reasonably often in the context of e.g.
+ triggering overflow behaviour.
+ """
+ i = 0
+ while i < len(self.shrink_target.blocks):
+ if self.is_payload_block(i):
+ j = i + 1
+ while j < len(self.shrink_target.blocks):
+ u, v = self.shrink_target.blocks[i]
+ m = int_from_bytes(self.shrink_target.buffer[u:v])
+ if m == 0:
+ break
+ r, s = self.shrink_target.blocks[j]
+ n = int_from_bytes(self.shrink_target.buffer[r:s])
+
+ if (
+ s - r == v - u and
+ self.is_payload_block(j)
+ ):
+ def trial(x, y):
+ if s > len(self.shrink_target.buffer):
+ return False
+ attempt = bytearray(self.shrink_target.buffer)
+ try:
+ attempt[u:v] = int_to_bytes(x, v - u)
+ attempt[r:s] = int_to_bytes(y, s - r)
+ except OverflowError:
+ return False
+ return self.incorporate_new_buffer(attempt)
+ # We first attempt to move 1 from m to n. If that works
+ # then we treat that as a sign that it's worth trying
+ # a more expensive minimization. But if m was already 1
+ # (we know it's > 0) then there's no point continuing
+ # because the value there is now zero.
+ if trial(m - 1, n + 1) and m > 1:
+ m = int_from_bytes(self.shrink_target.buffer[u:v])
+ n = int_from_bytes(self.shrink_target.buffer[r:s])
+
+ tot = m + n
+ minimize_int(
+ m, lambda x: trial(x, tot - x)
+ )
+ j += 1
+ i += 1
+
+ def reorder_examples(self):
+ """This pass allows us to reorder pairs of examples which come from the
+ same strategy (or strategies that happen to pun to the same label by
+ accident, but that shouldn't happen often).
+
+ For example, consider the following:
+
+ .. code-block:: python
+
+ import hypothesis.strategies as st
+ from hypothesis import given
+
+ @given(st.text(), st.text())
+ def test_does_not_exceed_100(x, y):
+ assert x != y
+
+ Without the ability to reorder x and y this could fail either with
+ ``x="", ``y="0"``, or the other way around. With reordering it will
+ reliably fail with ``x=""``, ``y="0"``.
+ """
+ i = 0
+ while i < len(self.shrink_target.examples):
+ j = i + 1
+ while j < len(self.shrink_target.examples):
+ ex1 = self.shrink_target.examples[i]
+ ex2 = self.shrink_target.examples[j]
+ if ex1.label == ex2.label and ex2.start >= ex1.end:
+ buf = self.shrink_target.buffer
+ attempt = (
+ buf[:ex1.start] +
+ buf[ex2.start:ex2.end] +
+ buf[ex1.end:ex2.start] +
+ buf[ex1.start:ex1.end] +
+ buf[ex2.end:]
+ )
+ assert len(attempt) == len(buf)
+ if attempt < buf:
+ self.incorporate_new_buffer(attempt)
+ j += 1
+ i += 1
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hypothesis-hypothesis-python-3.66.1/hypothesis-python/src/hypothesis/internal/reflection.py new/hypothesis-hypothesis-python-3.66.4/hypothesis-python/src/hypothesis/internal/reflection.py
--- old/hypothesis-hypothesis-python-3.66.1/hypothesis-python/src/hypothesis/internal/reflection.py 2018-07-09 01:06:33.000000000 +0200
+++ new/hypothesis-hypothesis-python-3.66.4/hypothesis-python/src/hypothesis/internal/reflection.py 2018-07-20 15:37:18.000000000 +0200
@@ -88,6 +88,18 @@
return hasher.digest()
+def is_typed_named_tuple(cls):
+ """Return True if cls is probably a subtype of `typing.NamedTuple`.
+
+ Unfortunately types created with `class T(NamedTuple):` actually
+ subclass `tuple` directly rather than NamedTuple. This is annoying,
+ and means we just have to hope that nobody defines a different tuple
+ subclass with similar attributes.
+ """
+ return issubclass(cls, tuple) and hasattr(cls, '_fields') and \
+ hasattr(cls, '_field_types')
+
+
def required_args(target, args=(), kwargs=()):
"""Return a set of names of required args to target that were not supplied
in args or kwargs.
@@ -97,6 +109,11 @@
and bound methods). args and kwargs should be as they are passed to
builds() - that is, a tuple of values and a dict of names: values.
"""
+ # We start with a workaround for NamedTuples, which don't have nice inits
+ if inspect.isclass(target) and is_typed_named_tuple(target):
+ provided = set(kwargs) | set(target._fields[:len(args)])
+ return set(target._fields) - provided
+ # Then we try to do the right thing with getfullargspec
try:
spec = getfullargspec(
target.__init__ if inspect.isclass(target) else target)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hypothesis-hypothesis-python-3.66.1/hypothesis-python/src/hypothesis/strategies.py new/hypothesis-hypothesis-python-3.66.4/hypothesis-python/src/hypothesis/strategies.py
--- old/hypothesis-hypothesis-python-3.66.1/hypothesis-python/src/hypothesis/strategies.py 2018-07-09 01:06:33.000000000 +0200
+++ new/hypothesis-hypothesis-python-3.66.4/hypothesis-python/src/hypothesis/strategies.py 2018-07-20 15:37:18.000000000 +0200
@@ -46,7 +46,7 @@
from hypothesis.internal.renaming import renamed_arguments
from hypothesis.utils.conventions import infer, not_set
from hypothesis.internal.reflection import proxies, required_args, \
- define_function_signature
+ is_typed_named_tuple, define_function_signature
from hypothesis.internal.validation import check_type, try_convert, \
check_valid_size, check_valid_bound, check_valid_sizes, \
check_valid_integer, check_valid_interval, check_valid_magnitude
@@ -1125,8 +1125,14 @@
from hypothesis.searchstrategy.attrs import from_attrs
return from_attrs(target, args, kwargs, required | to_infer)
# Otherwise, try using type hints
- hints = get_type_hints(
- target.__init__ if isclass(target) else target)
+ if isclass(target):
+ if is_typed_named_tuple(target):
+ # Special handling for typing.NamedTuple
+ hints = target._field_types
+ else:
+ hints = get_type_hints(target.__init__)
+ else:
+ hints = get_type_hints(target)
if to_infer - set(hints):
raise InvalidArgument(
'passed infer for %s, but there is no type annotation'
@@ -1248,25 +1254,22 @@
return one_of(strategies)
# If we don't have a strategy registered for this type or any subtype, we
# may be able to fall back on type annotations.
- # Types created via typing.NamedTuple use a custom attribute instead -
- # but we can still use builds(), if we work out the right kwargs.
- if issubclass(thing, tuple) and hasattr(thing, '_fields') \
- and hasattr(thing, '_field_types'):
- kwargs = {k: from_type(thing._field_types[k]) for k in thing._fields}
- return builds(thing, **kwargs)
if issubclass(thing, enum.Enum):
assert len(thing), repr(thing) + ' has no members to sample'
return sampled_from(thing)
- # If the constructor has an annotation for all required arguments,
- # or the class was defined with attrs, builds(thing) will work.
- # (unless inference fails for an argument, but that's the same above too)
+ # If we know that builds(thing) will fail, give a better error message
required = required_args(thing)
- if not required or required.issubset(get_type_hints(thing.__init__)) or \
- attr.has(thing):
- return builds(thing)
- # We have utterly failed, and might as well say so now.
- raise ResolutionFailed('Could not resolve %r to a strategy; consider '
- 'using register_type_strategy' % (thing,))
+ if not any([
+ not required,
+ required.issubset(get_type_hints(thing.__init__)),
+ attr.has(thing),
+ # NamedTuples are weird enough that we need a specific check for them.
+ is_typed_named_tuple(thing),
+ ]):
+ raise ResolutionFailed('Could not resolve %r to a strategy; consider '
+ 'using register_type_strategy' % (thing,))
+ # Finally, try to build an instance by calling the type object
+ return builds(thing)
@cacheable
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hypothesis-hypothesis-python-3.66.1/hypothesis-python/src/hypothesis/version.py new/hypothesis-hypothesis-python-3.66.4/hypothesis-python/src/hypothesis/version.py
--- old/hypothesis-hypothesis-python-3.66.1/hypothesis-python/src/hypothesis/version.py 2018-07-09 01:06:33.000000000 +0200
+++ new/hypothesis-hypothesis-python-3.66.4/hypothesis-python/src/hypothesis/version.py 2018-07-20 15:37:18.000000000 +0200
@@ -17,5 +17,5 @@
from __future__ import division, print_function, absolute_import
-__version_info__ = (3, 66, 1)
+__version_info__ = (3, 66, 4)
__version__ = '.'.join(map(str, __version_info__))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hypothesis-hypothesis-python-3.66.1/hypothesis-python/tests/cover/test_conjecture_engine.py new/hypothesis-hypothesis-python-3.66.4/hypothesis-python/tests/cover/test_conjecture_engine.py
--- old/hypothesis-hypothesis-python-3.66.1/hypothesis-python/tests/cover/test_conjecture_engine.py 2018-07-09 01:06:33.000000000 +0200
+++ new/hypothesis-hypothesis-python-3.66.4/hypothesis-python/tests/cover/test_conjecture_engine.py 2018-07-20 15:37:18.000000000 +0200
@@ -1330,3 +1330,69 @@
runner.run()
assert runner.exit_reason == ExitReason.finished
+
+
+@pytest.mark.parametrize('lo', [0, 1, 50])
+def test_can_shrink_additively(monkeypatch, lo):
+ monkeypatch.setattr(
+ ConjectureRunner, 'generate_new_examples',
+ lambda self: self.test_function(
+ ConjectureData.for_buffer(hbytes([100, 100]))))
+
+ @run_to_buffer
+ def x(data):
+ m = data.draw_bits(8)
+ n = data.draw_bits(8)
+ if m >= lo and m + n == 200:
+ data.mark_interesting()
+
+ assert list(x) == [lo, 200 - lo]
+
+
+def test_can_shrink_additively_losing_size(monkeypatch):
+ monkeypatch.setattr(
+ ConjectureRunner, 'generate_new_examples',
+ lambda self: self.test_function(
+ ConjectureData.for_buffer(hbytes([100, 100]))))
+
+ monkeypatch.setattr(
+ Shrinker, 'shrink', lambda self: (
+ self.minimize_block_pairs_retaining_sum(),
+ )
+ )
+
+ @run_to_buffer
+ def x(data):
+ m = data.draw_bits(8)
+ if m >= 10:
+ if m <= 50:
+ data.mark_interesting()
+ else:
+ n = data.draw_bits(8)
+ if m + n == 200:
+ data.mark_interesting()
+ assert len(x) == 1
+
+
+def test_can_reorder_examples(monkeypatch):
+ monkeypatch.setattr(
+ ConjectureRunner, 'generate_new_examples',
+ lambda runner: runner.test_function(
+ ConjectureData.for_buffer([1, 0, 1, 1, 0, 1, 0, 0, 0])))
+
+ monkeypatch.setattr(
+ Shrinker, 'shrink', Shrinker.reorder_examples,
+ )
+
+ @run_to_buffer
+ def x(data):
+ total = 0
+ for _ in range(5):
+ data.start_example(0)
+ if data.draw_bits(8):
+ total += data.draw_bits(9)
+ data.stop_example(0)
+ if total == 2:
+ data.mark_interesting()
+
+ assert list(x) == [0, 0, 0, 1, 0, 1, 1, 0, 1]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hypothesis-hypothesis-python-3.66.1/hypothesis-python/tests/py3/test_lookup.py new/hypothesis-hypothesis-python-3.66.4/hypothesis-python/tests/py3/test_lookup.py
--- old/hypothesis-hypothesis-python-3.66.1/hypothesis-python/tests/py3/test_lookup.py 2018-07-09 01:06:33.000000000 +0200
+++ new/hypothesis-hypothesis-python-3.66.4/hypothesis-python/tests/py3/test_lookup.py 2018-07-20 15:37:18.000000000 +0200
@@ -367,6 +367,24 @@
**{k: st.just(v) for k, v in kwargs.items()}).example()
+AnnotatedNamedTuple = typing.NamedTuple('AnnotatedNamedTuple', [('a', str)])
+
+
+@given(st.builds(AnnotatedNamedTuple))
+def test_infers_args_for_namedtuple_builds(thing):
+ assert isinstance(thing.a, str)
+
+
+@given(st.from_type(AnnotatedNamedTuple))
+def test_infers_args_for_namedtuple_from_type(thing):
+ assert isinstance(thing.a, str)
+
+
+@given(st.builds(AnnotatedNamedTuple, a=st.none()))
+def test_override_args_for_namedtuple(thing):
+ assert thing.a is None
+
+
@pytest.mark.parametrize('thing', [
typing.Optional, typing.List, getattr(typing, 'Type', typing.Set)
]) # check Type if it's available, otherwise Set is redundant but harmless
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hypothesis-hypothesis-python-3.66.1/hypothesis-ruby/.rubocop.yml new/hypothesis-hypothesis-python-3.66.4/hypothesis-ruby/.rubocop.yml
--- old/hypothesis-hypothesis-python-3.66.1/hypothesis-ruby/.rubocop.yml 2018-07-09 01:06:33.000000000 +0200
+++ new/hypothesis-hypothesis-python-3.66.4/hypothesis-ruby/.rubocop.yml 2018-07-20 15:37:18.000000000 +0200
@@ -26,3 +26,5 @@
Enabled: false
Lint/HandleExceptions:
Enabled: false
+Style/GuardClause:
+ Enabled: false
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hypothesis-hypothesis-python-3.66.1/hypothesis-ruby/CHANGELOG.md new/hypothesis-hypothesis-python-3.66.4/hypothesis-ruby/CHANGELOG.md
--- old/hypothesis-hypothesis-python-3.66.1/hypothesis-ruby/CHANGELOG.md 2018-07-09 01:06:33.000000000 +0200
+++ new/hypothesis-hypothesis-python-3.66.4/hypothesis-ruby/CHANGELOG.md 2018-07-20 15:37:18.000000000 +0200
@@ -1,3 +1,8 @@
+# Hypothesis for Ruby 0.1.0 (2018-07-16)
+
+This release adds support for reporting multiple exceptions when Hypothesis
+finds more than one way for the test to fail.
+
# Hypothesis for Ruby 0.0.15 (2018-06-25)
This release fixes an occasional `RuntimeError` that could occur
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hypothesis-hypothesis-python-3.66.1/hypothesis-ruby/Gemfile.lock new/hypothesis-hypothesis-python-3.66.4/hypothesis-ruby/Gemfile.lock
--- old/hypothesis-hypothesis-python-3.66.1/hypothesis-ruby/Gemfile.lock 2018-07-09 01:06:33.000000000 +0200
+++ new/hypothesis-hypothesis-python-3.66.4/hypothesis-ruby/Gemfile.lock 2018-07-20 15:37:18.000000000 +0200
@@ -1,7 +1,7 @@
PATH
remote: .
specs:
- hypothesis-specs (0.0.14)
+ hypothesis-specs (0.0.15)
helix_runtime (~> 0.7.0)
rake (>= 10.0, < 13.0)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hypothesis-hypothesis-python-3.66.1/hypothesis-ruby/hypothesis-specs.gemspec new/hypothesis-hypothesis-python-3.66.4/hypothesis-ruby/hypothesis-specs.gemspec
--- old/hypothesis-hypothesis-python-3.66.1/hypothesis-ruby/hypothesis-specs.gemspec 2018-07-09 01:06:33.000000000 +0200
+++ new/hypothesis-hypothesis-python-3.66.4/hypothesis-ruby/hypothesis-specs.gemspec 2018-07-20 15:37:18.000000000 +0200
@@ -2,8 +2,8 @@
Gem::Specification.new do |s|
s.name = 'hypothesis-specs'
- s.version = '0.0.15'
- s.date = '2018-06-25'
+ s.version = '0.1.0'
+ s.date = '2018-07-16'
s.description = <<~DESCRIPTION
Hypothesis is a powerful, flexible, and easy to use library for property-based testing.
DESCRIPTION
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hypothesis-hypothesis-python-3.66.1/hypothesis-ruby/lib/hypothesis/engine.rb new/hypothesis-hypothesis-python-3.66.4/hypothesis-ruby/lib/hypothesis/engine.rb
--- old/hypothesis-hypothesis-python-3.66.1/hypothesis-ruby/lib/hypothesis/engine.rb 2018-07-09 01:06:33.000000000 +0200
+++ new/hypothesis-hypothesis-python-3.66.4/hypothesis-ruby/lib/hypothesis/engine.rb 2018-07-20 15:37:18.000000000 +0200
@@ -2,9 +2,12 @@
require 'helix_runtime'
require 'hypothesis-ruby/native'
+require 'rspec/expectations'
module Hypothesis
class Engine
+ include RSpec::Matchers
+
attr_reader :current_source
attr_accessor :is_find
@@ -13,6 +16,8 @@
@core_engine = HypothesisCoreEngine.new(
seed, options.fetch(:max_examples)
)
+
+ @exceptions_to_tags = Hash.new { |h, k| h[k] = h.size }
end
def run
@@ -23,7 +28,7 @@
begin
result = yield(@current_source)
if is_find && result
- @core_engine.finish_interesting(core)
+ @core_engine.finish_interesting(core, 0)
else
@core_engine.finish_valid(core)
end
@@ -31,54 +36,64 @@
@core_engine.finish_invalid(core)
rescue DataOverflow
@core_engine.finish_overflow(core)
- rescue Exception
+ rescue Exception => e
raise if is_find
- @core_engine.finish_interesting(core)
+ key = [
+ e.class,
+ HypothesisJunkDrawer.find_first_relevant_line(e.backtrace)
+ ]
+ @core_engine.finish_interesting(core, @exceptions_to_tags[key])
end
end
- @current_source = nil
- core = @core_engine.failing_example
- if core.nil?
+ if @core_engine.count_failing_examples.zero?
raise Unsatisfiable if @core_engine.was_unsatisfiable
+ @current_source = nil
return
end
if is_find
+ core = @core_engine.failing_example(0)
@current_source = TestCase.new(core, record_draws: true)
yield @current_source
else
- @current_source = TestCase.new(core, print_draws: true)
-
- begin
- yield @current_source
- rescue Exception => e
- givens = @current_source.print_log
- given_str = givens.each_with_index.map do |(name, s), i|
- name = "##{i + 1}" if name.nil?
- "Given #{name}: #{s}"
- end.to_a
-
- if e.respond_to? :hypothesis_data
- e.hypothesis_data[0] = given_str
- else
- original_to_s = e.to_s
- original_inspect = e.inspect
-
- class < e
+ givens = @current_source.print_log
+ given_str = givens.each_with_index.map do |(name, s), i|
+ name = "##{i + 1}" if name.nil?
+ "Given #{name}: #{s}"
+ end.to_a
+
+ if e.respond_to? :hypothesis_data
+ e.hypothesis_data[0] = given_str
+ else
+ original_to_s = e.to_s
+ original_inspect = e.inspect
+
+ class <= 1000
+ @initial = x
+ else
+ next
+ end
+ end
+
+ assert(x != @initial)
+ raise 'Nope'
+ end
+ end
+ end
+end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hypothesis-hypothesis-python-3.66.1/hypothesis-ruby/spec/backtrace_spec.rb new/hypothesis-hypothesis-python-3.66.4/hypothesis-ruby/spec/backtrace_spec.rb
--- old/hypothesis-hypothesis-python-3.66.1/hypothesis-ruby/spec/backtrace_spec.rb 1970-01-01 01:00:00.000000000 +0100
+++ new/hypothesis-hypothesis-python-3.66.4/hypothesis-ruby/spec/backtrace_spec.rb 2018-07-20 15:37:18.000000000 +0200
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+RSpec.describe 'backtrace manipulation' do
+ JD = Hypothesis::HypothesisJunkDrawer
+
+ it 'identifies the test file as relevant' do
+ JD.find_first_relevant_line(caller).include?('backtrace_spec.rb')
+ end
+
+ it 'prunes out hypothesis and rspec related lines' do
+ hypothesis do
+ relevant = JD.prune_backtrace(caller)
+ relevant.each do |e|
+ expect(e).to_not include(JD::HYPOTHESIS_ROOT)
+ expect(e).to_not include('/rspec-core/')
+ end
+ expect(relevant.grep(/backtrace_spec.rb/)).to_not be_empty
+ end
+ end
+end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hypothesis-hypothesis-python-3.66.1/hypothesis-ruby/spec/multiple_failures_spec.rb new/hypothesis-hypothesis-python-3.66.4/hypothesis-ruby/spec/multiple_failures_spec.rb
--- old/hypothesis-hypothesis-python-3.66.1/hypothesis-ruby/spec/multiple_failures_spec.rb 1970-01-01 01:00:00.000000000 +0100
+++ new/hypothesis-hypothesis-python-3.66.4/hypothesis-ruby/spec/multiple_failures_spec.rb 2018-07-20 15:37:18.000000000 +0200
@@ -0,0 +1,42 @@
+# frozen_string_literal: true
+
+RSpec.describe 'tests with multiple failures' do
+ they 'show multiple failures' do
+ expect do
+ @initial = nil
+
+ hypothesis do
+ x = any integers
+ if @initial.nil?
+ if x >= 1000
+ @initial = x
+ else
+ next
+ end
+ end
+
+ expect(x).to_not eq(@initial)
+ raise 'Nope'
+ end
+ end.to raise_exception(Hypothesis::MultipleExceptionError) { |e|
+ expect(e.all_exceptions.length).to eq(2)
+ }
+ end
+end
+
+RSpec.describe Hypothesis::MultipleExceptionError do
+ it 'includes the message from each exception' do
+ exceptions = []
+ %w[hello world].each do |m|
+ begin
+ raise m
+ rescue Exception => e
+ exceptions.append(e)
+ end
+ end
+
+ e = Hypothesis::MultipleExceptionError.new(*exceptions)
+ expect(e.message).to include('hello')
+ expect(e.message).to include('world')
+ end
+end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hypothesis-hypothesis-python-3.66.1/hypothesis-ruby/spec/spec_helper.rb new/hypothesis-hypothesis-python-3.66.4/hypothesis-ruby/spec/spec_helper.rb
--- old/hypothesis-hypothesis-python-3.66.1/hypothesis-ruby/spec/spec_helper.rb 2018-07-09 01:06:33.000000000 +0200
+++ new/hypothesis-hypothesis-python-3.66.4/hypothesis-ruby/spec/spec_helper.rb 2018-07-20 15:37:18.000000000 +0200
@@ -2,10 +2,51 @@
require 'simplecov'
SimpleCov.minimum_coverage 100
+
+class PrintingFormatter
+ # Takes a SimpleCov::Result and generates a string out of it
+ def format(result)
+ bad = []
+ result.files.each do |file|
+ bad.push file if file.covered_percent < 100.0
+ end
+
+ unless bad.empty?
+ puts 'Files with missing coverage!'
+ bad.each do |file|
+ lines = file.source_lines.select { |l| l.coverage == 0 }
+ .map(&:line_number).sort
+ s = lines[0]
+ groups = [[s, s]]
+ lines.each do |i|
+ if i <= groups[-1][-1] + 1
+ groups[-1][-1] = i
+ else
+ groups.push([i, i])
+ end
+ end
+ markers = []
+ groups.each do |g|
+ if g[0] == g[1]
+ markers.push(g[0].to_s)
+ else
+ markers.push(g.join('-'))
+ end
+ end
+ puts "#{file.filename}: #{markers.join(', ')}"
+ end
+ end
+ end
+end
+
+SimpleCov.formatters = SimpleCov::Formatter::MultiFormatter.new(
+ [SimpleCov::Formatter::HTMLFormatter, PrintingFormatter]
+)
+
SimpleCov.start do
add_filter do |source_file|
name = source_file.filename
- !(name.include?('/hypothesis/') || name.end_with?('hypothesis.rb'))
+ !(name.include?('/hypothesis-ruby/lib/') || name.end_with?('hypothesis.rb'))
end
end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hypothesis-hypothesis-python-3.66.1/hypothesis-ruby/src/lib.rs new/hypothesis-hypothesis-python-3.66.4/hypothesis-ruby/src/lib.rs
--- old/hypothesis-hypothesis-python-3.66.1/hypothesis-ruby/src/lib.rs 2018-07-09 01:06:33.000000000 +0200
+++ new/hypothesis-hypothesis-python-3.66.4/hypothesis-ruby/src/lib.rs 2018-07-20 15:37:18.000000000 +0200
@@ -15,7 +15,7 @@
use std::mem;
-use conjecture::data::{DataSource, Status};
+use conjecture::data::{DataSource, Status, TestResult};
use conjecture::distributions::Repeat;
use conjecture::distributions;
use conjecture::engine::Engine;
@@ -49,6 +49,7 @@
struct {
engine: Engine,
pending: Option<DataSource>,
+ interesting_examples: Vec<TestResult>,
}
def initialize(helix, seed: u64, max_examples: u64){
@@ -57,12 +58,16 @@
helix,
engine: Engine::new(max_examples, &xs),
pending: None,
+ interesting_examples: Vec::new(),
}
}
def new_source(&mut self) -> Option<HypothesisCoreDataSource> {
match self.engine.next_source() {
- None => None,
+ None => {
+ self.interesting_examples = self.engine.list_minimized_examples();
+ None
+ },
Some(source) => {
self.pending = Some(source);
Some(HypothesisCoreDataSource::new(self))
@@ -70,13 +75,15 @@
}
}
- def failing_example(&mut self) -> Option<HypothesisCoreDataSource> {
- if let Some(source) = self.engine.best_source() {
- self.pending = Some(source);
- return Some(HypothesisCoreDataSource::new(self));
- } else {
- return None;
- }
+ def count_failing_examples(&self) -> usize {
+ self.interesting_examples.len()
+ }
+
+ def failing_example(&mut self, i: usize) -> HypothesisCoreDataSource {
+ self.pending = Some(
+ DataSource::from_vec(self.interesting_examples[i].record.clone())
+ );
+ HypothesisCoreDataSource::new(self)
}
def was_unsatisfiable(&mut self) -> bool {
@@ -91,8 +98,8 @@
mark_child_status(&mut self.engine, child, Status::Invalid);
}
- def finish_interesting(&mut self, child: &mut HypothesisCoreDataSource){
- mark_child_status(&mut self.engine, child, Status::Interesting);
+ def finish_interesting(&mut self, child: &mut HypothesisCoreDataSource, label: u64){
+ mark_child_status(&mut self.engine, child, Status::Interesting(label));
}
def finish_valid(&mut self, child: &mut HypothesisCoreDataSource){
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hypothesis-hypothesis-python-3.66.1/requirements/coverage.txt new/hypothesis-hypothesis-python-3.66.4/requirements/coverage.txt
--- old/hypothesis-hypothesis-python-3.66.1/requirements/coverage.txt 2018-07-09 01:06:33.000000000 +0200
+++ new/hypothesis-hypothesis-python-3.66.4/requirements/coverage.txt 2018-07-20 15:37:18.000000000 +0200
@@ -6,7 +6,7 @@
#
coverage==4.5.1
numpy==1.14.5
-pandas==0.23.1
+pandas==0.23.3
python-dateutil==2.7.3 # via pandas
pytz==2018.5
six==1.11.0 # via python-dateutil
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hypothesis-hypothesis-python-3.66.1/requirements/test.txt new/hypothesis-hypothesis-python-3.66.4/requirements/test.txt
--- old/hypothesis-hypothesis-python-3.66.1/requirements/test.txt 2018-07-09 01:06:33.000000000 +0200
+++ new/hypothesis-hypothesis-python-3.66.4/requirements/test.txt 2018-07-20 15:37:18.000000000 +0200
@@ -4,17 +4,17 @@
#
# pip-compile --output-file requirements/test.txt requirements/test.in
#
-apipkg==1.4 # via execnet
+apipkg==1.5 # via execnet
atomicwrites==1.1.5 # via pytest
attrs==18.1.0
execnet==1.5.0 # via pytest-xdist
flaky==3.4.0
mock==2.0.0
more-itertools==4.2.0 # via pytest
-pbr==4.0.4 # via mock
+pbr==4.1.0 # via mock
pluggy==0.6.0 # via pytest
py==1.5.4 # via pytest
pytest-forked==0.2 # via pytest-xdist
pytest-xdist==1.22.2
-pytest==3.6.2
+pytest==3.6.3
six==1.11.0 # via mock, more-itertools, pytest
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hypothesis-hypothesis-python-3.66.1/requirements/tools.in new/hypothesis-hypothesis-python-3.66.4/requirements/tools.in
--- old/hypothesis-hypothesis-python-3.66.1/requirements/tools.in 2018-07-09 01:06:33.000000000 +0200
+++ new/hypothesis-hypothesis-python-3.66.4/requirements/tools.in 2018-07-20 15:37:18.000000000 +0200
@@ -17,7 +17,3 @@
django
numpy
IPython
-
-prompt-toolkit==1.0.15 # via ipython==6.4.0
-pycodestyle==2.3.1 # via flake8==3.5.0
-pyflakes==1.6.0 # via flake8==3.5.0
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hypothesis-hypothesis-python-3.66.1/requirements/tools.txt new/hypothesis-hypothesis-python-3.66.4/requirements/tools.txt
--- old/hypothesis-hypothesis-python-3.66.1/requirements/tools.txt 2018-07-09 01:06:33.000000000 +0200
+++ new/hypothesis-hypothesis-python-3.66.4/requirements/tools.txt 2018-07-20 15:37:18.000000000 +0200
@@ -34,43 +34,43 @@
markupsafe==1.0 # via jinja2
mccabe==0.6.1 # via flake8
more-itertools==4.2.0 # via pytest
-mypy==0.610
+mypy==0.620
numpy==1.14.5
-packaging==17.1 # via dparse, pyupio, safety, sphinx
+packaging==17.1 # via dparse, pyupio, safety, sphinx, tox
parso==0.3.0 # via jedi
pexpect==4.6.0 # via ipython
pickleshare==0.7.4 # via ipython
pip-tools==2.0.2
pkginfo==1.4.2 # via twine
pluggy==0.6.0 # via pytest, tox
-prompt-toolkit==1.0.15
+prompt-toolkit==1.0.15 # via ipython
ptyprocess==0.6.0 # via pexpect
py==1.5.4 # via pytest, tox
-pycodestyle==2.3.1
+pycodestyle==2.3.1 # via autopep8, flake8
pydocstyle==2.1.1 # via flake8-docstrings
-pyflakes==1.6.0
+pyflakes==1.6.0 # via autoflake, flake8
pyformat==0.7
pygithub==1.40 # via pyupio
pygments==2.2.0 # via ipython, sphinx
pyjwt==1.6.4 # via pygithub
pyparsing==2.2.0 # via packaging
-pytest==3.6.2
+pytest==3.6.3
python-dateutil==2.7.3
python-gitlab==1.5.1 # via pyupio
pytz==2018.5 # via babel, django
pyupio==1.0.1
-pyyaml==3.12 # via dparse, pyupio
+pyyaml==3.13 # via dparse, pyupio
requests-toolbelt==0.8.0 # via twine
requests==2.19.1 # via pygithub, python-gitlab, pyupio, requests-toolbelt, safety, sphinx, twine
restructuredtext-lint==1.1.3
-safety==1.8.1 # via pyupio
+safety==1.8.2 # via pyupio
simplegeneric==0.8.1 # via ipython
six==1.11.0 # via dparse, more-itertools, packaging, pip-tools, prompt-toolkit, pydocstyle, pytest, python-dateutil, python-gitlab, pyupio, sphinx, tox, traitlets
snowballstemmer==1.2.1 # via pydocstyle, sphinx
sphinx-rtd-theme==0.4.0
sphinx==1.7.5
sphinxcontrib-websupport==1.1.0 # via sphinx
-tox==3.0.0
+tox==3.1.2
tqdm==4.23.4 # via pyupio, twine
traitlets==4.3.2 # via ipython
twine==1.11.0
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hypothesis-hypothesis-python-3.66.1/tooling/scripts/ensure-rustup.sh new/hypothesis-hypothesis-python-3.66.4/tooling/scripts/ensure-rustup.sh
--- old/hypothesis-hypothesis-python-3.66.1/tooling/scripts/ensure-rustup.sh 2018-07-09 01:06:33.000000000 +0200
+++ new/hypothesis-hypothesis-python-3.66.4/tooling/scripts/ensure-rustup.sh 2018-07-20 15:37:18.000000000 +0200
@@ -13,4 +13,4 @@
rustup default stable
-rustup update
+rustup update stable