From 524cd400193562bcd2eb82df858e33dd5925bbe7 Mon Sep 17 00:00:00 2001 From: Juan Mauricio Matera Date: Sat, 12 Aug 2023 08:02:43 -0300 Subject: [PATCH] Moving private doctests to pytest for assignment and image (#901) Just another round Co-authored-by: R. Bernstein --- mathics/builtin/assignments/assignment.py | 14 -- mathics/builtin/assignments/clear.py | 29 ---- mathics/builtin/image/base.py | 6 - mathics/builtin/image/basic.py | 13 -- mathics/builtin/image/composition.py | 24 --- mathics/builtin/image/geometric.py | 19 --- mathics/builtin/image/misc.py | 12 -- mathics/builtin/image/pixel.py | 15 -- mathics/builtin/image/properties.py | 4 - test/builtin/image/test_image.py | 198 ++++++++++++++++++++++ test/builtin/test_assignment.py | 37 ++++ 11 files changed, 235 insertions(+), 136 deletions(-) create mode 100644 test/builtin/image/test_image.py diff --git a/mathics/builtin/assignments/assignment.py b/mathics/builtin/assignments/assignment.py index 0c145feca..29d7b0730 100644 --- a/mathics/builtin/assignments/assignment.py +++ b/mathics/builtin/assignments/assignment.py @@ -158,8 +158,6 @@ class Set(BinaryOperator, _SetOperator): >> B[[1;;2, 2;;-1]] = {{t, u}, {y, z}}; >> B = {{1, t, u}, {4, y, z}, {7, 8, 9}} - - #> x = Infinity; """ attributes = A_HOLD_FIRST | A_PROTECTED | A_SEQUENCE_HOLD @@ -371,12 +369,6 @@ class UpSet(BinaryOperator, _SetOperator): = custom >> UpValues[r] = {} - - #> f[g, a + b, h] ^= 2 - : Tag Plus in f[g, a + b, h] is Protected. - = 2 - #> UpValues[h] - = {HoldPattern[f[g, a + b, h]] :> 2} """ attributes = A_HOLD_FIRST | A_PROTECTED | A_SEQUENCE_HOLD @@ -413,12 +405,6 @@ class UpSetDelayed(UpSet): = 2 >> UpValues[b] = {HoldPattern[a[b]] :> x} - - #> f[g, a + b, h] ^:= 2 - : Tag Plus in f[g, a + b, h] is Protected. - #> f[a+b] ^:= 2 - : Tag Plus in f[a + b] is Protected. - = $Failed """ attributes = A_HOLD_ALL | A_PROTECTED | A_SEQUENCE_HOLD diff --git a/mathics/builtin/assignments/clear.py b/mathics/builtin/assignments/clear.py index f69fc034c..7ef50cb15 100644 --- a/mathics/builtin/assignments/clear.py +++ b/mathics/builtin/assignments/clear.py @@ -245,35 +245,6 @@ class Unset(PostfixOperator): >> a = b = 3; >> {a, {b}} =. = {Null, {Null}} - - #> x = 2; - #> OwnValues[x] =. - #> x - = x - #> f[a][b] = 3; - #> SubValues[f] =. - #> f[a][b] - = f[a][b] - #> PrimeQ[p] ^= True - = True - #> PrimeQ[p] - = True - #> UpValues[p] =. - #> PrimeQ[p] - = False - - #> a + b ^= 5; - #> a =. - #> a + b - = 5 - #> {UpValues[a], UpValues[b]} =. - = {Null, Null} - #> a + b - = a + b - - #> Unset[Messages[1]] - : First argument in Messages[1] is not a symbol or a string naming a symbol. - = $Failed """ attributes = A_HOLD_FIRST | A_LISTABLE | A_PROTECTED | A_READ_PROTECTED diff --git a/mathics/builtin/image/base.py b/mathics/builtin/image/base.py index 4fbafbb5d..7cc50b52a 100644 --- a/mathics/builtin/image/base.py +++ b/mathics/builtin/image/base.py @@ -223,12 +223,6 @@ class ImageAtom(AtomBuiltin):
produces the internal representation of an image from an array \ of values for the pixels. - - #> Image[{{{1,1,0},{0,1,1}}, {{1,0,1},{1,1,0}}}] - = -Image- - - #> Image[{{{0,0,0,0.25},{0,0,0,0.5}}, {{0,0,0,0.5},{0,0,0,0.75}}}] - = -Image- """ summary_text = "get internal representation of an image" diff --git a/mathics/builtin/image/basic.py b/mathics/builtin/image/basic.py index fe59024da..bf283591e 100644 --- a/mathics/builtin/image/basic.py +++ b/mathics/builtin/image/basic.py @@ -193,19 +193,6 @@ class ImagePartition(Builtin): >> ImagePartition[hedy, {512, 128}] = {{-Image-}, {-Image-}, {-Image-}, {-Image-}, {-Image-}, {-Image-}} - - #> ImagePartition[hedy, 257] - = {{-Image-, -Image-}, {-Image-, -Image-}, {-Image-, -Image-}} - #> ImagePartition[hedy, 646] - = {{-Image-}} - #> ImagePartition[hedy, 647] - = {} - #> ImagePartition[hedy, {256, 300}] - = {{-Image-, -Image-}, {-Image-, -Image-}} - - #> ImagePartition[hedy, {0, 300}] - : {0, 300} is not a valid size specification for image partitions. - = ImagePartition[-Image-, {0, 300}] """ messages = {"arg2": "`1` is not a valid size specification for image partitions."} diff --git a/mathics/builtin/image/composition.py b/mathics/builtin/image/composition.py index 66cee1f47..220e8d67a 100644 --- a/mathics/builtin/image/composition.py +++ b/mathics/builtin/image/composition.py @@ -79,13 +79,6 @@ class ImageAdd(_ImageArithmetic): >> ImageAdd[i, i] = -Image- - #> ImageAdd[i, 0.2, i, 0.1] - = -Image- - - #> ImageAdd[i, x] - : Expecting a number, image, or graphics instead of x. - = ImageAdd[-Image-, x] - >> ein = Import["ExampleData/Einstein.jpg"]; >> noise = RandomImage[{-0.1, 0.1}, ImageDimensions[ein]]; >> ImageAdd[noise, ein] @@ -117,16 +110,6 @@ class ImageMultiply(_ImageArithmetic): >> ImageMultiply[i, i] = -Image- - #> ImageMultiply[i, 0.2, i, 0.1] - = -Image- - - #> ImageMultiply[i, x] - : Expecting a number, image, or graphics instead of x. - = ImageMultiply[-Image-, x] - - S> ein = Import["ExampleData/Einstein.jpg"]; - S> noise = RandomImage[{0.7, 1.3}, ImageDimensions[ein]]; - S> ImageMultiply[noise, ein] = -Image- """ @@ -151,13 +134,6 @@ class ImageSubtract(_ImageArithmetic): >> ImageSubtract[i, i] = -Image- - - #> ImageSubtract[i, 0.2, i, 0.1] - = -Image- - - #> ImageSubtract[i, x] - : Expecting a number, image, or graphics instead of x. - = ImageSubtract[-Image-, x] """ summary_text = "build an image substracting pixel values of another image " diff --git a/mathics/builtin/image/geometric.py b/mathics/builtin/image/geometric.py index afaa51abf..6f96b306c 100644 --- a/mathics/builtin/image/geometric.py +++ b/mathics/builtin/image/geometric.py @@ -156,21 +156,6 @@ class ImageReflect(Builtin): = -Image- >> ImageReflect[ein, Left -> Top] = -Image- - - #> ein == ImageReflect[ein, Left -> Left] == ImageReflect[ein, Right -> Right] == ImageReflect[ein, Top -> Top] == ImageReflect[ein, Bottom -> Bottom] - = True - #> ImageReflect[ein, Left -> Right] == ImageReflect[ein, Right -> Left] == ImageReflect[ein, Left] == ImageReflect[ein, Right] - = True - #> ImageReflect[ein, Bottom -> Top] == ImageReflect[ein, Top -> Bottom] == ImageReflect[ein, Top] == ImageReflect[ein, Bottom] - = True - #> ImageReflect[ein, Left -> Top] == ImageReflect[ein, Right -> Bottom] (* Transpose *) - = True - #> ImageReflect[ein, Left -> Bottom] == ImageReflect[ein, Right -> Top] (* Anti-Transpose *) - = True - - #> ImageReflect[ein, x -> Top] - : x -> Top is not a valid 2D reflection specification. - = ImageReflect[-Image-, x -> Top] """ summary_text = "reflect an image" @@ -239,10 +224,6 @@ class ImageRotate(Builtin): >> ImageRotate[ein, Pi / 4] = -Image- - - #> ImageRotate[ein, ein] - : Angle -Image- should be a real number, one of Top, Bottom, Left, Right, or a rule from one to another. - = ImageRotate[-Image-, -Image-] """ messages = { diff --git a/mathics/builtin/image/misc.py b/mathics/builtin/image/misc.py index 89256f919..8437ab920 100644 --- a/mathics/builtin/image/misc.py +++ b/mathics/builtin/image/misc.py @@ -119,18 +119,6 @@ class RandomImage(Builtin): >> RandomImage[1, {100, 100}] = -Image- - - #> RandomImage[0.5] - = -Image- - #> RandomImage[{0.1, 0.9}] - = -Image- - #> RandomImage[0.9, {400, 600}] - = -Image- - #> RandomImage[{0.1, 0.5}, {400, 600}] - = -Image- - - #> RandomImage[{0.1, 0.5}, {400, 600}, ColorSpace -> "RGB"] - = -Image- """ options = {"ColorSpace": "Automatic"} diff --git a/mathics/builtin/image/pixel.py b/mathics/builtin/image/pixel.py index ebd519daa..e4b114b4c 100644 --- a/mathics/builtin/image/pixel.py +++ b/mathics/builtin/image/pixel.py @@ -26,21 +26,6 @@ class PixelValue(Builtin): >> hedy = Import["ExampleData/hedy.tif"]; >> PixelValue[hedy, {1, 1}] = {0.439216, 0.356863, 0.337255} - #> {82 / 255, 22 / 255, 57 / 255} // N (* pixel byte values from bottom left corner *) - = {0.321569, 0.0862745, 0.223529} - - #> PixelValue[hedy, {0, 1}]; - : Padding not implemented for PixelValue. - #> PixelValue[hedy, {512, 1}] - = {0.0509804, 0.0509804, 0.0588235} - #> PixelValue[hedy, {647, 1}]; - : Padding not implemented for PixelValue. - #> PixelValue[hedy, {1, 0}]; - : Padding not implemented for PixelValue. - #> PixelValue[hedy, {1, 512}] - = {0.286275, 0.4, 0.423529} - #> PixelValue[hedy, {1, 801}]; - : Padding not implemented for PixelValue. """ messages = {"nopad": "Padding not implemented for PixelValue."} diff --git a/mathics/builtin/image/properties.py b/mathics/builtin/image/properties.py index 38ffc4dbb..50313a205 100644 --- a/mathics/builtin/image/properties.py +++ b/mathics/builtin/image/properties.py @@ -93,10 +93,6 @@ class ImageData(Builtin): >> ImageData[Image[{{0, 1}, {1, 0}, {1, 1}}], "Bit"] = {{0, 1}, {1, 0}, {1, 1}} - - #> ImageData[img, "Bytf"] - : Unsupported pixel format "Bytf". - = ImageData[-Image-, Bytf] """ messages = {"pixelfmt": 'Unsupported pixel format "``".'} diff --git a/test/builtin/image/test_image.py b/test/builtin/image/test_image.py new file mode 100644 index 000000000..fb79fe470 --- /dev/null +++ b/test/builtin/image/test_image.py @@ -0,0 +1,198 @@ +# -*- coding: utf-8 -*- +""" +Unit tests for mathics.builtins.image.colors + +Largely tests error messages when parameters are incorrect. +""" +from test.helper import check_evaluation, session + +import pytest + + +@pytest.mark.parametrize( + ("str_expr", "str_expected", "msgs", "assert_failure_msg"), + [ + (None, None, None, None), + # + # Base Image Atom + # + ( + "Image[{{{1,1,0},{0,1,1}}, {{1,0,1},{1,1,0}}}]", + "-Image-", + None, + "Image Atom B&W", + ), + ( + "Image[{{{0,0,0,0.25},{0,0,0,0.5}}, {{0,0,0,0.5},{0,0,0,0.75}}}]", + "-Image-", + None, + "Image Atom RGB", + ), + # + # Operations over images + # + ('hedy = Import["ExampleData/hedy.tif"];', "Null", None, "Load an image"), + ( + 'ImageData[hedy, "Bytf"]', + "ImageData[-Image-, Bytf]", + ('Unsupported pixel format "Bytf".',), + "Wrong Image Data", + ), + ( + "ImagePartition[hedy, 257]", + "{{-Image-, -Image-}, {-Image-, -Image-}, {-Image-, -Image-}}", + None, + None, + ), + ("ImagePartition[hedy, 646]", "{{-Image-}}", None, None), + ("ImagePartition[hedy, 647]", "{}", None, None), + ( + "ImagePartition[hedy, {256, 300}]", + "{{-Image-, -Image-}, {-Image-, -Image-}}", + None, + None, + ), + ( + "ImagePartition[hedy, {0, 300}]", + "ImagePartition[-Image-, {0, 300}]", + ("{0, 300} is not a valid size specification for image partitions.",), + None, + ), + ( + "{82 / 255, 22 / 255, 57 / 255} // N", + "{0.321569, 0.0862745, 0.223529}", + None, + "pixel byte values from bottom left corner", + ), + ( + "PixelValue[hedy, {0, 1}];", + "Null", + ("Padding not implemented for PixelValue.",), + None, + ), + ("PixelValue[hedy, {512, 1}]", "{0.0509804, 0.0509804, 0.0588235}", None, None), + ( + "PixelValue[hedy, {647, 1}];", + "Null", + ("Padding not implemented for PixelValue.",), + None, + ), + ( + "PixelValue[hedy, {1, 0}];", + "Null", + ("Padding not implemented for PixelValue.",), + None, + ), + ("PixelValue[hedy, {1, 512}]", "{0.286275, 0.4, 0.423529}", None, None), + ( + "PixelValue[hedy, {1, 801}];", + "Null", + ("Padding not implemented for PixelValue.",), + None, + ), + # + # Composition + # + ( + "i = Image[{{0, 0.5, 0.2, 0.1, 0.9}, {1.0, 0.1, 0.3, 0.8, 0.6}}];", + "Null", + None, + None, + ), + ("ImageAdd[i, 0.2, i, 0.1]", "-Image-", None, None), + ( + "ImageAdd[i, x]", + "ImageAdd[-Image-, x]", + ("Expecting a number, image, or graphics instead of x.",), + None, + ), + ("ImageMultiply[i, 0.2, i, 0.1]", "-Image-", None, None), + ( + "ImageMultiply[i, x]", + "ImageMultiply[-Image-, x]", + ("Expecting a number, image, or graphics instead of x.",), + None, + ), + ( + 'ein = Import["ExampleData/Einstein.jpg"]; noise = RandomImage[{0.7, 1.3}, ImageDimensions[ein]];ImageMultiply[noise, ein]', + "-Image-", + None, + "Multiply Image by random noise", + ), + ("ImageSubtract[i, 0.2, i, 0.1]", "-Image-", None, None), + ( + "ImageSubtract[i, x]", + "ImageSubtract[-Image-, x]", + ("Expecting a number, image, or graphics instead of x.",), + None, + ), + # + # Random + # + ("RandomImage[0.5]", "-Image-", None, None), + ("RandomImage[{0.1, 0.9}]", "-Image-", None, None), + ("RandomImage[0.9, {400, 600}]", "-Image-", None, None), + ("RandomImage[{0.1, 0.5}, {400, 600}]", "-Image-", None, None), + ( + 'RandomImage[{0.1, 0.5}, {400, 600}, ColorSpace -> "RGB"]', + "-Image-", + None, + None, + ), + # + # Geometry + # + ( + "ein == ImageReflect[ein, Left -> Left] == ImageReflect[ein, Right -> Right] == ImageReflect[ein, Top -> Top] == ImageReflect[ein, Bottom -> Bottom]", + "True", + None, + None, + ), + ( + "ImageReflect[ein, Left -> Right] == ImageReflect[ein, Right -> Left] == ImageReflect[ein, Left] == ImageReflect[ein, Right]", + "True", + None, + None, + ), + ( + "ImageReflect[ein, Bottom -> Top] == ImageReflect[ein, Top -> Bottom] == ImageReflect[ein, Top] == ImageReflect[ein, Bottom]", + "True", + None, + None, + ), + ( + "ImageReflect[ein, Left -> Top] == ImageReflect[ein, Right -> Bottom]", + "True", + None, + "Transpose", + ), + ( + "ImageReflect[ein, Left -> Bottom] == ImageReflect[ein, Right -> Top]", + "True", + None, + "Anti-Transpose", + ), + ( + "ImageReflect[ein, x -> Top]", + "ImageReflect[-Image-, x -> Top]", + ("x -> Top is not a valid 2D reflection specification.",), + None, + ), + ( + "ImageRotate[ein, ein]", + "ImageRotate[-Image-, -Image-]", + ( + "Angle -Image- should be a real number, one of Top, Bottom, Left, Right, or a rule from one to another.", + ), + None, + ), + ], +) +def test_private_doctest(str_expr, str_expected, msgs, assert_failure_msg): + check_evaluation( + str_expr, + str_expected, + hold_expected=True, + expected_messages=msgs, + failure_message=assert_failure_msg, + ) diff --git a/test/builtin/test_assignment.py b/test/builtin/test_assignment.py index e9c846aac..476180249 100644 --- a/test/builtin/test_assignment.py +++ b/test/builtin/test_assignment.py @@ -413,3 +413,40 @@ def test_process_assign_other(): "Cannot set $ModuleNumber to -1; value must be a positive integer." ], ) + + +@pytest.mark.parametrize( + ("str_expr", "str_expected", "msgs", "failure_msg"), + [ + (None, None, None, None), + # From Clear + ("x = 2;OwnValues[x]=.;x", "x", None, "Erase Ownvalues"), + ("f[a][b] = 3; SubValues[f] =.;f[a][b]", "f[a][b]", None, "Erase Subvalues"), + ("PrimeQ[p] ^= True; PrimeQ[p]", "True", None, "Subvalues"), + ("UpValues[p]=.; PrimeQ[p]", "False", None, "Erase Subvalues"), + ("a + b ^= 5; a =.; a + b", "5", None, None), + ("{UpValues[a], UpValues[b]} =.; a+b", "a+b", None, None), + ( + "Unset[Messages[1]]", + "$Failed", + [ + "First argument in Messages[1] is not a symbol or a string naming a symbol." + ], + "Unset Message", + ), + # From assignent + ( + "f[g, a + b, h] ^= 2", + "2", + ("Tag Plus in f[g, a + b, h] is Protected.",), + "Upset to protected symbols fails", + ), + ("UpValues[h]", "{HoldPattern[f[g, a + b, h]] :> 2}", None, None), + (" g[a+b] ^:= 2", "$Failed", ("Tag Plus in g[a + b] is Protected.",), None), + (" g[a+b]", "g[a + b]", None, None), + ], +) +def test_private_doctests(str_expr, str_expected, msgs, failure_msg): + check_evaluation( + str_expr, str_expected, expected_messages=msgs, failure_message=failure_msg + )