Repository: ibis-project/ibis

Issue:
refactor(ir): replace enum functionality with string
It is being used only in the impala codebase.


Discussion:
@icexelloss Do you all use this type anywhere in your codebase?
I don’t think we use this

On Tue, Sep 20, 2022 at 4:56 PM Phillip Cloud ***@***.***>
wrote:

> @icexelloss <https://github.com/icexelloss> Do you all use this type
> anywhere in your codebase?
>
> —
> Reply to this email directly, view it on GitHub
> <https://github.com/ibis-project/ibis/issues/4477#issuecomment-1252902975>,
> or unsubscribe
> <https://github.com/notifications/unsubscribe-auth/AAGBXLCZLU733SRVBIWJ3B3V7IQJBANCNFSM6AAAAAAQISYMRY>
> .
> You are receiving this because you were mentioned.Message ID:
> ***@***.***>
>


Resolving patch:
diff --git a/ibis/expr/datatypes/core.py b/ibis/expr/datatypes/core.py
--- a/ibis/expr/datatypes/core.py
+++ b/ibis/expr/datatypes/core.py
@@ -752,17 +752,6 @@ def _pretty_piece(self) -> str:
         return f"<{self.value_type}>"
 
 
-@public
-class Enum(DataType):
-    """Enumeration values."""
-
-    rep_type = datatype
-    value_type = datatype
-
-    scalar = ir.EnumScalar
-    column = ir.EnumColumn
-
-
 @public
 class Map(Variadic):
     """Associative array values."""
@@ -959,6 +948,8 @@ class INET(String):
 inet = INET()
 decimal = Decimal()
 
+Enum = String
+
 public(
     null=null,
     boolean=boolean,
@@ -995,4 +986,5 @@ class INET(String):
     macaddr=macaddr,
     inet=inet,
     decimal=decimal,
+    Enum=Enum,
 )
diff --git a/ibis/expr/datatypes/value.py b/ibis/expr/datatypes/value.py
--- a/ibis/expr/datatypes/value.py
+++ b/ibis/expr/datatypes/value.py
@@ -175,8 +175,8 @@ def infer_integer(value: int, prefer_unsigned: bool = False) -> dt.Integer:
 
 
 @infer.register(enum.Enum)
-def infer_enum(value: enum.Enum) -> dt.Enum:
-    return dt.Enum(infer(value.name), infer(value.value))
+def infer_enum(_: enum.Enum) -> dt.String:
+    return dt.string
 
 
 @infer.register(bool)
diff --git a/ibis/expr/types/collections.py b/ibis/expr/types/collections.py
--- a/ibis/expr/types/collections.py
+++ b/ibis/expr/types/collections.py
@@ -3,21 +3,6 @@
 from ibis.expr.types.generic import Column, Scalar, Value
 
 
-@public
-class EnumValue(Value):
-    pass  # noqa: E701,E302
-
-
-@public
-class EnumScalar(Scalar, EnumValue):
-    pass  # noqa: E701,E302
-
-
-@public
-class EnumColumn(Column, EnumValue):
-    pass  # noqa: E701,E302
-
-
 @public
 class SetValue(Value):
     pass  # noqa: E701,E302


Test patch:
diff --git a/ibis/backends/impala/tests/snapshots/test_bucket_histogram/test_bucket_assign_labels/out.sql b/ibis/backends/impala/tests/snapshots/test_bucket_histogram/test_bucket_assign_labels/out.sql
new file mode 100644
--- /dev/null
+++ b/ibis/backends/impala/tests/snapshots/test_bucket_histogram/test_bucket_assign_labels/out.sql
@@ -0,0 +1,20 @@
+SELECT
+  CASE `tier`
+    WHEN 0 THEN 'Under 0'
+    WHEN 1 THEN '0 to 10'
+    WHEN 2 THEN '10 to 25'
+    WHEN 3 THEN '25 to 50'
+    ELSE 'error'
+  END AS `tier2`, `count`
+FROM (
+  SELECT
+    CASE
+      WHEN `f` < 0 THEN 0
+      WHEN (0 <= `f`) AND (`f` < 10) THEN 1
+      WHEN (10 <= `f`) AND (`f` < 25) THEN 2
+      WHEN (25 <= `f`) AND (`f` <= 50) THEN 3
+      ELSE CAST(NULL AS tinyint)
+    END AS `tier`, count(1) AS `count`
+  FROM alltypes
+  GROUP BY 1
+) t0
\ No newline at end of file
diff --git a/ibis/backends/impala/tests/snapshots/test_bucket_histogram/test_bucket_to_case/close_extreme_false/out.sql b/ibis/backends/impala/tests/snapshots/test_bucket_histogram/test_bucket_to_case/close_extreme_false/out.sql
new file mode 100644
--- /dev/null
+++ b/ibis/backends/impala/tests/snapshots/test_bucket_histogram/test_bucket_to_case/close_extreme_false/out.sql
@@ -0,0 +1,6 @@
+CASE
+  WHEN (0 <= `f`) AND (`f` < 10) THEN 0
+  WHEN (10 <= `f`) AND (`f` < 25) THEN 1
+  WHEN (25 <= `f`) AND (`f` < 50) THEN 2
+  ELSE CAST(NULL AS tinyint)
+END
\ No newline at end of file
diff --git a/ibis/backends/impala/tests/snapshots/test_bucket_histogram/test_bucket_to_case/close_extreme_false_closed_right/out.sql b/ibis/backends/impala/tests/snapshots/test_bucket_histogram/test_bucket_to_case/close_extreme_false_closed_right/out.sql
new file mode 100644
--- /dev/null
+++ b/ibis/backends/impala/tests/snapshots/test_bucket_histogram/test_bucket_to_case/close_extreme_false_closed_right/out.sql
@@ -0,0 +1,6 @@
+CASE
+  WHEN (0 < `f`) AND (`f` <= 10) THEN 0
+  WHEN (10 < `f`) AND (`f` <= 25) THEN 1
+  WHEN (25 < `f`) AND (`f` <= 50) THEN 2
+  ELSE CAST(NULL AS tinyint)
+END
\ No newline at end of file
diff --git a/ibis/backends/impala/tests/snapshots/test_bucket_histogram/test_bucket_to_case/close_extreme_false_include_under_include_over/out.sql b/ibis/backends/impala/tests/snapshots/test_bucket_histogram/test_bucket_to_case/close_extreme_false_include_under_include_over/out.sql
new file mode 100644
--- /dev/null
+++ b/ibis/backends/impala/tests/snapshots/test_bucket_histogram/test_bucket_to_case/close_extreme_false_include_under_include_over/out.sql
@@ -0,0 +1,8 @@
+CASE
+  WHEN `f` < 0 THEN 0
+  WHEN (0 <= `f`) AND (`f` < 10) THEN 1
+  WHEN (10 <= `f`) AND (`f` < 25) THEN 2
+  WHEN (25 <= `f`) AND (`f` < 50) THEN 3
+  WHEN 50 <= `f` THEN 4
+  ELSE CAST(NULL AS tinyint)
+END
\ No newline at end of file
diff --git a/ibis/backends/impala/tests/snapshots/test_bucket_histogram/test_bucket_to_case/closed_right/out.sql b/ibis/backends/impala/tests/snapshots/test_bucket_histogram/test_bucket_to_case/closed_right/out.sql
new file mode 100644
--- /dev/null
+++ b/ibis/backends/impala/tests/snapshots/test_bucket_histogram/test_bucket_to_case/closed_right/out.sql
@@ -0,0 +1,6 @@
+CASE
+  WHEN (0 <= `f`) AND (`f` <= 10) THEN 0
+  WHEN (10 < `f`) AND (`f` <= 25) THEN 1
+  WHEN (25 < `f`) AND (`f` <= 50) THEN 2
+  ELSE CAST(NULL AS tinyint)
+END
\ No newline at end of file
diff --git a/ibis/backends/impala/tests/snapshots/test_bucket_histogram/test_bucket_to_case/closed_right_close_extreme_false_include_under/out.sql b/ibis/backends/impala/tests/snapshots/test_bucket_histogram/test_bucket_to_case/closed_right_close_extreme_false_include_under/out.sql
new file mode 100644
--- /dev/null
+++ b/ibis/backends/impala/tests/snapshots/test_bucket_histogram/test_bucket_to_case/closed_right_close_extreme_false_include_under/out.sql
@@ -0,0 +1,7 @@
+CASE
+  WHEN `f` <= 0 THEN 0
+  WHEN (0 < `f`) AND (`f` <= 10) THEN 1
+  WHEN (10 < `f`) AND (`f` <= 25) THEN 2
+  WHEN (25 < `f`) AND (`f` <= 50) THEN 3
+  ELSE CAST(NULL AS tinyint)
+END
\ No newline at end of file
diff --git a/ibis/backends/impala/tests/snapshots/test_bucket_histogram/test_bucket_to_case/closed_right_include_over_include_under/out.sql b/ibis/backends/impala/tests/snapshots/test_bucket_histogram/test_bucket_to_case/closed_right_include_over_include_under/out.sql
new file mode 100644
--- /dev/null
+++ b/ibis/backends/impala/tests/snapshots/test_bucket_histogram/test_bucket_to_case/closed_right_include_over_include_under/out.sql
@@ -0,0 +1,5 @@
+CASE
+  WHEN `f` <= 10 THEN 0
+  WHEN 10 < `f` THEN 1
+  ELSE CAST(NULL AS tinyint)
+END
\ No newline at end of file
diff --git a/ibis/backends/impala/tests/snapshots/test_bucket_histogram/test_bucket_to_case/default/out.sql b/ibis/backends/impala/tests/snapshots/test_bucket_histogram/test_bucket_to_case/default/out.sql
new file mode 100644
--- /dev/null
+++ b/ibis/backends/impala/tests/snapshots/test_bucket_histogram/test_bucket_to_case/default/out.sql
@@ -0,0 +1,6 @@
+CASE
+  WHEN (0 <= `f`) AND (`f` < 10) THEN 0
+  WHEN (10 <= `f`) AND (`f` < 25) THEN 1
+  WHEN (25 <= `f`) AND (`f` <= 50) THEN 2
+  ELSE CAST(NULL AS tinyint)
+END
\ No newline at end of file
diff --git a/ibis/backends/impala/tests/snapshots/test_bucket_histogram/test_bucket_to_case/include_over_include_under0/out.sql b/ibis/backends/impala/tests/snapshots/test_bucket_histogram/test_bucket_to_case/include_over_include_under0/out.sql
new file mode 100644
--- /dev/null
+++ b/ibis/backends/impala/tests/snapshots/test_bucket_histogram/test_bucket_to_case/include_over_include_under0/out.sql
@@ -0,0 +1,5 @@
+CASE
+  WHEN `f` < 10 THEN 0
+  WHEN 10 <= `f` THEN 1
+  ELSE CAST(NULL AS tinyint)
+END
\ No newline at end of file
diff --git a/ibis/backends/impala/tests/snapshots/test_bucket_histogram/test_bucket_to_case/include_over_include_under1/out.sql b/ibis/backends/impala/tests/snapshots/test_bucket_histogram/test_bucket_to_case/include_over_include_under1/out.sql
new file mode 100644
--- /dev/null
+++ b/ibis/backends/impala/tests/snapshots/test_bucket_histogram/test_bucket_to_case/include_over_include_under1/out.sql
@@ -0,0 +1,5 @@
+CASE
+  WHEN `f` < 10 THEN 0
+  WHEN 10 <= `f` THEN 1
+  ELSE CAST(NULL AS tinyint)
+END
\ No newline at end of file
diff --git a/ibis/backends/impala/tests/snapshots/test_bucket_histogram/test_bucket_to_case/include_over_include_under2/out.sql b/ibis/backends/impala/tests/snapshots/test_bucket_histogram/test_bucket_to_case/include_over_include_under2/out.sql
new file mode 100644
--- /dev/null
+++ b/ibis/backends/impala/tests/snapshots/test_bucket_histogram/test_bucket_to_case/include_over_include_under2/out.sql
@@ -0,0 +1,5 @@
+CAST(CASE
+  WHEN `f` < 10 THEN 0
+  WHEN 10 <= `f` THEN 1
+  ELSE CAST(NULL AS tinyint)
+END AS double)
\ No newline at end of file
diff --git a/ibis/backends/impala/tests/snapshots/test_bucket_histogram/test_bucket_to_case/include_under/out.sql b/ibis/backends/impala/tests/snapshots/test_bucket_histogram/test_bucket_to_case/include_under/out.sql
new file mode 100644
--- /dev/null
+++ b/ibis/backends/impala/tests/snapshots/test_bucket_histogram/test_bucket_to_case/include_under/out.sql
@@ -0,0 +1,7 @@
+CASE
+  WHEN `f` < 0 THEN 0
+  WHEN (0 <= `f`) AND (`f` < 10) THEN 1
+  WHEN (10 <= `f`) AND (`f` < 25) THEN 2
+  WHEN (25 <= `f`) AND (`f` <= 50) THEN 3
+  ELSE CAST(NULL AS tinyint)
+END
\ No newline at end of file
diff --git a/ibis/backends/impala/tests/snapshots/test_bucket_histogram/test_bucket_to_case/include_under_include_over/out.sql b/ibis/backends/impala/tests/snapshots/test_bucket_histogram/test_bucket_to_case/include_under_include_over/out.sql
new file mode 100644
--- /dev/null
+++ b/ibis/backends/impala/tests/snapshots/test_bucket_histogram/test_bucket_to_case/include_under_include_over/out.sql
@@ -0,0 +1,8 @@
+CASE
+  WHEN `f` < 0 THEN 0
+  WHEN (0 <= `f`) AND (`f` < 10) THEN 1
+  WHEN (10 <= `f`) AND (`f` < 25) THEN 2
+  WHEN (25 <= `f`) AND (`f` <= 50) THEN 3
+  WHEN 50 < `f` THEN 4
+  ELSE CAST(NULL AS tinyint)
+END
\ No newline at end of file
diff --git a/ibis/backends/impala/tests/test_bucket_histogram.py b/ibis/backends/impala/tests/test_bucket_histogram.py
--- a/ibis/backends/impala/tests/test_bucket_histogram.py
+++ b/ibis/backends/impala/tests/test_bucket_histogram.py
@@ -13,139 +13,44 @@ def table(mockcon):
 
 
 @pytest.mark.parametrize(
-    ("expr_fn", "expected"),
+    "expr_fn",
     [
+        pytest.param(lambda f: f.bucket(BUCKETS), id="default"),
         pytest.param(
-            lambda f: f.bucket(BUCKETS),
-            """\
-CASE
-  WHEN (0 <= `f`) AND (`f` < 10) THEN 0
-  WHEN (10 <= `f`) AND (`f` < 25) THEN 1
-  WHEN (25 <= `f`) AND (`f` <= 50) THEN 2
-  ELSE CAST(NULL AS tinyint)
-END""",
-            id="default",
-        ),
-        pytest.param(
-            lambda f: f.bucket(BUCKETS, close_extreme=False),
-            """\
-CASE
-  WHEN (0 <= `f`) AND (`f` < 10) THEN 0
-  WHEN (10 <= `f`) AND (`f` < 25) THEN 1
-  WHEN (25 <= `f`) AND (`f` < 50) THEN 2
-  ELSE CAST(NULL AS tinyint)
-END""",
-            id="close_extreme_false",
-        ),
-        pytest.param(
-            lambda f: f.bucket(BUCKETS, closed="right"),
-            """\
-CASE
-  WHEN (0 <= `f`) AND (`f` <= 10) THEN 0
-  WHEN (10 < `f`) AND (`f` <= 25) THEN 1
-  WHEN (25 < `f`) AND (`f` <= 50) THEN 2
-  ELSE CAST(NULL AS tinyint)
-END""",
-            id="closed_right",
+            lambda f: f.bucket(BUCKETS, close_extreme=False), id="close_extreme_false"
         ),
+        pytest.param(lambda f: f.bucket(BUCKETS, closed="right"), id="closed_right"),
         pytest.param(
             lambda f: f.bucket(BUCKETS, closed="right", close_extreme=False),
-            """\
-CASE
-  WHEN (0 < `f`) AND (`f` <= 10) THEN 0
-  WHEN (10 < `f`) AND (`f` <= 25) THEN 1
-  WHEN (25 < `f`) AND (`f` <= 50) THEN 2
-  ELSE CAST(NULL AS tinyint)
-END""",
             id="close_extreme_false_closed_right",
         ),
         pytest.param(
-            lambda f: f.bucket(BUCKETS, include_under=True),
-            """\
-CASE
-  WHEN `f` < 0 THEN 0
-  WHEN (0 <= `f`) AND (`f` < 10) THEN 1
-  WHEN (10 <= `f`) AND (`f` < 25) THEN 2
-  WHEN (25 <= `f`) AND (`f` <= 50) THEN 3
-  ELSE CAST(NULL AS tinyint)
-END""",
-            id="include_under",
+            lambda f: f.bucket(BUCKETS, include_under=True), id="include_under"
         ),
         pytest.param(
             lambda f: f.bucket(BUCKETS, include_under=True, include_over=True),
-            """\
-CASE
-  WHEN `f` < 0 THEN 0
-  WHEN (0 <= `f`) AND (`f` < 10) THEN 1
-  WHEN (10 <= `f`) AND (`f` < 25) THEN 2
-  WHEN (25 <= `f`) AND (`f` <= 50) THEN 3
-  WHEN 50 < `f` THEN 4
-  ELSE CAST(NULL AS tinyint)
-END""",
             id="include_under_include_over",
         ),
         pytest.param(
             lambda f: f.bucket(
-                BUCKETS,
-                close_extreme=False,
-                include_under=True,
-                include_over=True,
+                BUCKETS, close_extreme=False, include_under=True, include_over=True
             ),
-            """\
-CASE
-  WHEN `f` < 0 THEN 0
-  WHEN (0 <= `f`) AND (`f` < 10) THEN 1
-  WHEN (10 <= `f`) AND (`f` < 25) THEN 2
-  WHEN (25 <= `f`) AND (`f` < 50) THEN 3
-  WHEN 50 <= `f` THEN 4
-  ELSE CAST(NULL AS tinyint)
-END""",
             id="close_extreme_false_include_under_include_over",
         ),
         pytest.param(
             lambda f: f.bucket(
-                BUCKETS,
-                closed="right",
-                close_extreme=False,
-                include_under=True,
+                BUCKETS, closed="right", close_extreme=False, include_under=True
             ),
-            """\
-CASE
-  WHEN `f` <= 0 THEN 0
-  WHEN (0 < `f`) AND (`f` <= 10) THEN 1
-  WHEN (10 < `f`) AND (`f` <= 25) THEN 2
-  WHEN (25 < `f`) AND (`f` <= 50) THEN 3
-  ELSE CAST(NULL AS tinyint)
-END""",
             id="closed_right_close_extreme_false_include_under",
         ),
         pytest.param(
             lambda f: f.bucket(
-                [10],
-                closed="right",
-                include_over=True,
-                include_under=True,
+                [10], closed="right", include_over=True, include_under=True
             ),
-            """\
-CASE
-  WHEN `f` <= 10 THEN 0
-  WHEN 10 < `f` THEN 1
-  ELSE CAST(NULL AS tinyint)
-END""",
             id="closed_right_include_over_include_under",
         ),
         pytest.param(
-            lambda f: f.bucket(
-                [10],
-                include_over=True,
-                include_under=True,
-            ),
-            """\
-CASE
-  WHEN `f` < 10 THEN 0
-  WHEN 10 <= `f` THEN 1
-  ELSE CAST(NULL AS tinyint)
-END""",
+            lambda f: f.bucket([10], include_over=True, include_under=True),
             id="include_over_include_under",
         ),
         # Because the bucket result is an integer, no explicit cast is
@@ -154,35 +59,23 @@ def table(mockcon):
             lambda f: f.bucket([10], include_over=True, include_under=True).cast(
                 'int32'
             ),
-            """\
-CASE
-  WHEN `f` < 10 THEN 0
-  WHEN 10 <= `f` THEN 1
-  ELSE CAST(NULL AS tinyint)
-END""",
             id="include_over_include_under",
         ),
         pytest.param(
             lambda f: f.bucket([10], include_over=True, include_under=True).cast(
                 'double'
             ),
-            """\
-CAST(CASE
-  WHEN `f` < 10 THEN 0
-  WHEN 10 <= `f` THEN 1
-  ELSE CAST(NULL AS tinyint)
-END AS double)""",
             id="include_over_include_under",
         ),
     ],
 )
-def test_bucket_to_case(table, expr_fn, expected):
+def test_bucket_to_case(table, expr_fn, snapshot):
     expr = expr_fn(table.f)
     result = translate(expr)
-    assert result == expected
+    snapshot.assert_match(result, "out.sql")
 
 
-def test_bucket_assign_labels(table):
+def test_bucket_assign_labels(table, snapshot):
     buckets = [0, 10, 25, 50]
     bucket = table.f.bucket(buckets, include_under=True)
 
@@ -192,33 +85,4 @@ def test_bucket_assign_labels(table):
     ).name('tier2')
     expr = size[labelled, size['count']]
 
-    expected = """\
-SELECT
-  CASE `tier`
-    WHEN 0 THEN 'Under 0'
-    WHEN 1 THEN '0 to 10'
-    WHEN 2 THEN '10 to 25'
-    WHEN 3 THEN '25 to 50'
-    ELSE 'error'
-  END AS `tier2`, `count`
-FROM (
-  SELECT
-    CASE
-      WHEN `f` < 0 THEN 0
-      WHEN (0 <= `f`) AND (`f` < 10) THEN 1
-      WHEN (10 <= `f`) AND (`f` < 25) THEN 2
-      WHEN (25 <= `f`) AND (`f` <= 50) THEN 3
-      ELSE CAST(NULL AS tinyint)
-    END AS `tier`, count(1) AS `count`
-  FROM alltypes
-  GROUP BY 1
-) t0"""
-
-    result = ImpalaCompiler.to_sql(expr)
-    assert result == expected
-
-    with pytest.raises(ValueError):
-        size.tier.label(list("abc"))
-
-    with pytest.raises(ValueError):
-        size.tier.label(list("abcde"))
+    snapshot.assert_match(ImpalaCompiler.to_sql(expr), "out.sql")
diff --git a/ibis/tests/expr/test_datatypes.py b/ibis/tests/expr/test_datatypes.py
--- a/ibis/tests/expr/test_datatypes.py
+++ b/ibis/tests/expr/test_datatypes.py
@@ -444,7 +444,7 @@ class Foo(enum.Enum):
                 ]
             ),
         ),
-        (Foo.a, dt.Enum(dt.string, dt.int8)),
+        (Foo.a, dt.Enum()),
     ],
 )
 def test_infer_dtype(value, expected_dtype):
diff --git a/ibis/tests/expr/test_rules.py b/ibis/tests/expr/test_rules.py
--- a/ibis/tests/expr/test_rules.py
+++ b/ibis/tests/expr/test_rules.py
@@ -1,5 +1,3 @@
-import enum
-
 import parsy
 import pytest
 from pytest import param
@@ -147,21 +145,6 @@ def test_invalid_isin(values, value, expected):
         rlz.isin(values, value)
 
 
-class Foo(enum.Enum):
-    a = 1
-    b = 2
-
-
-class Bar:
-    a = 'A'
-    b = 'B'
-
-
-class Baz:
-    def __init__(self, a):
-        self.a = a
-
-
 @pytest.mark.parametrize(
     ('validator', 'values', 'expected'),
     [