///|
pub fn py_bool() -> @qc.Gen[@py.PyBool] {
let gen : @qc.Gen[Bool] = @qc.Gen::spawn()
gen.fmap(@py.PyBool::from(_))
}
///|
pub fn py_integer() -> @qc.Gen[@py.PyInteger] {
let gen : @qc.Gen[Int64] = @qc.Gen::spawn()
gen.fmap(@py.PyInteger::from(_))
}
///|
pub fn py_float() -> @qc.Gen[@py.PyFloat] {
let gen : @qc.Gen[Double] = @qc.Gen::spawn()
gen.fmap(@py.PyFloat::from(_))
}
///|
pub fn py_string() -> @qc.Gen[@py.PyString] {
let gen : @qc.Gen[String] = @qc.Gen::spawn()
gen.fmap(@py.PyString::from(_))
}
///|
pub impl[T : @cqc.Arbitrary + PyObjectInto] @cqc.Arbitrary for TypedPyList[T] with arbitrary(
size : Int,
rng : @qc.RandomState,
) -> TypedPyList[T] {
let arr : Array[T] = @cqc.Arbitrary::arbitrary(size, rng)
let arr_gen = arr.map(x => x.to_py_object())
{ data: @py.PyList::from(arr_gen) }
}
///|
pub fn[A : @cqc.Arbitrary + PyObjectInto, B : @cqc.Arbitrary + PyObjectInto] py_tuple2() -> @qc.Gen[
TypedPyTuple2[A, B],
] {
@qc.Gen::new(fn(size, rng) {
let a : A = @cqc.Arbitrary::arbitrary(size, rng)
let b : B = @cqc.Arbitrary::arbitrary(size, rng)
let tuple = @py.PyTuple::new(2)
tuple..set(0, a.to_py_object())
tuple..set(1, b.to_py_object())
{ tuple2: tuple }
})
}
///|
pub impl[A : @cqc.Arbitrary + PyObjectInto, B : @cqc.Arbitrary + PyObjectInto] @cqc.Arbitrary for TypedPyTuple2[
A,
B,
] with arbitrary(size : Int, rng : @qc.RandomState) {
let a : A = @cqc.Arbitrary::arbitrary(size, rng)
let b : B = @cqc.Arbitrary::arbitrary(size, rng)
let tuple = @py.PyTuple::new(2)
tuple..set(0, a.to_py_object())
tuple..set(1, b.to_py_object())
{ tuple2: tuple }
}
///|
pub impl[
A : @cqc.Arbitrary + PyObjectInto,
B : @cqc.Arbitrary + PyObjectInto,
C : @cqc.Arbitrary + PyObjectInto,
] @cqc.Arbitrary for TypedPyTuple3[A, B, C] with arbitrary(
size : Int,
rng : @qc.RandomState,
) {
let a : A = @cqc.Arbitrary::arbitrary(size, rng)
let b : B = @cqc.Arbitrary::arbitrary(size, rng)
let c : C = @cqc.Arbitrary::arbitrary(size, rng)
let tuple = @py.PyTuple::new(3)
tuple..set(0, a.to_py_object())
tuple..set(1, b.to_py_object())
tuple..set(2, c.to_py_object())
{ tuple3: tuple }
}
///|
pub impl[B : @cqc.Arbitrary + PyObjectInto] @cqc.Arbitrary for TypedPyDict[B] with arbitrary(
size,
eng,
) {
let kvs : Array[(String, B)] = @cqc.Arbitrary::arbitrary(size, eng)
let dict = @py.PyDict::new()
for _, sv in kvs {
let (s, v) = sv
dict.set(s, v.to_py_object())
}
{ dict, }
}
///|
test "rng typed py list" {
let gen : @qc.Gen[TypedPyList[Int]] = @qc.Gen::spawn()
let sample = gen.run(230, @splitmix.new(seed=22))
inspect(sample, content="[0, 0, 0, 0, 2, 1, 0, 1, -2, 8]")
}
///|
test "rng typed py dict" {
let gen : @qc.Gen[TypedPyDict[Int64]] = @qc.Gen::spawn()
let sample = gen.run(50, @splitmix.new(seed=1234))
inspect(
sample,
content=(
#|{'': -2, 'c': 2, '\x17xy\x0b': 4, '^*': 0, 'nl\x02#F': 4, '}k>U\x15"Z': 2, '8 \x12zzyQ': 1, '\x07X\x04!': 9, '#ZZ\t': 9, "h*\x18\x135p'F": -11}
),
)
}
///|
test "rng typed py tuple2" {
let gen : @qc.Gen[TypedPyTuple2[String, Double]] = @qc.Gen::spawn()
let sample = gen.run(40, @splitmix.new(seed=32))
inspect(sample, content="('K', 0.3914602989489513)")
}
///|
test "rng typed py tuple3" {
let gen : @qc.Gen[TypedPyTuple3[Int64, String, Bool]] = @qc.Gen::spawn()
let sample = gen.run(15, @splitmix.new(seed=412))
inspect(sample, content="(-3, '\\x02vY)', True)")
}
///|
test {
let nums = [1L, 1, 2, 2, 3, 3, 3, 4, 4, 4, 4]
let py_nums = nums.map(@py.PyInteger::from) |> @py.PyList::from
guard @py.pyimport("collections") is Some(collections)
// It's equivalent to `from collections import Counter`
guard collections.get_attr("Counter") is Some(PyCallable(counter))
let args = @py.PyTuple::new(1)
args..set(0, py_nums)
guard (try? counter.invoke(args~)) is Ok(Some(cnt))
guard cnt is PyDict(cnt)
println(cnt)
}