Repository: ibis-project/ibis-bigquery (language: python)

Issue:
test with multiple versions of ibis
We may explicitly decide to only support ibis-framework 2.0+, but even if so we'll want to test against more than just the version from GitHub on our CI.


Discussion / hints:
Now that https://github.com/ibis-project/ibis-bigquery/pull/31 is done, we can (and should) test with at least ibis 1.4.0, but likely also 1.2.0 and 1.3.0 (based on internal request to support these versions).

Fix patch:
diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index b57275a..f659f6b 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -50,6 +50,15 @@ jobs:
       fail-fast: false
       matrix:
         python_version: ["3.7", "3.8", "3.9"]
+        ibis_version: ["github"]
+        include:
+          - python_version: "3.7"
+            "ibis_version": "1.2.0"
+          - python_version: "3.7"
+            "ibis_version":  "1.3.0"
+          - python_version: "3.8"
+            "ibis_version": "1.4.0"
+
     steps:
 
     - name: checkout
@@ -66,7 +75,9 @@ jobs:
       with:
         python-version: ${{ matrix.python-version }}
 
-    - name: install dependencies
+    - name: install dependencies (ibis ${{ matrix.ibis_version }})
+      env:
+        IBIS_VERSION: ${{ matrix.ibis_version }}
       run: ./ci/install_deps.sh
 
     - name: run tests
diff --git a/README.rst b/README.rst
index fdf0db6..57e5eeb 100644
--- a/README.rst
+++ b/README.rst
@@ -33,7 +33,7 @@ Usage
 Connecting to BigQuery
 ^^^^^^^^^^^^^^^^^^^^^^
 
-Recommended usage:
+Recommended usage (Ibis 2.x, only [not yet released]):
 
 .. code-block:: python
 
diff --git a/ci/install_deps.sh b/ci/install_deps.sh
index 6ddfa3e..1da9c11 100755
--- a/ci/install_deps.sh
+++ b/ci/install_deps.sh
@@ -3,13 +3,20 @@
 set -e
 set -x
 
-# See https://github.com/pypa/pip/issues/7953
-echo "import site
+python -m pip install --upgrade pip
+
+if [ "$IBIS_VERSION" = "github" ] ; then
+    # See https://github.com/pypa/pip/issues/7953
+    echo "
+import site
 import sys
 site.ENABLE_USER_SITE = '--user' in sys.argv[1:]
 $(cat ./ibis/setup.py)" > ./ibis/setup.py
 
-python -m pip install --upgrade pip
-python -m pip install --user -e ./ibis
+    python -m pip install --user -e ./ibis
+else
+    python -m pip install --user ibis-framework=="$IBIS_VERSION"
+fi
+
 python -m pip install --user -e .
 python -m pip install --user pytest
diff --git a/setup.py b/setup.py
index ab57783..095a271 100644
--- a/setup.py
+++ b/setup.py
@@ -41,7 +41,8 @@
     packages=setuptools.find_packages(),
     python_requires=">=3.7",
     install_requires=[
-        "ibis-framework",  # TODO require ibis 2.0 when it's released
+        # TODO require ibis 2.0 when it's released
+        "ibis-framework >= 1.2.0,<3.0.0dev",
         "google-cloud-bigquery >=1.12.0,<3.0.0dev",
         "google-cloud-bigquery-storage >=1.0.0,<3.0.0dev",
         "pyarrow >=1.0.0,<4.0.0dev",


Test patch:
diff --git a/.github/workflows/system-tests-pr.yml b/.github/workflows/system-tests-pr.yml
index 55d63be..f21c7a7 100644
--- a/.github/workflows/system-tests-pr.yml
+++ b/.github/workflows/system-tests-pr.yml
@@ -18,6 +18,15 @@ jobs:
       fail-fast: false
       matrix:
         python_version: ["3.7", "3.8", "3.9"]
+        ibis_version: ["github"]
+        include:
+          - python_version: "3.7"
+            "ibis_version": "1.2.0"
+          - python_version: "3.7"
+            "ibis_version":  "1.3.0"
+          - python_version: "3.8"
+            "ibis_version": "1.4.0"
+
     steps:
     - name: checkout
       uses: actions/checkout@v2
@@ -35,7 +44,9 @@ jobs:
         repository: ibis-project/ibis
         path: ibis
 
-    - name: install dependencies
+    - name: install dependencies (ibis ${{ matrix.ibis_version }})
+      env:
+        IBIS_VERSION: ${{ matrix.ibis_version }}
       run: ./ci/install_deps.sh
 
     - name: set up bigquery credentials
diff --git a/.github/workflows/system-tests.yml b/.github/workflows/system-tests.yml
index 2dff571..aef8ef0 100644
--- a/.github/workflows/system-tests.yml
+++ b/.github/workflows/system-tests.yml
@@ -16,6 +16,15 @@ jobs:
       fail-fast: false
       matrix:
         python_version: ["3.7", "3.8", "3.9"]
+        ibis_version: ["github"]
+        include:
+          - python_version: "3.7"
+            "ibis_version": "1.2.0"
+          - python_version: "3.7"
+            "ibis_version":  "1.3.0"
+          - python_version: "3.8"
+            "ibis_version": "1.4.0"
+
     steps:
     - name: checkout
       uses: actions/checkout@v2
@@ -31,7 +40,9 @@ jobs:
         repository: ibis-project/ibis
         path: ibis
 
-    - name: install dependencies
+    - name: install dependencies (ibis ${{ matrix.ibis_version }})
+      env:
+        IBIS_VERSION: ${{ matrix.ibis_version }}
       run: ./ci/install_deps.sh
 
     - name: set up bigquery credentials
diff --git a/tests/system/test_client.py b/tests/system/test_client.py
index 24f7f73..f36c9bc 100644
--- a/tests/system/test_client.py
+++ b/tests/system/test_client.py
@@ -6,6 +6,7 @@
 import ibis.expr.datatypes as dt
 import ibis.expr.types as ir
 import numpy as np
+import packaging
 import pandas as pd
 import pandas.testing as tm
 import pytest
@@ -15,7 +16,8 @@
 import ibis_bigquery
 from ibis_bigquery.client import bigquery_param
 
-pytestmark = pytest.mark.bigquery
+IBIS_VERSION = packaging.version.Version(ibis.__version__)
+IBIS_1_4_VERSION = packaging.version.Version("1.4.0")
 
 
 def test_table(alltypes):
@@ -236,6 +238,8 @@ def test_subquery_scalar_params(alltypes, project_id):
 
 
 def test_scalar_param_string(alltypes, df):
+    if IBIS_VERSION < IBIS_1_4_VERSION:
+        pytest.skip("requires ibis 1.4+")
     param = ibis.param('string')
     expr = alltypes[alltypes.string_col == param]
 
@@ -254,6 +258,8 @@ def test_scalar_param_string(alltypes, df):
 
 
 def test_scalar_param_int64(alltypes, df):
+    if IBIS_VERSION < IBIS_1_4_VERSION:
+        pytest.skip("requires ibis 1.4+")
     param = ibis.param('int64')
     expr = alltypes[alltypes.string_col.cast('int64') == param]
 
@@ -272,6 +278,8 @@ def test_scalar_param_int64(alltypes, df):
 
 
 def test_scalar_param_double(alltypes, df):
+    if IBIS_VERSION < IBIS_1_4_VERSION:
+        pytest.skip("requires ibis 1.4+")
     param = ibis.param('double')
     expr = alltypes[alltypes.string_col.cast('int64').cast('double') == param]
 
@@ -290,6 +298,8 @@ def test_scalar_param_double(alltypes, df):
 
 
 def test_scalar_param_boolean(alltypes, df):
+    if IBIS_VERSION < IBIS_1_4_VERSION:
+        pytest.skip("requires ibis 1.4+")
     param = ibis.param('boolean')
     expr = alltypes[(alltypes.string_col.cast('int64') == 0) == param]
 
@@ -316,6 +326,8 @@ def test_scalar_param_boolean(alltypes, df):
     ],
 )
 def test_scalar_param_timestamp(alltypes, df, timestamp_value):
+    if IBIS_VERSION < IBIS_1_4_VERSION:
+        pytest.skip("requires ibis 1.4+")
     param = ibis.param('timestamp')
     expr = alltypes[alltypes.timestamp_col <= param][['timestamp_col']]
 
@@ -338,6 +350,8 @@ def test_scalar_param_timestamp(alltypes, df, timestamp_value):
     ['2009-01-20', datetime.date(2009, 1, 20), datetime.datetime(2009, 1, 20)],
 )
 def test_scalar_param_date(alltypes, df, date_value):
+    if IBIS_VERSION < IBIS_1_4_VERSION:
+        pytest.skip("requires ibis 1.4+")
     param = ibis.param('date')
     expr = alltypes[alltypes.timestamp_col.cast('date') <= param]
 
@@ -356,6 +370,8 @@ def test_scalar_param_date(alltypes, df, date_value):
 
 
 def test_scalar_param_array(alltypes, df):
+    if IBIS_VERSION < IBIS_1_4_VERSION:
+        pytest.skip("requires ibis 1.4+")
     param = ibis.param('array<double>')
     expr = alltypes.sort_by('id').limit(1).double_col.collect() + param
     result = expr.execute(params={param: [1]})
@@ -368,6 +384,8 @@ def test_scalar_param_array(alltypes, df):
 
 
 def test_scalar_param_struct(client):
+    if IBIS_VERSION < IBIS_1_4_VERSION:
+        pytest.skip("requires ibis 1.4+")
     struct_type = dt.Struct.from_tuples([('x', dt.int64), ('y', dt.string)])
     param = ibis.param(struct_type)
     value = collections.OrderedDict([('x', 1), ('y', 'foobar')])
@@ -376,6 +394,8 @@ def test_scalar_param_struct(client):
 
 
 def test_scalar_param_nested(client):
+    if IBIS_VERSION < IBIS_1_4_VERSION:
+        pytest.skip("requires ibis 1.4+")
     param = ibis.param('struct<x: array<struct<y: array<double>>>>')
     value = collections.OrderedDict(
         [('x', [collections.OrderedDict([('y', [1.0, 2.0, 3.0])])])]
@@ -467,6 +487,8 @@ def test_parted_column_rename(parted_alltypes):
 
 
 def test_scalar_param_partition_time(parted_alltypes):
+    if IBIS_VERSION < IBIS_1_4_VERSION:
+        pytest.skip("requires ibis 1.4+")
     assert 'PARTITIONTIME' in parted_alltypes.columns
     assert 'PARTITIONTIME' in parted_alltypes.schema()
     param = ibis.param('timestamp').name('time_param')
diff --git a/tests/unit/test_compiler.py b/tests/unit/test_compiler.py
index a52f076..a579cc3 100644
--- a/tests/unit/test_compiler.py
+++ b/tests/unit/test_compiler.py
@@ -3,12 +3,16 @@
 import ibis
 import ibis.expr.datatypes as dt
 import ibis.expr.operations as ops
+import packaging.version
 import pandas as pd
 import pytest
 from ibis.expr.types import TableExpr
 
 import ibis_bigquery
 
+IBIS_VERSION = packaging.version.Version(ibis.__version__)
+IBIS_1_4_VERSION = packaging.version.Version("1.4.0")
+
 
 @pytest.mark.parametrize(
     ('case', 'expected', 'dtype'),
@@ -103,6 +107,8 @@ def test_day_of_week(case, expected, dtype, strftime_func):
     ],
 )
 def test_hash(case, expected, dtype):
+    if IBIS_VERSION < IBIS_1_4_VERSION:
+        pytest.skip("requires ibis 1.4+")
     string_var = ibis.literal(case, type=dtype)
     expr = string_var.hash(how="farm_fingerprint")
     result = ibis_bigquery.compile(expr)
@@ -123,6 +129,8 @@ def test_hash(case, expected, dtype):
     ],
 )
 def test_hashbytes(case, expected, how, dtype):
+    if IBIS_VERSION < IBIS_1_4_VERSION:
+        pytest.skip("requires ibis 1.4+")
     var = ibis.literal(case, type=dtype)
     expr = var.hashbytes(how=how)
     result = ibis_bigquery.compile(expr)
@@ -158,6 +166,8 @@ def test_literal_timestamp_or_time(case, expected, dtype):
 
 
 def test_projection_fusion_only_peeks_at_immediate_parent():
+    if IBIS_VERSION < IBIS_1_4_VERSION:
+        pytest.skip("requires ibis 1.4+")
     schema = [
         ('file_date', 'timestamp'),
         ('PARTITIONTIME', 'date'),