Skip to content

Commit 9f01439

Browse files
authored
refactor tests to match refactored modules (#412)
Co-authored-by: Christopher Doris <github.com/cjdoris>
1 parent 49e307f commit 9f01439

File tree

5 files changed

+643
-643
lines changed

5 files changed

+643
-643
lines changed

test/abstract.jl renamed to test/Py.jl

+390
Original file line numberDiff line numberDiff line change
@@ -402,3 +402,393 @@ end
402402
@test pyeq(Bool, pybuiltins.eval(ans, pydict()), 7)
403403
end
404404
end
405+
406+
@testitem "import" begin
407+
sys = pyimport("sys")
408+
os = pyimport("os")
409+
@test pyeq(Bool, sys.__name__, "sys")
410+
@test pyeq(Bool, os.__name__, "os")
411+
sysos = pyimport("sys", "os")
412+
@test sysos isa Tuple{Py, Py}
413+
@test pyis(sysos[1], sys)
414+
@test pyis(sysos[2], os)
415+
ver = pyimport("sys" => "version")
416+
@test pyis(ver, sys.version)
417+
path = pyimport("sys" => "path")
418+
@test pyis(path, sys.path)
419+
verpath = pyimport("sys" => ("version", "path"))
420+
@test verpath isa Tuple{Py, Py}
421+
@test pyis(verpath[1], ver)
422+
@test pyis(verpath[2], path)
423+
end
424+
425+
@testitem "consts" begin
426+
@test pybuiltins.None isa Py
427+
@test pystr(String, pybuiltins.None) == "None"
428+
end
429+
430+
@testitem "str" begin
431+
@test pyisinstance(pystr("foo"), pybuiltins.str)
432+
@test pyeq(Bool, pystr(pystr("foo")), pystr("foo"))
433+
@test pyeq(Bool, pystr(SubString("foobarbaz", 4:6)), pystr("bar"))
434+
@test pyeq(Bool, pystr('x'), pystr("x"))
435+
@test pystr(String, pybuiltins.None) === "None"
436+
@test pystr(String, pyint(123)) === "123"
437+
@test pystr(String, pystr("foo")) === "foo"
438+
end
439+
440+
@testitem "bytes" begin
441+
@test pyisinstance(pybytes(UInt8[1,2,3]), pybuiltins.bytes)
442+
@test pyeq(Bool, pybytes(pylist([1,2,3])), pybytes(UInt8[1,2,3]))
443+
@test pyeq(Bool, pybytes(b"foo"), pystr("foo").encode("ascii"))
444+
@test pyeq(Bool, pybytes(codeunits(SubString("foobarbaz", 4:6))), pystr("bar").encode("ascii"))
445+
@test pybytes(Vector, pylist([1,2,3])) == UInt8[1,2,3]
446+
@test pybytes(Vector{UInt8}, pylist([1,2,3])) == UInt8[1,2,3]
447+
@test pybytes(Base.CodeUnits, pystr("foo").encode("ascii")) == b"foo"
448+
@test pybytes(Base.CodeUnits{UInt8,String}, pystr("bar").encode("ascii")) == b"bar"
449+
end
450+
451+
@testitem "tuple" begin
452+
z = pytuple()
453+
@test pyisinstance(z, pybuiltins.tuple)
454+
@test pylen(z) == 0
455+
x = pytuple((1,2,3))
456+
@test pyisinstance(x, pybuiltins.tuple)
457+
@test pylen(x) == 3
458+
@test pyeq(Bool, pygetitem(x, 0), 1)
459+
@test pyeq(Bool, pygetitem(x, 1), 2)
460+
@test pyeq(Bool, pygetitem(x, 2), 3)
461+
@test pyeq(Bool, pytuple([1,2,3]), x)
462+
@test pyeq(Bool, pytuple(i+1 for i in 0:10 if i<3), x)
463+
@test pyeq(Bool, pytuple(pytuple((1,2,3))), x)
464+
@test pyeq(Bool, pytuple(pylist([1,2,3])), x)
465+
end
466+
467+
@testitem "list" begin
468+
z = pylist()
469+
@test pyisinstance(z, pybuiltins.list)
470+
@test pylen(z) == 0
471+
x = pylist((1,2,3))
472+
@test pyisinstance(x, pybuiltins.list)
473+
@test pylen(x) == 3
474+
@test pyeq(Bool, pygetitem(x, 0), 1)
475+
@test pyeq(Bool, pygetitem(x, 1), 2)
476+
@test pyeq(Bool, pygetitem(x, 2), 3)
477+
@test pyeq(Bool, pylist([1,2,3]), x)
478+
@test pyeq(Bool, pylist(i+1 for i in 0:10 if i<3), x)
479+
@test pyeq(Bool, pylist(pylist((1,2,3))), x)
480+
@test pyeq(Bool, pylist(pytuple([1,2,3])), x)
481+
@test pyeq(Bool, pycollist([1,2,3]), pylist([1,2,3]))
482+
@test pyeq(Bool, pycollist([1 2; 3 4]), pylist((pylist([1,3]), pylist([2,4]))))
483+
@test pyeq(Bool, pyrowlist([1,2,3]), pylist([1,2,3]))
484+
@test pyeq(Bool, pyrowlist([1 2; 3 4]), pylist((pylist([1,2]), pylist([3,4]))))
485+
end
486+
487+
@testitem "dict" begin
488+
z = pydict()
489+
@test pyisinstance(z, pybuiltins.dict)
490+
@test pylen(z) == 0
491+
x = pydict(foo=1, bar=2)
492+
@test pyisinstance(x, pybuiltins.dict)
493+
@test pylen(x) == 2
494+
@test pyeq(Bool, pygetitem(x, "foo"), 1)
495+
@test pyeq(Bool, pygetitem(x, "bar"), 2)
496+
@test pyeq(Bool, pydict(["foo"=>1, "bar"=>2]), x)
497+
@test pyeq(Bool, pydict([("foo"=>1), ("bar"=>2)]), x)
498+
@test pyeq(Bool, pydict(Dict("foo"=>1, "bar"=>2)), x)
499+
@test pyeq(Bool, pydict((foo=1, bar=2)), x)
500+
@test pyeq(Bool, pydict(x), x)
501+
end
502+
503+
@testitem "bool" begin
504+
@test pyis(pybool(), pybuiltins.False)
505+
@test pyis(pybool(false), pybuiltins.False)
506+
@test pyis(pybool(true), pybuiltins.True)
507+
@test pyis(pybool(0.0), pybuiltins.False)
508+
@test pyis(pybool(-1.2), pybuiltins.True)
509+
@test pyis(pybool(pybuiltins.None), pybuiltins.False)
510+
@test pyis(pybool(pylist()), pybuiltins.False)
511+
@test pyis(pybool(pylist([1,2,3])), pybuiltins.True)
512+
end
513+
514+
@testitem "int" begin
515+
@test pyisinstance(pyint(), pybuiltins.int)
516+
@test pystr(String, pyint()) == "0"
517+
x = 123
518+
y = pyint(x)
519+
@test pyisinstance(y, pybuiltins.int)
520+
@test pystr(String, y) == string(x)
521+
x = BigInt(123) << 200
522+
y = pyint(x)
523+
@test pyisinstance(y, pybuiltins.int)
524+
@test pystr(String, y) == string(x)
525+
x = UInt(123)
526+
y = pyint(x)
527+
@test pyisinstance(y, pybuiltins.int)
528+
@test pystr(String, y) == string(x)
529+
x = UInt128(123) << 100
530+
y = pyint(x)
531+
@test pyisinstance(y, pybuiltins.int)
532+
@test pystr(String, y) == string(x)
533+
@test pyeq(Bool, pyint(pyint(123)), pyint(123))
534+
@test pyeq(Bool, pyint(pyfloat(12.3)), pyint(12))
535+
end
536+
537+
@testitem "float" begin
538+
y = pyfloat()
539+
@test pyisinstance(y, pybuiltins.float)
540+
@test pyeq(Bool, y, pyint(0))
541+
x = 123
542+
y = pyfloat(x)
543+
@test pyisinstance(y, pybuiltins.float)
544+
@test pyeq(Bool, y, pyint(x))
545+
x = 0.25
546+
y = pyfloat(x)
547+
@test pyisinstance(y, pybuiltins.float)
548+
@test pyeq(Bool, y, pytruediv(1, 4))
549+
x = 1//4
550+
y = pyfloat(x)
551+
@test pyisinstance(y, pybuiltins.float)
552+
@test pyeq(Bool, y, pyfloat(float(x)))
553+
@test pyeq(Bool, pyfloat(pyfloat(12.3)), pyfloat(12.3))
554+
@test pyeq(Bool, pyfloat(pyint(123)), pyfloat(123))
555+
end
556+
557+
@testitem "complex" begin
558+
y = pycomplex()
559+
@test pyisinstance(y, pybuiltins.complex)
560+
@test pyeq(Bool, y, pyint(0))
561+
x = 12.3
562+
y = pycomplex(x)
563+
@test pyisinstance(y, pybuiltins.complex)
564+
@test pyeq(Bool, y, pyfloat(x))
565+
xr, xi = 12, 34
566+
y = pycomplex(xr, xi)
567+
@test pyisinstance(y, pybuiltins.complex)
568+
@test pyeq(Bool, y.real, pyfloat(xr))
569+
@test pyeq(Bool, y.imag, pyfloat(xi))
570+
x = Complex(12, 34)
571+
y = pycomplex(x)
572+
@test pyisinstance(y, pybuiltins.complex)
573+
@test pyeq(Bool, y.real, pyfloat(real(x)))
574+
@test pyeq(Bool, y.imag, pyfloat(imag(x)))
575+
@test pyeq(Bool, pycomplex(y), y)
576+
@test pyeq(Bool, pycomplex(pyint(12), pyint(34)), y)
577+
end
578+
579+
@testitem "set" begin
580+
y = pyset()
581+
yf = pyfrozenset()
582+
@test pyisinstance(y, pybuiltins.set)
583+
@test pylen(y) == 0
584+
@test pyisinstance(yf, pybuiltins.frozenset)
585+
@test pylen(yf) == 0
586+
@test pyeq(Bool, y, yf)
587+
x = [1,2,3,2,1]
588+
y = pyset(x)
589+
yf = pyfrozenset(x)
590+
@test pyisinstance(y, pybuiltins.set)
591+
@test pylen(y) == 3
592+
@test pycontains(y, 1)
593+
@test pycontains(y, 2)
594+
@test pycontains(y, 3)
595+
@test pyeq(Bool, pyset(y), y)
596+
@test pyisinstance(yf, pybuiltins.frozenset)
597+
@test pylen(yf) == 3
598+
@test pycontains(yf, 1)
599+
@test pycontains(yf, 2)
600+
@test pycontains(yf, 3)
601+
@test pyeq(Bool, pyfrozenset(y), y)
602+
@test pyeq(Bool, y, yf)
603+
end
604+
605+
@testitem "slice" begin
606+
x = pyslice(12)
607+
@test pyisinstance(x, pybuiltins.slice)
608+
@test pyeq(Bool, x.start, pybuiltins.None)
609+
@test pyeq(Bool, x.stop, 12)
610+
@test pyeq(Bool, x.step, pybuiltins.None)
611+
x = pyslice(12, 34)
612+
@test pyisinstance(x, pybuiltins.slice)
613+
@test pyeq(Bool, x.start, 12)
614+
@test pyeq(Bool, x.stop, 34)
615+
@test pyeq(Bool, x.step, pybuiltins.None)
616+
x = pyslice(12, 34, 56)
617+
@test pyisinstance(x, pybuiltins.slice)
618+
@test pyeq(Bool, x.start, 12)
619+
@test pyeq(Bool, x.stop, 34)
620+
@test pyeq(Bool, x.step, 56)
621+
end
622+
623+
@testitem "range" begin
624+
x = pyrange(123)
625+
@test pyisinstance(x, pybuiltins.range)
626+
@test pyeq(Bool, x.start, 0)
627+
@test pyeq(Bool, x.stop, 123)
628+
@test pyeq(Bool, x.step, 1)
629+
x = pyrange(12, 123)
630+
@test pyisinstance(x, pybuiltins.range)
631+
@test pyeq(Bool, x.start, 12)
632+
@test pyeq(Bool, x.stop, 123)
633+
@test pyeq(Bool, x.step, 1)
634+
x = pyrange(12, 123, 3)
635+
@test pyisinstance(x, pybuiltins.range)
636+
@test pyeq(Bool, x.start, 12)
637+
@test pyeq(Bool, x.stop, 123)
638+
@test pyeq(Bool, x.step, 3)
639+
end
640+
641+
@testitem "none" begin
642+
# TODO
643+
end
644+
645+
@testitem "type" begin
646+
x = pytype(pyint())
647+
@test pyisinstance(x, pybuiltins.type)
648+
@test pyis(x, pybuiltins.int)
649+
x = pytype(pybuiltins.type)
650+
@test pyisinstance(x, pybuiltins.type)
651+
@test pyis(x, pybuiltins.type)
652+
x = pytype("Foo", (), ["foo"=>1, "bar"=>2])
653+
@test pyisinstance(x, pybuiltins.type)
654+
@test pyeq(Bool, x.__name__, "Foo")
655+
@test pyeq(Bool, x.foo, 1)
656+
@test pyeq(Bool, x.bar, 2)
657+
end
658+
659+
@testitem "fraction" begin
660+
# TODO
661+
end
662+
663+
@testitem "method" begin
664+
# TODO
665+
end
666+
667+
@testitem "datetime" begin
668+
using Dates
669+
dt = pyimport("datetime")
670+
x1 = pydate(2001, 2, 3)
671+
@test pyisinstance(x1, dt.date)
672+
@test pyeq(Bool, x1, dt.date(2001, 2, 3))
673+
x2 = pydate(Date(2002, 3, 4))
674+
@test pyisinstance(x2, dt.date)
675+
@test pyeq(Bool, x2, dt.date(2002, 3, 4))
676+
x3 = pytime(12, 3, 4, 5)
677+
@test pyisinstance(x3, dt.time)
678+
@test pyeq(Bool, x3, dt.time(12, 3, 4, 5))
679+
x4 = pytime(Time(23, 4, 5, 0, 6))
680+
@test pyisinstance(x4, dt.time)
681+
@test pyeq(Bool, x4, dt.time(23, 4, 5, 6))
682+
x5 = pydatetime(2001, 2, 3, 4, 5, 6, 7)
683+
@test pyisinstance(x5, dt.datetime)
684+
@test pyeq(Bool, x5, dt.datetime(2001, 2, 3, 4, 5, 6, 7))
685+
x6 = pydatetime(Date(2007, 8, 9))
686+
@test pyisinstance(x6, dt.datetime)
687+
@test pyeq(Bool, x6, dt.datetime(2007, 8, 9))
688+
x7 = pydatetime(DateTime(2001, 2, 3, 4, 5, 6, 7))
689+
@test pyisinstance(x7, dt.datetime)
690+
@test pyeq(Bool, x7, dt.datetime(2001, 2, 3, 4, 5, 6, 7000))
691+
end
692+
693+
@testitem "code" begin
694+
# check for ArgumentError when inputs are mixed up
695+
@test_throws ArgumentError pyeval(Main, "1+1")
696+
@test_throws ArgumentError pyeval(Main, Main)
697+
@test_throws ArgumentError pyeval("1+1", "1+1")
698+
@test_throws ArgumentError pyexec(Main, "1+1")
699+
@test_throws ArgumentError pyexec(Main, Main)
700+
@test_throws ArgumentError pyexec("1+1", "1+1")
701+
# basic code execution
702+
m = Module(:test)
703+
g = pydict()
704+
@test pyeq(Bool, pyeval("1+1", m), 2)
705+
@test pyeq(Bool, pyeval("1+1", g), 2)
706+
@test pyeq(Bool, pyeval(pystr("1+1"), g), 2)
707+
@test pyexec("1+1", m) === nothing
708+
@test pyexec("1+1", g) === nothing
709+
@test pyexec(pystr("1+1"), g) === nothing
710+
# check the globals are what we think they are
711+
@test pyis(pyeval("globals()", g), g)
712+
mg = pyeval("globals()", m)
713+
@test pyisinstance(mg, pybuiltins.dict)
714+
# these automatically gain 1 item, __builtins__
715+
@test length(g) == 1
716+
@test length(mg) == 1
717+
@test pycontains(g, "__builtins__")
718+
@test pycontains(mg, "__builtins__")
719+
# code should fail when x does not exist
720+
@test_throws PyException pyeval("x+1", g)
721+
@test_throws PyException pyeval("x+1", g)
722+
# now set x and try again
723+
g["x"] = 1
724+
@test pyeq(Bool, pyeval("x+1", g), 2)
725+
# set x using pyexec this time
726+
pyexec("x=2", g)
727+
@test pyeq(Bool, g["x"], 2)
728+
@test pyeq(Bool, pyeval("x+1", g), 3)
729+
# now use locals
730+
# check empty locals have no effect
731+
l = pydict()
732+
@test pyeq(Bool, pyeval("x+1", g, l), 3)
733+
@test pyeq(Bool, pyeval("x+1", g, Dict()), 3)
734+
# now set x locally
735+
l["x"] = 3
736+
@test pyeq(Bool, pyeval("x+1", g, l), 4)
737+
@test pyeq(Bool, pyeval("x+1", g, Dict()), 3)
738+
@test pyeq(Bool, pyeval("x+1", g, Dict("x" => 0)), 1)
739+
@test pyeq(Bool, pyeval("x+1", g, (x=1,)), 2)
740+
# check pyexec runs in local scope
741+
pyexec("x=4", g, l)
742+
@test pyeq(Bool, g["x"], 2)
743+
@test pyeq(Bool, l["x"], 4)
744+
# check global code runs in global scope
745+
pyexec("global y; y=x+1", g, l)
746+
@test pyeq(Bool, g["y"], 5)
747+
@test !pycontains(l, "y")
748+
# check pyeval converts types correctly
749+
@test pyeval(Int, "1+1", g) === 2
750+
@test pyeval(Nothing, "None", g) === nothing
751+
end
752+
753+
@testitem "@pyconst" begin
754+
f() = @pyconst "hello"
755+
g() = @pyconst "hello"
756+
@test f() === f()
757+
@test f() === f()
758+
@test g() === g()
759+
@test g() !== f()
760+
@test f() isa Py
761+
@test pyeq(Bool, f(), "hello")
762+
end
763+
764+
@testitem "Base.jl" begin
765+
@testset "broadcast" begin
766+
# Py always broadcasts as a scalar
767+
x = [1 2; 3 4] .+ Py(1)
768+
@test isequal(x, [Py(2) Py(3); Py(4) Py(5)])
769+
x = Py("foo") .* [1 2; 3 4]
770+
@test isequal(x, [Py("foo") Py("foofoo"); Py("foofoofoo") Py("foofoofoofoo")])
771+
# this previously treated the list as a shape (2,) object
772+
# but now tries to do `1 + [1, 2]` which properly fails
773+
@test_throws PyException [1 2; 3 4] .+ pylist([1, 2])
774+
end
775+
end
776+
777+
@testitem "pywith" begin
778+
@testset "no error" begin
779+
tdir = pyimport("tempfile").TemporaryDirectory()
780+
tname = pyconvert(String, tdir.name)
781+
@test isdir(tname)
782+
pywith(tdir) do name
783+
@test pyconvert(String, name) == tname
784+
end
785+
@test !isdir(tname)
786+
end
787+
@testset "error" begin
788+
tdir = pyimport("tempfile").TemporaryDirectory()
789+
tname = pyconvert(String, tdir.name)
790+
@test isdir(tname)
791+
@test_throws PyException pywith(name -> name.invalid_attr, tdir)
792+
@test !isdir(tname)
793+
end
794+
end

0 commit comments

Comments
 (0)