You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@iceberg.apache.org by bl...@apache.org on 2022/11/19 22:21:35 UTC
[iceberg] branch master updated: Python: Remove dataclasses (#6139)
This is an automated email from the ASF dual-hosted git repository.
blue pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/iceberg.git
The following commit(s) were added to refs/heads/master by this push:
new dbf91118c9 Python: Remove dataclasses (#6139)
dbf91118c9 is described below
commit dbf91118c9333977fd0a3dcfc294c646dbd5e2b9
Author: Fokko Driesprong <fo...@apache.org>
AuthorDate: Sat Nov 19 23:21:28 2022 +0100
Python: Remove dataclasses (#6139)
---
python/poetry.lock | 177 +++++----
python/pyiceberg/expressions/__init__.py | 526 ++++++++++++++++----------
python/pyiceberg/expressions/literals.py | 99 ++---
python/pyiceberg/expressions/visitors.py | 126 +++----
python/pyiceberg/typedef.py | 7 +-
python/pyproject.toml | 1 +
python/tests/expressions/test_expressions.py | 522 +++++++++++++++++---------
python/tests/expressions/test_literals.py | 41 +-
python/tests/expressions/test_visitors.py | 535 ++++++++++++---------------
python/tests/table/test_init.py | 12 +-
10 files changed, 1144 insertions(+), 902 deletions(-)
diff --git a/python/poetry.lock b/python/poetry.lock
index 2cb2689f57..e5157bda8c 100644
--- a/python/poetry.lock
+++ b/python/poetry.lock
@@ -49,11 +49,11 @@ typing_extensions = {version = ">=4.0", markers = "python_version < \"3.10\""}
[[package]]
name = "aiosignal"
-version = "1.2.0"
+version = "1.3.1"
description = "aiosignal: a list of registered asynchronous callbacks"
category = "main"
optional = true
-python-versions = ">=3.6"
+python-versions = ">=3.7"
[package.dependencies]
frozenlist = ">=1.1.0"
@@ -216,7 +216,7 @@ python-versions = ">=3.7"
[[package]]
name = "exceptiongroup"
-version = "1.0.0"
+version = "1.0.4"
description = "Backport of PEP 654 (exception groups)"
category = "dev"
optional = false
@@ -253,7 +253,7 @@ testing = ["covdefaults (>=2.2)", "coverage (>=6.4.2)", "pytest (>=7.1.2)", "pyt
[[package]]
name = "frozenlist"
-version = "1.3.1"
+version = "1.3.3"
description = "A list-like structure which implements collections.abc.MutableSequence"
category = "main"
optional = true
@@ -400,15 +400,15 @@ tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""}
[[package]]
name = "platformdirs"
-version = "2.5.2"
-description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"."
+version = "2.5.4"
+description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"."
category = "dev"
optional = false
python-versions = ">=3.7"
[package.extras]
-docs = ["furo (>=2021.7.5b38)", "proselint (>=0.10.2)", "sphinx (>=4)", "sphinx-autodoc-typehints (>=1.12)"]
-test = ["appdirs (==1.4.4)", "pytest (>=6)", "pytest-cov (>=2.7)", "pytest-mock (>=3.6)"]
+docs = ["furo (>=2022.9.29)", "proselint (>=0.13)", "sphinx (>=5.3)", "sphinx-autodoc-typehints (>=1.19.4)"]
+test = ["appdirs (==1.4.4)", "pytest (>=7.2)", "pytest-cov (>=4)", "pytest-mock (>=3.10)"]
[[package]]
name = "pluggy"
@@ -627,7 +627,7 @@ boto3 = ["aiobotocore[boto3] (>=2.4.0,<2.5.0)"]
[[package]]
name = "setuptools"
-version = "65.5.0"
+version = "65.5.1"
description = "Easily download, build, install, upgrade, and uninstall Python packages"
category = "dev"
optional = false
@@ -635,7 +635,7 @@ python-versions = ">=3.7"
[package.extras]
docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-hoverxref (<2)", "sphinx-inline-tabs", "sphinx-notfound-page (==0.8.3)", "sphinx-reredirects", "sphinxcontrib-towncrier"]
-testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8 (<5)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "mock", "pip (>=19.1)", "pip-run (>=8.8)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"]
+testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8 (<5)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip (>=19.1)", "pip-run (>=8.8)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"]
testing-integration = ["build[virtualenv]", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"]
[[package]]
@@ -701,7 +701,7 @@ socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"]
[[package]]
name = "virtualenv"
-version = "20.16.6"
+version = "20.16.7"
description = "Virtual Python Environment builder"
category = "dev"
optional = false
@@ -771,7 +771,7 @@ snappy = ["python-snappy"]
[metadata]
lock-version = "1.1"
python-versions = "^3.8"
-content-hash = "4f90d01e509c4918b7e4ce6da629f5e009165a499cd2f43c25f3ef73ef58af86"
+content-hash = "fda6f8ad5abce655e854325c9e0e944c6ad818487479c97078d1dce93496465e"
[metadata.files]
aiobotocore = [
@@ -872,8 +872,8 @@ aioitertools = [
{file = "aioitertools-0.11.0.tar.gz", hash = "sha256:42c68b8dd3a69c2bf7f2233bf7df4bb58b557bca5252ac02ed5187bbc67d6831"},
]
aiosignal = [
- {file = "aiosignal-1.2.0-py3-none-any.whl", hash = "sha256:26e62109036cd181df6e6ad646f91f0dcfd05fe16d0cb924138ff2ab75d64e3a"},
- {file = "aiosignal-1.2.0.tar.gz", hash = "sha256:78ed67db6c7b7ced4f98e495e572106d5c432a93e1ddd1bf475e1dc05f5b7df2"},
+ {file = "aiosignal-1.3.1-py3-none-any.whl", hash = "sha256:f8376fb07dd1e86a584e4fcdec80b36b7f81aac666ebc724e2c090300dd83b17"},
+ {file = "aiosignal-1.3.1.tar.gz", hash = "sha256:54cd96e15e1649b75d6c87526a6ff0b6c1b0dd3459f43d9ca11d48c339b68cfc"},
]
async-timeout = [
{file = "async-timeout-4.0.2.tar.gz", hash = "sha256:2163e1640ddb52b7a8c80d0a67a08587e5d245cc9c553a74a847056bc2976b15"},
@@ -1042,8 +1042,8 @@ docutils = [
{file = "docutils-0.19.tar.gz", hash = "sha256:33995a6753c30b7f577febfc2c50411fec6aac7f7ffeb7c4cfe5991072dcf9e6"},
]
exceptiongroup = [
- {file = "exceptiongroup-1.0.0-py3-none-any.whl", hash = "sha256:2ac84b496be68464a2da60da518af3785fff8b7ec0d090a581604bc870bdee41"},
- {file = "exceptiongroup-1.0.0.tar.gz", hash = "sha256:affbabf13fb6e98988c38d9c5650e701569fe3c1de3233cfb61c5f33774690ad"},
+ {file = "exceptiongroup-1.0.4-py3-none-any.whl", hash = "sha256:542adf9dea4055530d6e1279602fa5cb11dab2395fa650b8674eaec35fc4a828"},
+ {file = "exceptiongroup-1.0.4.tar.gz", hash = "sha256:bd14967b79cd9bdb54d97323216f8fdf533e278df937aa2a90089e7d6e06e5ec"},
]
fastavro = [
{file = "fastavro-1.6.1-cp310-cp310-macosx_10_14_x86_64.whl", hash = "sha256:de244146a3d7bc4e60c7be11f317054ee0e57ca807d85923bd8407981488ff18"},
@@ -1069,65 +1069,80 @@ filelock = [
{file = "filelock-3.8.0.tar.gz", hash = "sha256:55447caa666f2198c5b6b13a26d2084d26fa5b115c00d065664b2124680c4edc"},
]
frozenlist = [
- {file = "frozenlist-1.3.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:5f271c93f001748fc26ddea409241312a75e13466b06c94798d1a341cf0e6989"},
- {file = "frozenlist-1.3.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:9c6ef8014b842f01f5d2b55315f1af5cbfde284eb184075c189fd657c2fd8204"},
- {file = "frozenlist-1.3.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:219a9676e2eae91cb5cc695a78b4cb43d8123e4160441d2b6ce8d2c70c60e2f3"},
- {file = "frozenlist-1.3.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b47d64cdd973aede3dd71a9364742c542587db214e63b7529fbb487ed67cddd9"},
- {file = "frozenlist-1.3.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2af6f7a4e93f5d08ee3f9152bce41a6015b5cf87546cb63872cc19b45476e98a"},
- {file = "frozenlist-1.3.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a718b427ff781c4f4e975525edb092ee2cdef6a9e7bc49e15063b088961806f8"},
- {file = "frozenlist-1.3.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c56c299602c70bc1bb5d1e75f7d8c007ca40c9d7aebaf6e4ba52925d88ef826d"},
- {file = "frozenlist-1.3.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:717470bfafbb9d9be624da7780c4296aa7935294bd43a075139c3d55659038ca"},
- {file = "frozenlist-1.3.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:31b44f1feb3630146cffe56344704b730c33e042ffc78d21f2125a6a91168131"},
- {file = "frozenlist-1.3.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:c3b31180b82c519b8926e629bf9f19952c743e089c41380ddca5db556817b221"},
- {file = "frozenlist-1.3.1-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:d82bed73544e91fb081ab93e3725e45dd8515c675c0e9926b4e1f420a93a6ab9"},
- {file = "frozenlist-1.3.1-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:49459f193324fbd6413e8e03bd65789e5198a9fa3095e03f3620dee2f2dabff2"},
- {file = "frozenlist-1.3.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:94e680aeedc7fd3b892b6fa8395b7b7cc4b344046c065ed4e7a1e390084e8cb5"},
- {file = "frozenlist-1.3.1-cp310-cp310-win32.whl", hash = "sha256:fabb953ab913dadc1ff9dcc3a7a7d3dc6a92efab3a0373989b8063347f8705be"},
- {file = "frozenlist-1.3.1-cp310-cp310-win_amd64.whl", hash = "sha256:eee0c5ecb58296580fc495ac99b003f64f82a74f9576a244d04978a7e97166db"},
- {file = "frozenlist-1.3.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0bc75692fb3770cf2b5856a6c2c9de967ca744863c5e89595df64e252e4b3944"},
- {file = "frozenlist-1.3.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:086ca1ac0a40e722d6833d4ce74f5bf1aba2c77cbfdc0cd83722ffea6da52a04"},
- {file = "frozenlist-1.3.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1b51eb355e7f813bcda00276b0114c4172872dc5fb30e3fea059b9367c18fbcb"},
- {file = "frozenlist-1.3.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:74140933d45271c1a1283f708c35187f94e1256079b3c43f0c2267f9db5845ff"},
- {file = "frozenlist-1.3.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ee4c5120ddf7d4dd1eaf079af3af7102b56d919fa13ad55600a4e0ebe532779b"},
- {file = "frozenlist-1.3.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:97d9e00f3ac7c18e685320601f91468ec06c58acc185d18bb8e511f196c8d4b2"},
- {file = "frozenlist-1.3.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:6e19add867cebfb249b4e7beac382d33215d6d54476bb6be46b01f8cafb4878b"},
- {file = "frozenlist-1.3.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:a027f8f723d07c3f21963caa7d585dcc9b089335565dabe9c814b5f70c52705a"},
- {file = "frozenlist-1.3.1-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:61d7857950a3139bce035ad0b0945f839532987dfb4c06cfe160254f4d19df03"},
- {file = "frozenlist-1.3.1-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:53b2b45052e7149ee8b96067793db8ecc1ae1111f2f96fe1f88ea5ad5fd92d10"},
- {file = "frozenlist-1.3.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:bbb1a71b1784e68870800b1bc9f3313918edc63dbb8f29fbd2e767ce5821696c"},
- {file = "frozenlist-1.3.1-cp37-cp37m-win32.whl", hash = "sha256:ab6fa8c7871877810e1b4e9392c187a60611fbf0226a9e0b11b7b92f5ac72792"},
- {file = "frozenlist-1.3.1-cp37-cp37m-win_amd64.whl", hash = "sha256:f89139662cc4e65a4813f4babb9ca9544e42bddb823d2ec434e18dad582543bc"},
- {file = "frozenlist-1.3.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:4c0c99e31491a1d92cde8648f2e7ccad0e9abb181f6ac3ddb9fc48b63301808e"},
- {file = "frozenlist-1.3.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:61e8cb51fba9f1f33887e22488bad1e28dd8325b72425f04517a4d285a04c519"},
- {file = "frozenlist-1.3.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:cc2f3e368ee5242a2cbe28323a866656006382872c40869b49b265add546703f"},
- {file = "frozenlist-1.3.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:58fb94a01414cddcdc6839807db77ae8057d02ddafc94a42faee6004e46c9ba8"},
- {file = "frozenlist-1.3.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:022178b277cb9277d7d3b3f2762d294f15e85cd2534047e68a118c2bb0058f3e"},
- {file = "frozenlist-1.3.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:572ce381e9fe027ad5e055f143763637dcbac2542cfe27f1d688846baeef5170"},
- {file = "frozenlist-1.3.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:19127f8dcbc157ccb14c30e6f00392f372ddb64a6ffa7106b26ff2196477ee9f"},
- {file = "frozenlist-1.3.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:42719a8bd3792744c9b523674b752091a7962d0d2d117f0b417a3eba97d1164b"},
- {file = "frozenlist-1.3.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:2743bb63095ef306041c8f8ea22bd6e4d91adabf41887b1ad7886c4c1eb43d5f"},
- {file = "frozenlist-1.3.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:fa47319a10e0a076709644a0efbcaab9e91902c8bd8ef74c6adb19d320f69b83"},
- {file = "frozenlist-1.3.1-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:52137f0aea43e1993264a5180c467a08a3e372ca9d378244c2d86133f948b26b"},
- {file = "frozenlist-1.3.1-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:f5abc8b4d0c5b556ed8cd41490b606fe99293175a82b98e652c3f2711b452988"},
- {file = "frozenlist-1.3.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:1e1cf7bc8cbbe6ce3881863671bac258b7d6bfc3706c600008925fb799a256e2"},
- {file = "frozenlist-1.3.1-cp38-cp38-win32.whl", hash = "sha256:0dde791b9b97f189874d654c55c24bf7b6782343e14909c84beebd28b7217845"},
- {file = "frozenlist-1.3.1-cp38-cp38-win_amd64.whl", hash = "sha256:9494122bf39da6422b0972c4579e248867b6b1b50c9b05df7e04a3f30b9a413d"},
- {file = "frozenlist-1.3.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:31bf9539284f39ff9398deabf5561c2b0da5bb475590b4e13dd8b268d7a3c5c1"},
- {file = "frozenlist-1.3.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:e0c8c803f2f8db7217898d11657cb6042b9b0553a997c4a0601f48a691480fab"},
- {file = "frozenlist-1.3.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:da5ba7b59d954f1f214d352308d1d86994d713b13edd4b24a556bcc43d2ddbc3"},
- {file = "frozenlist-1.3.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:74e6b2b456f21fc93ce1aff2b9728049f1464428ee2c9752a4b4f61e98c4db96"},
- {file = "frozenlist-1.3.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:526d5f20e954d103b1d47232e3839f3453c02077b74203e43407b962ab131e7b"},
- {file = "frozenlist-1.3.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b499c6abe62a7a8d023e2c4b2834fce78a6115856ae95522f2f974139814538c"},
- {file = "frozenlist-1.3.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ab386503f53bbbc64d1ad4b6865bf001414930841a870fc97f1546d4d133f141"},
- {file = "frozenlist-1.3.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5f63c308f82a7954bf8263a6e6de0adc67c48a8b484fab18ff87f349af356efd"},
- {file = "frozenlist-1.3.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:12607804084d2244a7bd4685c9d0dca5df17a6a926d4f1967aa7978b1028f89f"},
- {file = "frozenlist-1.3.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:da1cdfa96425cbe51f8afa43e392366ed0b36ce398f08b60de6b97e3ed4affef"},
- {file = "frozenlist-1.3.1-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:f810e764617b0748b49a731ffaa525d9bb36ff38332411704c2400125af859a6"},
- {file = "frozenlist-1.3.1-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:35c3d79b81908579beb1fb4e7fcd802b7b4921f1b66055af2578ff7734711cfa"},
- {file = "frozenlist-1.3.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:c92deb5d9acce226a501b77307b3b60b264ca21862bd7d3e0c1f3594022f01bc"},
- {file = "frozenlist-1.3.1-cp39-cp39-win32.whl", hash = "sha256:5e77a8bd41e54b05e4fb2708dc6ce28ee70325f8c6f50f3df86a44ecb1d7a19b"},
- {file = "frozenlist-1.3.1-cp39-cp39-win_amd64.whl", hash = "sha256:625d8472c67f2d96f9a4302a947f92a7adbc1e20bedb6aff8dbc8ff039ca6189"},
- {file = "frozenlist-1.3.1.tar.gz", hash = "sha256:3a735e4211a04ccfa3f4833547acdf5d2f863bfeb01cfd3edaffbc251f15cec8"},
+ {file = "frozenlist-1.3.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:ff8bf625fe85e119553b5383ba0fb6aa3d0ec2ae980295aaefa552374926b3f4"},
+ {file = "frozenlist-1.3.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:dfbac4c2dfcc082fcf8d942d1e49b6aa0766c19d3358bd86e2000bf0fa4a9cf0"},
+ {file = "frozenlist-1.3.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:b1c63e8d377d039ac769cd0926558bb7068a1f7abb0f003e3717ee003ad85530"},
+ {file = "frozenlist-1.3.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7fdfc24dcfce5b48109867c13b4cb15e4660e7bd7661741a391f821f23dfdca7"},
+ {file = "frozenlist-1.3.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2c926450857408e42f0bbc295e84395722ce74bae69a3b2aa2a65fe22cb14b99"},
+ {file = "frozenlist-1.3.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1841e200fdafc3d51f974d9d377c079a0694a8f06de2e67b48150328d66d5483"},
+ {file = "frozenlist-1.3.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f470c92737afa7d4c3aacc001e335062d582053d4dbe73cda126f2d7031068dd"},
+ {file = "frozenlist-1.3.3-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:783263a4eaad7c49983fe4b2e7b53fa9770c136c270d2d4bbb6d2192bf4d9caf"},
+ {file = "frozenlist-1.3.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:924620eef691990dfb56dc4709f280f40baee568c794b5c1885800c3ecc69816"},
+ {file = "frozenlist-1.3.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:ae4dc05c465a08a866b7a1baf360747078b362e6a6dbeb0c57f234db0ef88ae0"},
+ {file = "frozenlist-1.3.3-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:bed331fe18f58d844d39ceb398b77d6ac0b010d571cba8267c2e7165806b00ce"},
+ {file = "frozenlist-1.3.3-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:02c9ac843e3390826a265e331105efeab489ffaf4dd86384595ee8ce6d35ae7f"},
+ {file = "frozenlist-1.3.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:9545a33965d0d377b0bc823dcabf26980e77f1b6a7caa368a365a9497fb09420"},
+ {file = "frozenlist-1.3.3-cp310-cp310-win32.whl", hash = "sha256:d5cd3ab21acbdb414bb6c31958d7b06b85eeb40f66463c264a9b343a4e238642"},
+ {file = "frozenlist-1.3.3-cp310-cp310-win_amd64.whl", hash = "sha256:b756072364347cb6aa5b60f9bc18e94b2f79632de3b0190253ad770c5df17db1"},
+ {file = "frozenlist-1.3.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:b4395e2f8d83fbe0c627b2b696acce67868793d7d9750e90e39592b3626691b7"},
+ {file = "frozenlist-1.3.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:14143ae966a6229350021384870458e4777d1eae4c28d1a7aa47f24d030e6678"},
+ {file = "frozenlist-1.3.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5d8860749e813a6f65bad8285a0520607c9500caa23fea6ee407e63debcdbef6"},
+ {file = "frozenlist-1.3.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:23d16d9f477bb55b6154654e0e74557040575d9d19fe78a161bd33d7d76808e8"},
+ {file = "frozenlist-1.3.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:eb82dbba47a8318e75f679690190c10a5e1f447fbf9df41cbc4c3afd726d88cb"},
+ {file = "frozenlist-1.3.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9309869032abb23d196cb4e4db574232abe8b8be1339026f489eeb34a4acfd91"},
+ {file = "frozenlist-1.3.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a97b4fe50b5890d36300820abd305694cb865ddb7885049587a5678215782a6b"},
+ {file = "frozenlist-1.3.3-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c188512b43542b1e91cadc3c6c915a82a5eb95929134faf7fd109f14f9892ce4"},
+ {file = "frozenlist-1.3.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:303e04d422e9b911a09ad499b0368dc551e8c3cd15293c99160c7f1f07b59a48"},
+ {file = "frozenlist-1.3.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:0771aed7f596c7d73444c847a1c16288937ef988dc04fb9f7be4b2aa91db609d"},
+ {file = "frozenlist-1.3.3-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:66080ec69883597e4d026f2f71a231a1ee9887835902dbe6b6467d5a89216cf6"},
+ {file = "frozenlist-1.3.3-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:41fe21dc74ad3a779c3d73a2786bdf622ea81234bdd4faf90b8b03cad0c2c0b4"},
+ {file = "frozenlist-1.3.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:f20380df709d91525e4bee04746ba612a4df0972c1b8f8e1e8af997e678c7b81"},
+ {file = "frozenlist-1.3.3-cp311-cp311-win32.whl", hash = "sha256:f30f1928162e189091cf4d9da2eac617bfe78ef907a761614ff577ef4edfb3c8"},
+ {file = "frozenlist-1.3.3-cp311-cp311-win_amd64.whl", hash = "sha256:a6394d7dadd3cfe3f4b3b186e54d5d8504d44f2d58dcc89d693698e8b7132b32"},
+ {file = "frozenlist-1.3.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:8df3de3a9ab8325f94f646609a66cbeeede263910c5c0de0101079ad541af332"},
+ {file = "frozenlist-1.3.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0693c609e9742c66ba4870bcee1ad5ff35462d5ffec18710b4ac89337ff16e27"},
+ {file = "frozenlist-1.3.3-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cd4210baef299717db0a600d7a3cac81d46ef0e007f88c9335db79f8979c0d3d"},
+ {file = "frozenlist-1.3.3-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:394c9c242113bfb4b9aa36e2b80a05ffa163a30691c7b5a29eba82e937895d5e"},
+ {file = "frozenlist-1.3.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6327eb8e419f7d9c38f333cde41b9ae348bec26d840927332f17e887a8dcb70d"},
+ {file = "frozenlist-1.3.3-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2e24900aa13212e75e5b366cb9065e78bbf3893d4baab6052d1aca10d46d944c"},
+ {file = "frozenlist-1.3.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:3843f84a6c465a36559161e6c59dce2f2ac10943040c2fd021cfb70d58c4ad56"},
+ {file = "frozenlist-1.3.3-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:84610c1502b2461255b4c9b7d5e9c48052601a8957cd0aea6ec7a7a1e1fb9420"},
+ {file = "frozenlist-1.3.3-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:c21b9aa40e08e4f63a2f92ff3748e6b6c84d717d033c7b3438dd3123ee18f70e"},
+ {file = "frozenlist-1.3.3-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:efce6ae830831ab6a22b9b4091d411698145cb9b8fc869e1397ccf4b4b6455cb"},
+ {file = "frozenlist-1.3.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:40de71985e9042ca00b7953c4f41eabc3dc514a2d1ff534027f091bc74416401"},
+ {file = "frozenlist-1.3.3-cp37-cp37m-win32.whl", hash = "sha256:180c00c66bde6146a860cbb81b54ee0df350d2daf13ca85b275123bbf85de18a"},
+ {file = "frozenlist-1.3.3-cp37-cp37m-win_amd64.whl", hash = "sha256:9bbbcedd75acdfecf2159663b87f1bb5cfc80e7cd99f7ddd9d66eb98b14a8411"},
+ {file = "frozenlist-1.3.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:034a5c08d36649591be1cbb10e09da9f531034acfe29275fc5454a3b101ce41a"},
+ {file = "frozenlist-1.3.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ba64dc2b3b7b158c6660d49cdb1d872d1d0bf4e42043ad8d5006099479a194e5"},
+ {file = "frozenlist-1.3.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:47df36a9fe24054b950bbc2db630d508cca3aa27ed0566c0baf661225e52c18e"},
+ {file = "frozenlist-1.3.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:008a054b75d77c995ea26629ab3a0c0d7281341f2fa7e1e85fa6153ae29ae99c"},
+ {file = "frozenlist-1.3.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:841ea19b43d438a80b4de62ac6ab21cfe6827bb8a9dc62b896acc88eaf9cecba"},
+ {file = "frozenlist-1.3.3-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e235688f42b36be2b6b06fc37ac2126a73b75fb8d6bc66dd632aa35286238703"},
+ {file = "frozenlist-1.3.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ca713d4af15bae6e5d79b15c10c8522859a9a89d3b361a50b817c98c2fb402a2"},
+ {file = "frozenlist-1.3.3-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9ac5995f2b408017b0be26d4a1d7c61bce106ff3d9e3324374d66b5964325448"},
+ {file = "frozenlist-1.3.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:a4ae8135b11652b08a8baf07631d3ebfe65a4c87909dbef5fa0cdde440444ee4"},
+ {file = "frozenlist-1.3.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:4ea42116ceb6bb16dbb7d526e242cb6747b08b7710d9782aa3d6732bd8d27649"},
+ {file = "frozenlist-1.3.3-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:810860bb4bdce7557bc0febb84bbd88198b9dbc2022d8eebe5b3590b2ad6c842"},
+ {file = "frozenlist-1.3.3-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:ee78feb9d293c323b59a6f2dd441b63339a30edf35abcb51187d2fc26e696d13"},
+ {file = "frozenlist-1.3.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:0af2e7c87d35b38732e810befb9d797a99279cbb85374d42ea61c1e9d23094b3"},
+ {file = "frozenlist-1.3.3-cp38-cp38-win32.whl", hash = "sha256:899c5e1928eec13fd6f6d8dc51be23f0d09c5281e40d9cf4273d188d9feeaf9b"},
+ {file = "frozenlist-1.3.3-cp38-cp38-win_amd64.whl", hash = "sha256:7f44e24fa70f6fbc74aeec3e971f60a14dde85da364aa87f15d1be94ae75aeef"},
+ {file = "frozenlist-1.3.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:2b07ae0c1edaa0a36339ec6cce700f51b14a3fc6545fdd32930d2c83917332cf"},
+ {file = "frozenlist-1.3.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:ebb86518203e12e96af765ee89034a1dbb0c3c65052d1b0c19bbbd6af8a145e1"},
+ {file = "frozenlist-1.3.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:5cf820485f1b4c91e0417ea0afd41ce5cf5965011b3c22c400f6d144296ccbc0"},
+ {file = "frozenlist-1.3.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5c11e43016b9024240212d2a65043b70ed8dfd3b52678a1271972702d990ac6d"},
+ {file = "frozenlist-1.3.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8fa3c6e3305aa1146b59a09b32b2e04074945ffcfb2f0931836d103a2c38f936"},
+ {file = "frozenlist-1.3.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:352bd4c8c72d508778cf05ab491f6ef36149f4d0cb3c56b1b4302852255d05d5"},
+ {file = "frozenlist-1.3.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:65a5e4d3aa679610ac6e3569e865425b23b372277f89b5ef06cf2cdaf1ebf22b"},
+ {file = "frozenlist-1.3.3-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b1e2c1185858d7e10ff045c496bbf90ae752c28b365fef2c09cf0fa309291669"},
+ {file = "frozenlist-1.3.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:f163d2fd041c630fed01bc48d28c3ed4a3b003c00acd396900e11ee5316b56bb"},
+ {file = "frozenlist-1.3.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:05cdb16d09a0832eedf770cb7bd1fe57d8cf4eaf5aced29c4e41e3f20b30a784"},
+ {file = "frozenlist-1.3.3-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:8bae29d60768bfa8fb92244b74502b18fae55a80eac13c88eb0b496d4268fd2d"},
+ {file = "frozenlist-1.3.3-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:eedab4c310c0299961ac285591acd53dc6723a1ebd90a57207c71f6e0c2153ab"},
+ {file = "frozenlist-1.3.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:3bbdf44855ed8f0fbcd102ef05ec3012d6a4fd7c7562403f76ce6a52aeffb2b1"},
+ {file = "frozenlist-1.3.3-cp39-cp39-win32.whl", hash = "sha256:efa568b885bca461f7c7b9e032655c0c143d305bf01c30caf6db2854a4532b38"},
+ {file = "frozenlist-1.3.3-cp39-cp39-win_amd64.whl", hash = "sha256:cfe33efc9cb900a4c46f91a5ceba26d6df370ffddd9ca386eb1d4f0ad97b9ea9"},
+ {file = "frozenlist-1.3.3.tar.gz", hash = "sha256:58bcc55721e8a90b88332d6cd441261ebb22342e238296bb330968952fbb3a6a"},
]
fsspec = [
{file = "fsspec-2022.10.0-py3-none-any.whl", hash = "sha256:6b7c6ab3b476cdf17efcfeccde7fca28ef5a48f73a71010aaceec5fc15bf9ebf"},
@@ -1293,8 +1308,8 @@ pep517 = [
{file = "pep517-0.13.0.tar.gz", hash = "sha256:ae69927c5c172be1add9203726d4b84cf3ebad1edcd5f71fcdc746e66e829f59"},
]
platformdirs = [
- {file = "platformdirs-2.5.2-py3-none-any.whl", hash = "sha256:027d8e83a2d7de06bbac4e5ef7e023c02b863d7ea5d079477e722bb41ab25788"},
- {file = "platformdirs-2.5.2.tar.gz", hash = "sha256:58c8abb07dcb441e6ee4b11d8df0ac856038f944ab98b7be6b27b2a3c7feef19"},
+ {file = "platformdirs-2.5.4-py3-none-any.whl", hash = "sha256:af0276409f9a02373d540bf8480021a048711d572745aef4b7842dad245eba10"},
+ {file = "platformdirs-2.5.4.tar.gz", hash = "sha256:1006647646d80f16130f052404c6b901e80ee4ed6bef6792e1f238a8969106f7"},
]
pluggy = [
{file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"},
@@ -1499,8 +1514,8 @@ s3fs = [
{file = "s3fs-2022.10.0.tar.gz", hash = "sha256:e8deb80f20bd0b2059141b874fdb9d6aeb8cce35312ea5f2c02b225a78a00406"},
]
setuptools = [
- {file = "setuptools-65.5.0-py3-none-any.whl", hash = "sha256:f62ea9da9ed6289bfe868cd6845968a2c854d1427f8548d52cae02a42b4f0356"},
- {file = "setuptools-65.5.0.tar.gz", hash = "sha256:512e5536220e38146176efb833d4a62aa726b7bbff82cfbc8ba9eaa3996e0b17"},
+ {file = "setuptools-65.5.1-py3-none-any.whl", hash = "sha256:d0b9a8433464d5800cbe05094acf5c6d52a91bfac9b52bcfc4d41382be5d5d31"},
+ {file = "setuptools-65.5.1.tar.gz", hash = "sha256:e197a19aa8ec9722928f2206f8de752def0e4c9fc6953527360d1c36d94ddb2f"},
]
six = [
{file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"},
@@ -1526,8 +1541,8 @@ urllib3 = [
{file = "urllib3-1.26.12.tar.gz", hash = "sha256:3fa96cf423e6987997fc326ae8df396db2a8b7c667747d47ddd8ecba91f4a74e"},
]
virtualenv = [
- {file = "virtualenv-20.16.6-py3-none-any.whl", hash = "sha256:186ca84254abcbde98180fd17092f9628c5fe742273c02724972a1d8a2035108"},
- {file = "virtualenv-20.16.6.tar.gz", hash = "sha256:530b850b523c6449406dfba859d6345e48ef19b8439606c5d74d7d3c9e14d76e"},
+ {file = "virtualenv-20.16.7-py3-none-any.whl", hash = "sha256:efd66b00386fdb7dbe4822d172303f40cd05e50e01740b19ea42425cbe653e29"},
+ {file = "virtualenv-20.16.7.tar.gz", hash = "sha256:8691e3ff9387f743e00f6bb20f70121f5e4f596cae754531f2b3b3a1b1ac696e"},
]
wrapt = [
{file = "wrapt-1.14.1-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:1b376b3f4896e7930f1f772ac4b064ac12598d1c38d04907e696cc4d794b43d3"},
diff --git a/python/pyiceberg/expressions/__init__.py b/python/pyiceberg/expressions/__init__.py
index 39d4884a51..d6ae395c17 100644
--- a/python/pyiceberg/expressions/__init__.py
+++ b/python/pyiceberg/expressions/__init__.py
@@ -18,18 +18,37 @@
from __future__ import annotations
from abc import ABC, abstractmethod
-from dataclasses import dataclass
from functools import reduce
-from typing import ClassVar, Generic, TypeVar
-
-from pyiceberg.expressions.literals import Literal
+from typing import (
+ Any,
+ Generic,
+ Iterable,
+ Set,
+ Type,
+ Union,
+)
+
+from pyiceberg.expressions.literals import Literal, literal
from pyiceberg.files import StructProtocol
from pyiceberg.schema import Accessor, Schema
+from pyiceberg.typedef import L
from pyiceberg.types import DoubleType, FloatType, NestedField
from pyiceberg.utils.singleton import Singleton
-T = TypeVar("T")
-B = TypeVar("B")
+
+def _to_unbound_term(term: Union[str, UnboundTerm]) -> UnboundTerm:
+ return Reference(term) if isinstance(term, str) else term
+
+
+def _to_literal_set(values: Union[Iterable[L], Iterable[Literal[L]]]) -> Set[Literal[L]]:
+ return {_to_literal(v) for v in values}
+
+
+def _to_literal(value: Union[L, Literal[L]]) -> Literal[L]:
+ if isinstance(value, Literal):
+ return value
+ else:
+ return literal(value)
class BooleanExpression(ABC):
@@ -40,7 +59,7 @@ class BooleanExpression(ABC):
"""Transform the Expression into its negated version."""
-class Term(Generic[T], ABC):
+class Term(Generic[L], ABC):
"""A simple expression that evaluates to a value"""
@@ -48,28 +67,28 @@ class Bound(ABC):
"""Represents a bound value expression"""
-class Unbound(Generic[B], ABC):
+class Unbound(ABC):
"""Represents an unbound value expression"""
+ @property
@abstractmethod
- def bind(self, schema: Schema, case_sensitive: bool = True) -> B:
- ... # pragma: no cover
+ def as_bound(self) -> Type[Bound]:
+ ...
-class BoundTerm(Term[T], Bound, ABC):
+class BoundTerm(Term[L], Bound, ABC):
"""Represents a bound term"""
@abstractmethod
- def ref(self) -> BoundReference[T]:
+ def ref(self) -> BoundReference[L]:
"""Returns the bound reference"""
@abstractmethod
- def eval(self, struct: StructProtocol) -> T: # pylint: disable=W0613
+ def eval(self, struct: StructProtocol) -> L: # pylint: disable=W0613
"""Returns the value at the referenced field's position in an object that abides by the StructProtocol"""
-@dataclass(frozen=True)
-class BoundReference(BoundTerm[T]):
+class BoundReference(BoundTerm[L]):
"""A reference bound to a field in a schema
Args:
@@ -80,7 +99,11 @@ class BoundReference(BoundTerm[T]):
field: NestedField
accessor: Accessor
- def eval(self, struct: StructProtocol) -> T:
+ def __init__(self, field: NestedField, accessor: Accessor):
+ self.field = field
+ self.accessor = accessor
+
+ def eval(self, struct: StructProtocol) -> L:
"""Returns the value at the referenced field's position in an object that abides by the StructProtocol
Args:
@@ -90,16 +113,25 @@ class BoundReference(BoundTerm[T]):
"""
return self.accessor.get(struct)
- def ref(self) -> BoundReference[T]:
+ def __eq__(self, other):
+ return self.field == other.field if isinstance(other, BoundReference) else False
+
+ def __repr__(self) -> str:
+ return f"BoundReference(field={repr(self.field)}, accessor={repr(self.accessor)})"
+
+ def ref(self) -> BoundReference[L]:
return self
-class UnboundTerm(Term[T], Unbound[BoundTerm[T]], ABC):
+class UnboundTerm(Term, Unbound, ABC):
"""Represents an unbound term."""
+ @abstractmethod
+ def bind(self, schema: Schema, case_sensitive: bool = True) -> BoundTerm:
+ ... # pragma: no cover
+
-@dataclass(frozen=True)
-class Reference(UnboundTerm[T]):
+class Reference(UnboundTerm):
"""A reference not yet bound to a field in a schema
Args:
@@ -111,7 +143,16 @@ class Reference(UnboundTerm[T]):
name: str
- def bind(self, schema: Schema, case_sensitive: bool = True) -> BoundReference[T]:
+ def __init__(self, name: str):
+ self.name = name
+
+ def __repr__(self):
+ return f"Reference(name={repr(self.name)})"
+
+ def __eq__(self, other):
+ return self.name == other.name if isinstance(other, Reference) else False
+
+ def bind(self, schema: Schema, case_sensitive: bool = True) -> BoundReference[L]:
"""Bind the reference to an Iceberg schema
Args:
@@ -126,10 +167,13 @@ class Reference(UnboundTerm[T]):
"""
field = schema.find_field(name_or_id=self.name, case_sensitive=case_sensitive)
accessor = schema.accessor_for_field(field.field_id)
- return BoundReference(field=field, accessor=accessor)
+ return self.as_bound(field=field, accessor=accessor)
+
+ @property
+ def as_bound(self) -> Type[BoundReference]:
+ return BoundReference[L]
-@dataclass(frozen=True, init=False)
class And(BooleanExpression):
"""AND operation expression - logical conjunction"""
@@ -146,16 +190,24 @@ class And(BooleanExpression):
elif right is AlwaysTrue():
return left
else:
- result = super().__new__(cls)
- object.__setattr__(result, "left", left)
- object.__setattr__(result, "right", right)
- return result
+ obj = super().__new__(cls)
+ obj.left = left
+ obj.right = right
+ return obj
+
+ def __eq__(self, other: Any) -> bool:
+ return self.left == other.left and self.right == other.right if isinstance(other, And) else False
+
+ def __str__(self) -> str:
+ return f"And(left={str(self.left)}, right={str(self.right)})"
+
+ def __repr__(self) -> str:
+ return f"And(left={repr(self.left)}, right={repr(self.right)})"
def __invert__(self) -> Or:
return Or(~self.left, ~self.right)
-@dataclass(frozen=True, init=False)
class Or(BooleanExpression):
"""OR operation expression - logical disjunction"""
@@ -172,16 +224,21 @@ class Or(BooleanExpression):
elif right is AlwaysFalse():
return left
else:
- result = super().__new__(cls)
- object.__setattr__(result, "left", left)
- object.__setattr__(result, "right", right)
- return result
+ obj = super().__new__(cls)
+ obj.left = left
+ obj.right = right
+ return obj
+
+ def __eq__(self, other: Any) -> bool:
+ return self.left == other.left and self.right == other.right if isinstance(other, Or) else False
+
+ def __repr__(self) -> str:
+ return f"Or(left={repr(self.left)}, right={repr(self.right)})"
def __invert__(self) -> And:
return And(~self.left, ~self.right)
-@dataclass(frozen=True, init=False)
class Not(BooleanExpression):
"""NOT operation expression - logical negation"""
@@ -194,85 +251,108 @@ class Not(BooleanExpression):
return AlwaysTrue()
elif isinstance(child, Not):
return child.child
- result = super().__new__(cls)
- object.__setattr__(result, "child", child)
- return result
+ obj = super().__new__(cls)
+ obj.child = child
+ return obj
+
+ def __repr__(self) -> str:
+ return f"Not(child={repr(self.child)})"
+
+ def __eq__(self, other: Any) -> bool:
+ return self.child == other.child if isinstance(other, Not) else False
def __invert__(self) -> BooleanExpression:
return self.child
-@dataclass(frozen=True)
class AlwaysTrue(BooleanExpression, Singleton):
"""TRUE expression"""
def __invert__(self) -> AlwaysFalse:
return AlwaysFalse()
+ def __str__(self):
+ return "AlwaysTrue()"
+
+ def __repr__(self):
+ return "AlwaysTrue()"
+
-@dataclass(frozen=True)
class AlwaysFalse(BooleanExpression, Singleton):
"""FALSE expression"""
def __invert__(self) -> AlwaysTrue:
return AlwaysTrue()
+ def __str__(self):
+ return "AlwaysFalse()"
+
+ def __repr__(self):
+ return "AlwaysFalse()"
+
-@dataclass(frozen=True)
-class BoundPredicate(Generic[T], Bound, BooleanExpression):
- term: BoundTerm[T]
+class BoundPredicate(Generic[L], Bound, BooleanExpression, ABC):
+ term: BoundTerm[L]
- def __invert__(self) -> BoundPredicate[T]:
- """Inverts the predicate"""
- raise NotImplementedError
+ def __init__(self, term: BoundTerm[L]):
+ self.term = term
+ def __eq__(self, other: Any) -> bool:
+ if isinstance(other, BoundPredicate):
+ return self.term == other.term
+ return False
-@dataclass(frozen=True)
-class UnboundPredicate(Generic[T], Unbound[BooleanExpression], BooleanExpression):
- as_bound: ClassVar[type]
- term: UnboundTerm[T]
- def __invert__(self) -> UnboundPredicate[T]:
- """Inverts the predicate"""
- raise NotImplementedError
+class UnboundPredicate(Generic[L], Unbound, BooleanExpression, ABC):
+ term: UnboundTerm
- def bind(self, schema: Schema, case_sensitive: bool = True) -> BooleanExpression:
- """Binds the predicate to a schema"""
- raise NotImplementedError
+ def __init__(self, term: Union[str, UnboundTerm]):
+ self.term = _to_unbound_term(term)
+ def __eq__(self, other):
+ return self.term == other.term if isinstance(other, UnboundPredicate) else False
-@dataclass(frozen=True)
-class UnaryPredicate(UnboundPredicate[T]):
- def bind(self, schema: Schema, case_sensitive: bool = True) -> BooleanExpression:
+ @abstractmethod
+ def bind(self, schema: Schema, case_sensitive: bool = True) -> BoundPredicate:
+ ...
+
+ @property
+ @abstractmethod
+ def as_bound(self) -> Type[BoundPredicate]:
+ ...
+
+
+class UnaryPredicate(UnboundPredicate[Any], ABC):
+ def bind(self, schema: Schema, case_sensitive: bool = True) -> BoundUnaryPredicate:
bound_term = self.term.bind(schema, case_sensitive)
return self.as_bound(bound_term)
- def __invert__(self) -> UnaryPredicate[T]:
- """Inverts the unary predicate"""
- raise NotImplementedError
+ def __repr__(self) -> str:
+ return f"{str(self.__class__.__name__)}(term={repr(self.term)})"
+
+ @property
+ @abstractmethod
+ def as_bound(self) -> Type[BoundUnaryPredicate[L]]:
+ ...
-@dataclass(frozen=True)
-class BoundUnaryPredicate(BoundPredicate[T]):
- def __invert__(self) -> BoundUnaryPredicate[T]:
- """Inverts the unary predicate"""
- raise NotImplementedError
+class BoundUnaryPredicate(BoundPredicate[L], ABC):
+ def __repr__(self) -> str:
+ return f"{str(self.__class__.__name__)}(term={repr(self.term)})"
-@dataclass(frozen=True)
-class BoundIsNull(BoundUnaryPredicate[T]):
- def __new__(cls, term: BoundTerm[T]): # pylint: disable=W0221
+class BoundIsNull(BoundUnaryPredicate[L]):
+ def __new__(cls, term: BoundTerm[L]): # pylint: disable=W0221
if term.ref().field.required:
return AlwaysFalse()
return super().__new__(cls)
- def __invert__(self) -> BoundNotNull[T]:
+ def __invert__(self) -> BoundNotNull[L]:
return BoundNotNull(self.term)
-@dataclass(frozen=True)
-class BoundNotNull(BoundUnaryPredicate[T]):
- def __new__(cls, term: BoundTerm[T]): # pylint: disable=W0221
+class BoundNotNull(BoundUnaryPredicate[L]):
+ def __new__(cls, term: BoundTerm[L]): # pylint: disable=W0221
if term.ref().field.required:
return AlwaysTrue()
return super().__new__(cls)
@@ -281,87 +361,114 @@ class BoundNotNull(BoundUnaryPredicate[T]):
return BoundIsNull(self.term)
-@dataclass(frozen=True)
-class IsNull(UnaryPredicate[T]):
- as_bound = BoundIsNull
-
- def __invert__(self) -> NotNull[T]:
+class IsNull(UnaryPredicate):
+ def __invert__(self) -> NotNull:
return NotNull(self.term)
+ @property
+ def as_bound(self) -> Type[BoundIsNull[L]]:
+ return BoundIsNull[L]
-@dataclass(frozen=True)
-class NotNull(UnaryPredicate[T]):
- as_bound = BoundNotNull
- def __invert__(self) -> IsNull[T]:
+class NotNull(UnaryPredicate):
+ def __invert__(self) -> IsNull:
return IsNull(self.term)
+ @property
+ def as_bound(self) -> Type[BoundNotNull[L]]:
+ return BoundNotNull[L]
+
-@dataclass(frozen=True)
-class BoundIsNaN(BoundUnaryPredicate[T]):
- def __new__(cls, term: BoundTerm[T]): # pylint: disable=W0221
+class BoundIsNaN(BoundUnaryPredicate[L]):
+ def __new__(cls, term: BoundTerm[L]): # pylint: disable=W0221
bound_type = term.ref().field.field_type
if type(bound_type) in {FloatType, DoubleType}:
return super().__new__(cls)
return AlwaysFalse()
- def __invert__(self) -> BoundNotNaN[T]:
+ def __invert__(self) -> BoundNotNaN[L]:
return BoundNotNaN(self.term)
-@dataclass(frozen=True)
-class BoundNotNaN(BoundUnaryPredicate[T]):
- def __new__(cls, term: BoundTerm[T]): # pylint: disable=W0221
+class BoundNotNaN(BoundUnaryPredicate[L]):
+ def __new__(cls, term: BoundTerm[L]): # pylint: disable=W0221
bound_type = term.ref().field.field_type
if type(bound_type) in {FloatType, DoubleType}:
return super().__new__(cls)
return AlwaysTrue()
- def __invert__(self) -> BoundIsNaN[T]:
+ def __invert__(self) -> BoundIsNaN[L]:
return BoundIsNaN(self.term)
-@dataclass(frozen=True)
-class IsNaN(UnaryPredicate[T]):
- as_bound = BoundIsNaN
-
- def __invert__(self) -> NotNaN[T]:
+class IsNaN(UnaryPredicate):
+ def __invert__(self) -> NotNaN:
return NotNaN(self.term)
+ @property
+ def as_bound(self) -> Type[BoundIsNaN[L]]:
+ return BoundIsNaN[L]
-@dataclass(frozen=True)
-class NotNaN(UnaryPredicate[T]):
- as_bound = BoundNotNaN
- def __invert__(self) -> IsNaN[T]:
+class NotNaN(UnaryPredicate):
+ def __invert__(self) -> IsNaN:
return IsNaN(self.term)
+ @property
+ def as_bound(self) -> Type[BoundNotNaN[L]]:
+ return BoundNotNaN[L]
+
-@dataclass(frozen=True)
-class SetPredicate(UnboundPredicate[T]):
- literals: tuple[Literal[T], ...]
+class SetPredicate(Generic[L], UnboundPredicate[L], ABC):
+ literals: Set[Literal[L]]
- def __invert__(self) -> SetPredicate[T]:
- """Inverted expression of the SetPredicate"""
- raise NotImplementedError
+ def __init__(self, term: Union[str, UnboundTerm], literals: Union[Iterable[L], Iterable[Literal[L]]]):
+ super().__init__(term)
+ self.literals = _to_literal_set(literals)
- def bind(self, schema: Schema, case_sensitive: bool = True) -> BooleanExpression:
+ def bind(self, schema: Schema, case_sensitive: bool = True) -> BoundSetPredicate[L]:
bound_term = self.term.bind(schema, case_sensitive)
return self.as_bound(bound_term, {lit.to(bound_term.ref().field.field_type) for lit in self.literals})
+ def __str__(self):
+ # Sort to make it deterministic
+ return f"{str(self.__class__.__name__)}({str(self.term)}, {{{', '.join(sorted([str(literal) for literal in self.literals]))}}})"
+
+ def __repr__(self) -> str:
+ # Sort to make it deterministic
+ return f"{str(self.__class__.__name__)}({repr(self.term)}, {{{', '.join(sorted([repr(literal) for literal in self.literals]))}}})"
+
+ def __eq__(self, other: Any) -> bool:
+ return self.term == other.term and self.literals == other.literals if isinstance(other, SetPredicate) else False
+
+ @property
+ @abstractmethod
+ def as_bound(self) -> Type[BoundSetPredicate[L]]:
+ return BoundSetPredicate[L]
+
+
+class BoundSetPredicate(BoundPredicate[L], ABC):
+ literals: Set[Literal[L]]
+
+ def __init__(self, term: BoundTerm[L], literals: Set[Literal[L]]):
+ # Since we don't know the type of BoundPredicate[L], we have to ignore this one
+ super().__init__(term) # type: ignore
+ self.literals = _to_literal_set(literals) # pylint: disable=W0621
-@dataclass(frozen=True)
-class BoundSetPredicate(BoundPredicate[T]):
- literals: set[Literal[T]]
+ def __str__(self):
+ # Sort to make it deterministic
+ return f"{str(self.__class__.__name__)}({str(self.term)}, {{{', '.join(sorted([str(literal) for literal in self.literals]))}}})"
- def __invert__(self) -> BoundSetPredicate[T]:
- """Inverted expression of the SetPredicate"""
- raise NotImplementedError
+ def __repr__(self) -> str:
+ # Sort to make it deterministic
+ return f"{str(self.__class__.__name__)}({repr(self.term)}, {{{', '.join(sorted([repr(literal) for literal in self.literals]))}}})"
+ def __eq__(self, other: Any) -> bool:
+ return self.term == other.term and self.literals == other.literals if isinstance(other, BoundSetPredicate) else False
-@dataclass(frozen=True)
-class BoundIn(BoundSetPredicate[T]):
- def __new__(cls, term: BoundTerm[T], literals: set[Literal[T]]): # pylint: disable=W0221
+
+class BoundIn(BoundSetPredicate[L]):
+ def __new__(cls, term: BoundTerm[L], literals: Set[Literal[L]]): # pylint: disable=W0221
count = len(literals)
if count == 0:
return AlwaysFalse()
@@ -370,13 +477,19 @@ class BoundIn(BoundSetPredicate[T]):
else:
return super().__new__(cls)
- def __invert__(self) -> BoundNotIn[T]:
+ def __invert__(self) -> BoundNotIn[L]:
return BoundNotIn(self.term, self.literals)
+ def __eq__(self, other: Any) -> bool:
+ return self.term == other.term and self.literals == other.literals if isinstance(other, BoundIn) else False
+
-@dataclass(frozen=True)
-class BoundNotIn(BoundSetPredicate[T]):
- def __new__(cls, term: BoundTerm[T], literals: set[Literal[T]]): # pylint: disable=W0221
+class BoundNotIn(BoundSetPredicate[L]):
+ def __new__( # pylint: disable=W0221
+ cls,
+ term: BoundTerm[L],
+ literals: Set[Literal[L]],
+ ):
count = len(literals)
if count == 0:
return AlwaysTrue()
@@ -385,145 +498,174 @@ class BoundNotIn(BoundSetPredicate[T]):
else:
return super().__new__(cls)
- def __invert__(self) -> BoundIn[T]:
+ def __invert__(self) -> BoundIn[L]:
return BoundIn(self.term, self.literals)
-@dataclass(frozen=True)
-class In(SetPredicate[T]):
- as_bound = BoundIn
-
- def __new__(cls, term: UnboundTerm[T], literals: tuple[Literal[T], ...]): # pylint: disable=W0221
- count = len(literals)
+class In(SetPredicate[L]):
+ def __new__(cls, term: Union[str, UnboundTerm], literals: Union[Iterable[L], Iterable[Literal[L]]]): # pylint: disable=W0221
+ literals_set: Set[Literal[L]] = _to_literal_set(literals)
+ count = len(literals_set)
if count == 0:
return AlwaysFalse()
elif count == 1:
- return EqualTo(term, literals[0])
+ return EqualTo(term, next(iter(literals)))
else:
return super().__new__(cls)
- def __invert__(self) -> NotIn[T]:
- return NotIn(self.term, self.literals)
+ def __invert__(self) -> NotIn:
+ return NotIn[L](self.term, self.literals)
+ @property
+ def as_bound(self) -> Type[BoundIn[L]]:
+ return BoundIn[L]
-@dataclass(frozen=True)
-class NotIn(SetPredicate[T]):
- as_bound = BoundNotIn
- def __new__(cls, term: UnboundTerm[T], literals: tuple[Literal[T], ...]): # pylint: disable=W0221
- count = len(literals)
+class NotIn(SetPredicate[L], ABC):
+ def __new__(cls, term: Union[str, UnboundTerm], literals: Union[Iterable[L], Iterable[Literal[L]]]): # pylint: disable=W0221
+ literals_set: Set[Literal[L]] = _to_literal_set(literals)
+ count = len(literals_set)
if count == 0:
return AlwaysTrue()
elif count == 1:
- return NotEqualTo(term, literals[0])
+ return NotEqualTo(term, next(iter(literals_set)))
else:
return super().__new__(cls)
- def __invert__(self) -> In[T]:
- return In(self.term, self.literals)
+ def __invert__(self) -> In:
+ return In[L](self.term, self.literals)
+
+ def __eq__(self, other: Any) -> bool:
+ if isinstance(other, NotIn):
+ return self.term == other.term and self.literals == other.literals
+ return False
+
+ @property
+ def as_bound(self) -> Type[BoundNotIn[L]]:
+ return BoundNotIn[L]
+
+class LiteralPredicate(Generic[L], UnboundPredicate[L], ABC):
+ literal: Literal[L]
-@dataclass(frozen=True)
-class LiteralPredicate(UnboundPredicate[T]):
- literal: Literal[T]
+ def __init__(self, term: Union[str, UnboundTerm], literal: Union[L, Literal[L]]): # pylint: disable=W0621
+ super().__init__(term)
+ self.literal = _to_literal(literal) # pylint: disable=W0621
- def bind(self, schema: Schema, case_sensitive: bool = True) -> BooleanExpression:
+ def bind(self, schema: Schema, case_sensitive: bool = True) -> BoundLiteralPredicate[L]:
bound_term = self.term.bind(schema, case_sensitive)
return self.as_bound(bound_term, self.literal.to(bound_term.ref().field.field_type))
- def __invert__(self) -> LiteralPredicate[T]:
- """Inverts the literal predicate"""
- raise NotImplementedError
+ def __eq__(self, other):
+ if isinstance(other, LiteralPredicate):
+ return self.term == other.term and self.literal == other.literal
+ return False
+ def __repr__(self) -> str:
+ return f"{str(self.__class__.__name__)}(term={repr(self.term)}, literal={repr(self.literal)})"
-@dataclass(frozen=True)
-class BoundLiteralPredicate(BoundPredicate[T]):
- literal: Literal[T]
+ @property
+ @abstractmethod
+ def as_bound(self) -> Type[BoundLiteralPredicate[L]]:
+ ...
+
+
+class BoundLiteralPredicate(BoundPredicate[L], ABC):
+ literal: Literal[L]
+
+ def __init__(self, term: BoundTerm[L], literal: Literal[L]): # pylint: disable=W0621
+ # Since we don't know the type of BoundPredicate[L], we have to ignore this one
+ super().__init__(term) # type: ignore
+ self.literal = literal # pylint: disable=W0621
- def __invert__(self) -> BoundLiteralPredicate[T]:
- """Inverts the bound literal predicate"""
- raise NotImplementedError
+ def __eq__(self, other):
+ if isinstance(other, BoundLiteralPredicate):
+ return self.term == other.term and self.literal == other.literal
+ return False
+ def __repr__(self) -> str:
+ return f"{str(self.__class__.__name__)}(term={repr(self.term)}, literal={repr(self.literal)})"
-@dataclass(frozen=True)
-class BoundEqualTo(BoundLiteralPredicate[T]):
- def __invert__(self) -> BoundNotEqualTo[T]:
+
+class BoundEqualTo(BoundLiteralPredicate[L]):
+ def __invert__(self) -> BoundNotEqualTo[L]:
return BoundNotEqualTo(self.term, self.literal)
-@dataclass(frozen=True)
-class BoundNotEqualTo(BoundLiteralPredicate[T]):
- def __invert__(self) -> BoundEqualTo[T]:
+class BoundNotEqualTo(BoundLiteralPredicate[L]):
+ def __invert__(self) -> BoundEqualTo[L]:
return BoundEqualTo(self.term, self.literal)
-@dataclass(frozen=True)
-class BoundGreaterThanOrEqual(BoundLiteralPredicate[T]):
- def __invert__(self) -> BoundLessThan[T]:
+class BoundGreaterThanOrEqual(BoundLiteralPredicate[L]):
+ def __invert__(self) -> BoundLessThan[L]:
return BoundLessThan(self.term, self.literal)
-@dataclass(frozen=True)
-class BoundGreaterThan(BoundLiteralPredicate[T]):
- def __invert__(self) -> BoundLessThanOrEqual[T]:
+class BoundGreaterThan(BoundLiteralPredicate[L]):
+ def __invert__(self) -> BoundLessThanOrEqual[L]:
return BoundLessThanOrEqual(self.term, self.literal)
-@dataclass(frozen=True)
-class BoundLessThan(BoundLiteralPredicate[T]):
- def __invert__(self) -> BoundGreaterThanOrEqual[T]:
+class BoundLessThan(BoundLiteralPredicate[L]):
+ def __invert__(self) -> BoundGreaterThanOrEqual[L]:
return BoundGreaterThanOrEqual(self.term, self.literal)
-@dataclass(frozen=True)
-class BoundLessThanOrEqual(BoundLiteralPredicate[T]):
- def __invert__(self) -> BoundGreaterThan[T]:
+class BoundLessThanOrEqual(BoundLiteralPredicate[L]):
+ def __invert__(self) -> BoundGreaterThan[L]:
return BoundGreaterThan(self.term, self.literal)
-@dataclass(frozen=True)
-class EqualTo(LiteralPredicate[T]):
- as_bound = BoundEqualTo
-
- def __invert__(self) -> NotEqualTo[T]:
+class EqualTo(LiteralPredicate[L]):
+ def __invert__(self) -> NotEqualTo:
return NotEqualTo(self.term, self.literal)
+ @property
+ def as_bound(self) -> Type[BoundEqualTo[L]]:
+ return BoundEqualTo[L]
-@dataclass(frozen=True)
-class NotEqualTo(LiteralPredicate[T]):
- as_bound = BoundNotEqualTo
- def __invert__(self) -> EqualTo[T]:
+class NotEqualTo(LiteralPredicate[L]):
+ def __invert__(self) -> EqualTo:
return EqualTo(self.term, self.literal)
+ @property
+ def as_bound(self) -> Type[BoundNotEqualTo[L]]:
+ return BoundNotEqualTo[L]
-@dataclass(frozen=True)
-class LessThan(LiteralPredicate[T]):
- as_bound = BoundLessThan
- def __invert__(self) -> GreaterThanOrEqual[T]:
+class LessThan(LiteralPredicate):
+ def __invert__(self) -> GreaterThanOrEqual:
return GreaterThanOrEqual(self.term, self.literal)
+ @property
+ def as_bound(self) -> Type[BoundLessThan[L]]:
+ return BoundLessThan[L]
-@dataclass(frozen=True)
-class GreaterThanOrEqual(LiteralPredicate[T]):
- as_bound = BoundGreaterThanOrEqual
- def __invert__(self) -> LessThan[T]:
+class GreaterThanOrEqual(LiteralPredicate[L]):
+ def __invert__(self) -> LessThan:
return LessThan(self.term, self.literal)
+ @property
+ def as_bound(self) -> Type[BoundGreaterThanOrEqual[L]]:
+ return BoundGreaterThanOrEqual[L]
-@dataclass(frozen=True)
-class GreaterThan(LiteralPredicate[T]):
- as_bound = BoundGreaterThan
- def __invert__(self) -> LessThanOrEqual[T]:
+class GreaterThan(LiteralPredicate[L]):
+ def __invert__(self) -> LessThanOrEqual:
return LessThanOrEqual(self.term, self.literal)
+ @property
+ def as_bound(self) -> Type[BoundGreaterThan[L]]:
+ return BoundGreaterThan[L]
-@dataclass(frozen=True)
-class LessThanOrEqual(LiteralPredicate[T]):
- as_bound = BoundLessThanOrEqual
- def __invert__(self) -> GreaterThan[T]:
+class LessThanOrEqual(LiteralPredicate[L]):
+ def __invert__(self) -> GreaterThan:
return GreaterThan(self.term, self.literal)
+
+ @property
+ def as_bound(self) -> Type[BoundLessThanOrEqual[L]]:
+ return BoundLessThanOrEqual[L]
diff --git a/python/pyiceberg/expressions/literals.py b/python/pyiceberg/expressions/literals.py
index a84cd9ae39..ada6fcc8eb 100644
--- a/python/pyiceberg/expressions/literals.py
+++ b/python/pyiceberg/expressions/literals.py
@@ -23,17 +23,12 @@ from __future__ import annotations
import struct
from abc import ABC, abstractmethod
-from datetime import date
from decimal import ROUND_HALF_UP, Decimal
-from functools import singledispatch, singledispatchmethod
-from typing import (
- Any,
- Generic,
- Type,
- TypeVar,
-)
+from functools import singledispatchmethod
+from typing import Any, Generic, Type
from uuid import UUID
+from pyiceberg.typedef import L
from pyiceberg.types import (
BinaryType,
BooleanType,
@@ -53,7 +48,6 @@ from pyiceberg.types import (
)
from pyiceberg.utils.datetime import (
date_str_to_days,
- date_to_days,
micros_to_days,
time_to_micros,
timestamp_to_micros,
@@ -61,19 +55,19 @@ from pyiceberg.utils.datetime import (
)
from pyiceberg.utils.singleton import Singleton
-T = TypeVar("T")
-
-class Literal(Generic[T], ABC):
+class Literal(Generic[L], ABC):
"""Literal which has a value and can be converted between types"""
- def __init__(self, value: T, value_type: Type):
+ _value: L
+
+ def __init__(self, value: L, value_type: Type[L]):
if value is None or not isinstance(value, value_type):
- raise TypeError(f"Invalid literal value: {value} (not a {value_type})")
+ raise TypeError(f"Invalid literal value: {value!r} (not a {value_type})")
self._value = value
@property
- def value(self) -> T:
+ def value(self) -> L:
return self._value
@singledispatchmethod
@@ -82,7 +76,7 @@ class Literal(Generic[T], ABC):
... # pragma: no cover
def __repr__(self) -> str:
- return f"{type(self).__name__}({self.value})"
+ return f"{type(self).__name__}({self.value!r})"
def __str__(self) -> str:
return str(self.value)
@@ -90,7 +84,7 @@ class Literal(Generic[T], ABC):
def __hash__(self) -> int:
return hash(self.value)
- def __eq__(self, other) -> bool:
+ def __eq__(self, other: Any) -> bool:
return self.value == other.value
def __ne__(self, other) -> bool:
@@ -109,11 +103,9 @@ class Literal(Generic[T], ABC):
return self.value >= other.value
-@singledispatch
-def literal(value: Any) -> Literal:
+def literal(value: L) -> Literal[L]:
"""
A generic Literal factory to construct an iceberg Literal based on python primitive data type
- using dynamic overloading
Args:
value(python primitive type): the value to be associated with literal
@@ -123,54 +115,22 @@ def literal(value: Any) -> Literal:
>>> literal(123)
LongLiteral(123)
"""
- raise TypeError(f"Invalid literal value: {repr(value)}")
-
-
-@literal.register(bool)
-def _(value: bool) -> Literal[bool]:
- return BooleanLiteral(value)
-
-
-@literal.register(int)
-def _(value: int) -> Literal[int]:
- return LongLiteral(value)
-
-
-@literal.register(float)
-def _(value: float) -> Literal[float]:
- # expression binding can convert to FloatLiteral if needed
- return DoubleLiteral(value)
-
-
-@literal.register(str)
-def _(value: str) -> Literal[str]:
- return StringLiteral(value)
-
-
-@literal.register(UUID)
-def _(value: UUID) -> Literal[UUID]:
- return UUIDLiteral(value)
-
-
-@literal.register(bytes)
-def _(value: bytes) -> Literal[bytes]:
- # expression binding can convert to FixedLiteral if needed
- return BinaryLiteral(value)
-
-
-@literal.register(bytearray)
-def _(value: bytearray) -> Literal[bytes]:
- return BinaryLiteral(bytes(value))
-
-
-@literal.register(Decimal)
-def _(value: Decimal) -> Literal[Decimal]:
- return DecimalLiteral(value)
-
-
-@literal.register(date)
-def _(value: date) -> Literal[int]:
- return DateLiteral(date_to_days(value))
+ if isinstance(value, float):
+ return DoubleLiteral(value)
+ elif isinstance(value, bool):
+ return BooleanLiteral(value) # type: ignore
+ elif isinstance(value, int):
+ return LongLiteral(value)
+ elif isinstance(value, str):
+ return StringLiteral(value)
+ elif isinstance(value, UUID):
+ return UUIDLiteral(value)
+ elif isinstance(value, bytes):
+ return BinaryLiteral(value)
+ elif isinstance(value, Decimal):
+ return DecimalLiteral(value)
+ else:
+ raise TypeError(f"Invalid literal value: {repr(value)}")
class FloatAboveMax(Literal[float], Singleton):
@@ -481,6 +441,9 @@ class StringLiteral(Literal[str]):
f"Could not convert {self.value} into a {type_var}, scales differ {type_var.scale} <> {abs(dec.as_tuple().exponent)}"
)
+ def __repr__(self) -> str:
+ return f"literal({repr(self.value)})"
+
class UUIDLiteral(Literal[UUID]):
def __init__(self, value: UUID):
diff --git a/python/pyiceberg/expressions/visitors.py b/python/pyiceberg/expressions/visitors.py
index 4c6df0b079..283e7d2317 100644
--- a/python/pyiceberg/expressions/visitors.py
+++ b/python/pyiceberg/expressions/visitors.py
@@ -17,11 +17,11 @@
from abc import ABC, abstractmethod
from functools import singledispatch
from typing import (
- Any,
Callable,
Generic,
List,
Set,
+ TypeVar,
)
from pyiceberg.conversions import from_bytes
@@ -44,9 +44,9 @@ from pyiceberg.expressions import (
BoundNotNull,
BoundPredicate,
BoundTerm,
+ L,
Not,
Or,
- T,
UnboundPredicate,
)
from pyiceberg.expressions.literals import Literal
@@ -60,6 +60,8 @@ from pyiceberg.types import (
PrimitiveType,
)
+T = TypeVar("T")
+
class BooleanExpressionVisitor(Generic[T], ABC):
@abstractmethod
@@ -89,8 +91,8 @@ class BooleanExpressionVisitor(Generic[T], ABC):
"""Visit method for an And boolean expression
Args:
- left_result (T): The result of visiting the left side of the expression
- right_result (T): The result of visiting the right side of the expression
+ left_result (R): The result of visiting the left side of the expression
+ right_result (R): The result of visiting the right side of the expression
"""
@abstractmethod
@@ -98,12 +100,12 @@ class BooleanExpressionVisitor(Generic[T], ABC):
"""Visit method for an Or boolean expression
Args:
- left_result (T): The result of visiting the left side of the expression
- right_result (T): The result of visiting the right side of the expression
+ left_result (R): The result of visiting the left side of the expression
+ right_result (R): The result of visiting the right side of the expression
"""
@abstractmethod
- def visit_unbound_predicate(self, predicate) -> T:
+ def visit_unbound_predicate(self, predicate: UnboundPredicate) -> T:
"""Visit method for an unbound predicate in an expression tree
Args:
@@ -111,11 +113,11 @@ class BooleanExpressionVisitor(Generic[T], ABC):
"""
@abstractmethod
- def visit_bound_predicate(self, predicate) -> T:
+ def visit_bound_predicate(self, predicate: BoundPredicate[L]) -> T:
"""Visit method for a bound predicate in an expression tree
Args:
- predicate (BoundPredicate): An instance of a BoundPredicate
+ predicate (BoundPredicate[L]): An instance of a BoundPredicate
"""
@@ -127,7 +129,7 @@ def visit(obj, visitor: BooleanExpressionVisitor[T]) -> T:
Args:
obj(BooleanExpression): An instance of a BooleanExpression
- visitor(BooleanExpressionVisitor[T]): An instance of an implementation of the generic BooleanExpressionVisitor base class
+ visitor(BooleanExpressionVisitor[R]): An instance of an implementation of the generic BooleanExpressionVisitor base class
Raises:
NotImplementedError: If attempting to visit an unsupported expression
@@ -135,26 +137,26 @@ def visit(obj, visitor: BooleanExpressionVisitor[T]) -> T:
raise NotImplementedError(f"Cannot visit unsupported expression: {obj}")
-@visit.register
+@visit.register(AlwaysTrue)
def _(_: AlwaysTrue, visitor: BooleanExpressionVisitor[T]) -> T:
"""Visit an AlwaysTrue boolean expression with a concrete BooleanExpressionVisitor"""
return visitor.visit_true()
-@visit.register
+@visit.register(AlwaysFalse)
def _(_: AlwaysFalse, visitor: BooleanExpressionVisitor[T]) -> T:
"""Visit an AlwaysFalse boolean expression with a concrete BooleanExpressionVisitor"""
return visitor.visit_false()
-@visit.register
+@visit.register(Not)
def _(obj: Not, visitor: BooleanExpressionVisitor[T]) -> T:
"""Visit a Not boolean expression with a concrete BooleanExpressionVisitor"""
child_result: T = visit(obj.child, visitor=visitor)
return visitor.visit_not(child_result=child_result)
-@visit.register
+@visit.register(And)
def _(obj: And, visitor: BooleanExpressionVisitor[T]) -> T:
"""Visit an And boolean expression with a concrete BooleanExpressionVisitor"""
left_result: T = visit(obj.left, visitor=visitor)
@@ -162,19 +164,19 @@ def _(obj: And, visitor: BooleanExpressionVisitor[T]) -> T:
return visitor.visit_and(left_result=left_result, right_result=right_result)
-@visit.register
+@visit.register(UnboundPredicate)
def _(obj: UnboundPredicate, visitor: BooleanExpressionVisitor[T]) -> T:
"""Visit an unbound boolean expression with a concrete BooleanExpressionVisitor"""
return visitor.visit_unbound_predicate(predicate=obj)
-@visit.register
-def _(obj: BoundPredicate, visitor: BooleanExpressionVisitor[T]) -> T:
+@visit.register(BoundPredicate)
+def _(obj: BoundPredicate[L], visitor: BooleanExpressionVisitor[T]) -> T:
"""Visit a bound boolean expression with a concrete BooleanExpressionVisitor"""
return visitor.visit_bound_predicate(predicate=obj)
-@visit.register
+@visit.register(Or)
def _(obj: Or, visitor: BooleanExpressionVisitor[T]) -> T:
"""Visit an Or boolean expression with a concrete BooleanExpressionVisitor"""
left_result: T = visit(obj.left, visitor=visitor)
@@ -232,57 +234,57 @@ class BindVisitor(BooleanExpressionVisitor[BooleanExpression]):
def visit_unbound_predicate(self, predicate: UnboundPredicate) -> BooleanExpression:
return predicate.bind(self.schema, case_sensitive=self.case_sensitive)
- def visit_bound_predicate(self, predicate: BoundPredicate) -> BooleanExpression:
+ def visit_bound_predicate(self, predicate: BoundPredicate[L]) -> BooleanExpression:
raise TypeError(f"Found already bound predicate: {predicate}")
class BoundBooleanExpressionVisitor(BooleanExpressionVisitor[T], ABC):
@abstractmethod
- def visit_in(self, term: BoundTerm[T], literals: Set[Literal[Any]]) -> T:
+ def visit_in(self, term: BoundTerm[L], literals: Set[Literal[L]]) -> T:
"""Visit a bound In predicate"""
@abstractmethod
- def visit_not_in(self, term: BoundTerm[T], literals: Set[Literal[Any]]) -> T:
+ def visit_not_in(self, term: BoundTerm[L], literals: Set[Literal[L]]) -> T:
"""Visit a bound NotIn predicate"""
@abstractmethod
- def visit_is_nan(self, term: BoundTerm[T]) -> T:
+ def visit_is_nan(self, term: BoundTerm[L]) -> T:
"""Visit a bound IsNan predicate"""
@abstractmethod
- def visit_not_nan(self, term: BoundTerm[T]) -> T:
+ def visit_not_nan(self, term: BoundTerm[L]) -> T:
"""Visit a bound NotNan predicate"""
@abstractmethod
- def visit_is_null(self, term: BoundTerm[T]) -> T:
+ def visit_is_null(self, term: BoundTerm[L]) -> T:
"""Visit a bound IsNull predicate"""
@abstractmethod
- def visit_not_null(self, term: BoundTerm[T]) -> T:
+ def visit_not_null(self, term: BoundTerm[L]) -> T:
"""Visit a bound NotNull predicate"""
@abstractmethod
- def visit_equal(self, term: BoundTerm[T], literal: Literal[Any]) -> T:
+ def visit_equal(self, term: BoundTerm[L], literal: Literal[L]) -> T:
"""Visit a bound Equal predicate"""
@abstractmethod
- def visit_not_equal(self, term: BoundTerm[T], literal: Literal[Any]) -> T:
+ def visit_not_equal(self, term: BoundTerm[L], literal: Literal[L]) -> T:
"""Visit a bound NotEqual predicate"""
@abstractmethod
- def visit_greater_than_or_equal(self, term: BoundTerm[T], literal: Literal[Any]) -> T:
+ def visit_greater_than_or_equal(self, term: BoundTerm[L], literal: Literal[L]) -> T:
"""Visit a bound GreaterThanOrEqual predicate"""
@abstractmethod
- def visit_greater_than(self, term: BoundTerm[T], literal: Literal[Any]) -> T:
+ def visit_greater_than(self, term: BoundTerm[L], literal: Literal[L]) -> T:
"""Visit a bound GreaterThan predicate"""
@abstractmethod
- def visit_less_than(self, term: BoundTerm[T], literal: Literal[Any]) -> T:
+ def visit_less_than(self, term: BoundTerm[L], literal: Literal[L]) -> T:
"""Visit a bound LessThan predicate"""
@abstractmethod
- def visit_less_than_or_equal(self, term: BoundTerm[T], literal: Literal[Any]) -> T:
+ def visit_less_than_or_equal(self, term: BoundTerm[L], literal: Literal[L]) -> T:
"""Visit a bound LessThanOrEqual predicate"""
@abstractmethod
@@ -305,86 +307,86 @@ class BoundBooleanExpressionVisitor(BooleanExpressionVisitor[T], ABC):
def visit_or(self, left_result: T, right_result: T) -> T:
"""Visit a bound Or predicate"""
- def visit_unbound_predicate(self, predicate: UnboundPredicate[T]):
+ def visit_unbound_predicate(self, predicate: UnboundPredicate):
"""Visit an unbound predicate
Args:
- predicate (UnboundPredicate[T]): An unbound predicate
+ predicate (UnboundPredicate): An unbound predicate
Raises:
TypeError: This always raises since an unbound predicate is not expected in a bound boolean expression
"""
raise TypeError(f"Not a bound predicate: {predicate}")
- def visit_bound_predicate(self, predicate: BoundPredicate[T]) -> T:
+ def visit_bound_predicate(self, predicate: BoundPredicate[L]) -> T:
"""Visit a bound predicate
Args:
- predicate (BoundPredicate[T]): A bound predicate
+ predicate (BoundPredicate[L]): A bound predicate
"""
return visit_bound_predicate(predicate, self)
@singledispatch
-def visit_bound_predicate(expr, _: BooleanExpressionVisitor[T]) -> T:
+def visit_bound_predicate(expr: BoundPredicate[L], _: BooleanExpressionVisitor[T]) -> T:
raise TypeError(f"Unknown predicate: {expr}")
@visit_bound_predicate.register(BoundIn)
-def _(expr: BoundIn, visitor: BoundBooleanExpressionVisitor[T]) -> T:
+def _(expr: BoundIn[L], visitor: BoundBooleanExpressionVisitor[T]) -> T:
return visitor.visit_in(term=expr.term, literals=expr.literals)
@visit_bound_predicate.register(BoundNotIn)
-def _(expr: BoundNotIn, visitor: BoundBooleanExpressionVisitor[T]) -> T:
+def _(expr: BoundNotIn[L], visitor: BoundBooleanExpressionVisitor[T]) -> T:
return visitor.visit_not_in(term=expr.term, literals=expr.literals)
@visit_bound_predicate.register(BoundIsNaN)
-def _(expr: BoundIsNaN, visitor: BoundBooleanExpressionVisitor[T]) -> T:
+def _(expr: BoundIsNaN[L], visitor: BoundBooleanExpressionVisitor[T]) -> T:
return visitor.visit_is_nan(term=expr.term)
@visit_bound_predicate.register(BoundNotNaN)
-def _(expr: BoundNotNaN, visitor: BoundBooleanExpressionVisitor[T]) -> T:
+def _(expr: BoundNotNaN[L], visitor: BoundBooleanExpressionVisitor[T]) -> T:
return visitor.visit_not_nan(term=expr.term)
@visit_bound_predicate.register(BoundIsNull)
-def _(expr: BoundIsNull, visitor: BoundBooleanExpressionVisitor[T]) -> T:
+def _(expr: BoundIsNull[L], visitor: BoundBooleanExpressionVisitor[T]) -> T:
return visitor.visit_is_null(term=expr.term)
@visit_bound_predicate.register(BoundNotNull)
-def _(expr: BoundNotNull, visitor: BoundBooleanExpressionVisitor[T]) -> T:
+def _(expr: BoundNotNull[L], visitor: BoundBooleanExpressionVisitor[T]) -> T:
return visitor.visit_not_null(term=expr.term)
@visit_bound_predicate.register(BoundEqualTo)
-def _(expr: BoundEqualTo, visitor: BoundBooleanExpressionVisitor[T]) -> T:
+def _(expr: BoundEqualTo[L], visitor: BoundBooleanExpressionVisitor[T]) -> T:
return visitor.visit_equal(term=expr.term, literal=expr.literal)
@visit_bound_predicate.register(BoundNotEqualTo)
-def _(expr: BoundNotEqualTo, visitor: BoundBooleanExpressionVisitor[T]) -> T:
+def _(expr: BoundNotEqualTo[L], visitor: BoundBooleanExpressionVisitor[T]) -> T:
return visitor.visit_not_equal(term=expr.term, literal=expr.literal)
@visit_bound_predicate.register(BoundGreaterThanOrEqual)
-def _(expr: BoundGreaterThanOrEqual, visitor: BoundBooleanExpressionVisitor[T]) -> T:
+def _(expr: BoundGreaterThanOrEqual[L], visitor: BoundBooleanExpressionVisitor[T]) -> T:
"""Visit a bound GreaterThanOrEqual predicate"""
return visitor.visit_greater_than_or_equal(term=expr.term, literal=expr.literal)
@visit_bound_predicate.register(BoundGreaterThan)
-def _(expr: BoundGreaterThan, visitor: BoundBooleanExpressionVisitor[T]) -> T:
+def _(expr: BoundGreaterThan[L], visitor: BoundBooleanExpressionVisitor[T]) -> T:
return visitor.visit_greater_than(term=expr.term, literal=expr.literal)
@visit_bound_predicate.register(BoundLessThan)
-def _(expr: BoundLessThan, visitor: BoundBooleanExpressionVisitor[T]) -> T:
+def _(expr: BoundLessThan[L], visitor: BoundBooleanExpressionVisitor[T]) -> T:
return visitor.visit_less_than(term=expr.term, literal=expr.literal)
@visit_bound_predicate.register(BoundLessThanOrEqual)
-def _(expr: BoundLessThanOrEqual, visitor: BoundBooleanExpressionVisitor[T]) -> T:
+def _(expr: BoundLessThanOrEqual[L], visitor: BoundBooleanExpressionVisitor[T]) -> T:
return visitor.visit_less_than_or_equal(term=expr.term, literal=expr.literal)
@@ -410,10 +412,10 @@ class _RewriteNotVisitor(BooleanExpressionVisitor[BooleanExpression]):
def visit_or(self, left_result: BooleanExpression, right_result: BooleanExpression) -> BooleanExpression:
return Or(left=left_result, right=right_result)
- def visit_unbound_predicate(self, predicate) -> BooleanExpression:
+ def visit_unbound_predicate(self, predicate: UnboundPredicate) -> BooleanExpression:
return predicate
- def visit_bound_predicate(self, predicate) -> BooleanExpression:
+ def visit_bound_predicate(self, predicate: BoundPredicate[L]) -> BooleanExpression:
return predicate
@@ -443,7 +445,7 @@ class _ManifestEvalVisitor(BoundBooleanExpressionVisitor[bool]):
# No partition information
return ROWS_MIGHT_MATCH
- def visit_in(self, term: BoundTerm, literals: Set[Literal[Any]]) -> bool:
+ def visit_in(self, term: BoundTerm[L], literals: Set[Literal[L]]) -> bool:
pos = term.ref().accessor.position
field = self.partition_fields[pos]
@@ -465,12 +467,12 @@ class _ManifestEvalVisitor(BoundBooleanExpressionVisitor[bool]):
return ROWS_MIGHT_MATCH
- def visit_not_in(self, term: BoundTerm, literals: Set[Literal[Any]]) -> bool:
+ def visit_not_in(self, term: BoundTerm[L], literals: Set[Literal[L]]) -> bool:
# because the bounds are not necessarily a min or max value, this cannot be answered using
# them. notIn(col, {X, ...}) with (X, Y) doesn't guarantee that X is a value in col.
return ROWS_MIGHT_MATCH
- def visit_is_nan(self, term: BoundTerm) -> bool:
+ def visit_is_nan(self, term: BoundTerm[L]) -> bool:
pos = term.ref().accessor.position
field = self.partition_fields[pos]
@@ -479,7 +481,7 @@ class _ManifestEvalVisitor(BoundBooleanExpressionVisitor[bool]):
return ROWS_MIGHT_MATCH
- def visit_not_nan(self, term: BoundTerm) -> bool:
+ def visit_not_nan(self, term: BoundTerm[L]) -> bool:
pos = term.ref().accessor.position
field = self.partition_fields[pos]
@@ -488,7 +490,7 @@ class _ManifestEvalVisitor(BoundBooleanExpressionVisitor[bool]):
return ROWS_MIGHT_MATCH
- def visit_is_null(self, term: BoundTerm) -> bool:
+ def visit_is_null(self, term: BoundTerm[L]) -> bool:
pos = term.ref().accessor.position
if self.partition_fields[pos].contains_null is False:
@@ -496,7 +498,7 @@ class _ManifestEvalVisitor(BoundBooleanExpressionVisitor[bool]):
return ROWS_MIGHT_MATCH
- def visit_not_null(self, term: BoundTerm) -> bool:
+ def visit_not_null(self, term: BoundTerm[L]) -> bool:
pos = term.ref().accessor.position
# contains_null encodes whether at least one partition value is null,
@@ -513,7 +515,7 @@ class _ManifestEvalVisitor(BoundBooleanExpressionVisitor[bool]):
return ROWS_MIGHT_MATCH
- def visit_equal(self, term: BoundTerm, literal: Literal[Any]) -> bool:
+ def visit_equal(self, term: BoundTerm[L], literal: Literal[L]) -> bool:
pos = term.ref().accessor.position
field = self.partition_fields[pos]
@@ -533,12 +535,12 @@ class _ManifestEvalVisitor(BoundBooleanExpressionVisitor[bool]):
return ROWS_MIGHT_MATCH
- def visit_not_equal(self, term: BoundTerm, literal: Literal[Any]) -> bool:
+ def visit_not_equal(self, term: BoundTerm[L], literal: Literal[L]) -> bool:
# because the bounds are not necessarily a min or max value, this cannot be answered using
# them. notEq(col, X) with (X, Y) doesn't guarantee that X is a value in col.
return ROWS_MIGHT_MATCH
- def visit_greater_than_or_equal(self, term: BoundTerm, literal: Literal[Any]) -> bool:
+ def visit_greater_than_or_equal(self, term: BoundTerm[L], literal: Literal[L]) -> bool:
pos = term.ref().accessor.position
field = self.partition_fields[pos]
@@ -552,7 +554,7 @@ class _ManifestEvalVisitor(BoundBooleanExpressionVisitor[bool]):
return ROWS_MIGHT_MATCH
- def visit_greater_than(self, term: BoundTerm, literal: Literal[Any]) -> bool:
+ def visit_greater_than(self, term: BoundTerm[L], literal: Literal[L]) -> bool:
pos = term.ref().accessor.position
field = self.partition_fields[pos]
@@ -566,7 +568,7 @@ class _ManifestEvalVisitor(BoundBooleanExpressionVisitor[bool]):
return ROWS_MIGHT_MATCH
- def visit_less_than(self, term: BoundTerm, literal: Literal[Any]) -> bool:
+ def visit_less_than(self, term: BoundTerm[L], literal: Literal[L]) -> bool:
pos = term.ref().accessor.position
field = self.partition_fields[pos]
@@ -580,7 +582,7 @@ class _ManifestEvalVisitor(BoundBooleanExpressionVisitor[bool]):
return ROWS_MIGHT_MATCH
- def visit_less_than_or_equal(self, term: BoundTerm, literal: Literal[Any]) -> bool:
+ def visit_less_than_or_equal(self, term: BoundTerm[L], literal: Literal[L]) -> bool:
pos = term.ref().accessor.position
field = self.partition_fields[pos]
diff --git a/python/pyiceberg/typedef.py b/python/pyiceberg/typedef.py
index 76add54bdd..b038bfb17c 100644
--- a/python/pyiceberg/typedef.py
+++ b/python/pyiceberg/typedef.py
@@ -14,13 +14,15 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
-
+from decimal import Decimal
from typing import (
Any,
Dict,
Tuple,
+ TypeVar,
Union,
)
+from uuid import UUID
class FrozenDict(Dict[Any, Any]):
@@ -36,3 +38,6 @@ EMPTY_DICT = FrozenDict()
Identifier = Tuple[str, ...]
Properties = Dict[str, str]
RecursiveDict = Dict[str, Union[str, "RecursiveDict"]]
+
+# Represents the literal value
+L = TypeVar("L", str, bool, int, float, bytes, UUID, Decimal)
diff --git a/python/pyproject.toml b/python/pyproject.toml
index b54f266e8b..181093e469 100644
--- a/python/pyproject.toml
+++ b/python/pyproject.toml
@@ -72,6 +72,7 @@ pre-commit = "2.20.0"
fastavro = "1.6.1"
coverage = { version = "^6.5.0", extras = ["toml"] }
requests-mock = "1.10.0"
+typing-extensions = '4.4.0'
[tool.poetry.scripts]
pyiceberg = "pyiceberg.cli.console:run"
diff --git a/python/tests/expressions/test_expressions.py b/python/tests/expressions/test_expressions.py
index 6ccada73a4..2772ac2c34 100644
--- a/python/tests/expressions/test_expressions.py
+++ b/python/tests/expressions/test_expressions.py
@@ -14,17 +14,18 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
+# pylint:disable=redefined-outer-name,eval-used
import uuid
from decimal import Decimal
import pytest
+from typing_extensions import assert_type
from pyiceberg.expressions import (
AlwaysFalse,
AlwaysTrue,
And,
- BooleanExpression,
BoundEqualTo,
BoundGreaterThan,
BoundGreaterThanOrEqual,
@@ -33,15 +34,11 @@ from pyiceberg.expressions import (
BoundIsNull,
BoundLessThan,
BoundLessThanOrEqual,
- BoundLiteralPredicate,
BoundNotEqualTo,
BoundNotIn,
BoundNotNaN,
BoundNotNull,
- BoundPredicate,
BoundReference,
- BoundSetPredicate,
- BoundUnaryPredicate,
EqualTo,
GreaterThan,
GreaterThanOrEqual,
@@ -50,7 +47,6 @@ from pyiceberg.expressions import (
IsNull,
LessThan,
LessThanOrEqual,
- LiteralPredicate,
Not,
NotEqualTo,
NotIn,
@@ -58,11 +54,8 @@ from pyiceberg.expressions import (
NotNull,
Or,
Reference,
- SetPredicate,
- UnaryPredicate,
- UnboundPredicate,
)
-from pyiceberg.expressions.literals import StringLiteral, literal
+from pyiceberg.expressions.literals import literal
from pyiceberg.expressions.visitors import _from_byte_buffer
from pyiceberg.schema import Accessor, Schema
from pyiceberg.types import (
@@ -73,27 +66,10 @@ from pyiceberg.types import (
NestedField,
StringType,
)
+from tests.conftest import FooStruct
from tests.expressions.test_visitors import ExpressionA, ExpressionB
-@pytest.mark.parametrize(
- "op, rep",
- [
- (
- And(ExpressionA(), ExpressionB()),
- "And(left=ExpressionA(), right=ExpressionB())",
- ),
- (
- Or(ExpressionA(), ExpressionB()),
- "Or(left=ExpressionA(), right=ExpressionB())",
- ),
- (Not(ExpressionA()), "Not(child=ExpressionA())"),
- ],
-)
-def test_reprs(op: BooleanExpression, rep: str):
- assert repr(op) == rep
-
-
def test_isnull_inverse():
assert ~IsNull(Reference("a")) == NotNull(Reference("a"))
@@ -202,48 +178,36 @@ def test_notnan_bind_nonfloat():
assert NotNaN(Reference("i")).bind(schema) == AlwaysTrue()
-@pytest.mark.parametrize(
- "op, string",
- [
- (And(ExpressionA(), ExpressionB()), "And(left=ExpressionA(), right=ExpressionB())"),
- (Or(ExpressionA(), ExpressionB()), "Or(left=ExpressionA(), right=ExpressionB())"),
- (Not(ExpressionA()), "Not(child=ExpressionA())"),
- ],
-)
-def test_strs(op, string):
- assert str(op) == string
-
-
def test_ref_binding_case_sensitive(table_schema_simple: Schema):
- ref = Reference[str]("foo")
+ ref = Reference("foo")
bound = BoundReference[str](table_schema_simple.find_field(1), table_schema_simple.accessor_for_field(1))
assert ref.bind(table_schema_simple, case_sensitive=True) == bound
def test_ref_binding_case_sensitive_failure(table_schema_simple: Schema):
- ref = Reference[str]("Foo")
+ ref = Reference("Foo")
with pytest.raises(ValueError):
ref.bind(table_schema_simple, case_sensitive=True)
def test_ref_binding_case_insensitive(table_schema_simple: Schema):
- ref = Reference[str]("Foo")
+ ref = Reference("Foo")
bound = BoundReference[str](table_schema_simple.find_field(1), table_schema_simple.accessor_for_field(1))
assert ref.bind(table_schema_simple, case_sensitive=False) == bound
def test_ref_binding_case_insensitive_failure(table_schema_simple: Schema):
- ref = Reference[str]("Foot")
+ ref = Reference("Foot")
with pytest.raises(ValueError):
ref.bind(table_schema_simple, case_sensitive=False)
def test_in_to_eq():
- assert In(Reference("x"), (literal(34.56),)) == EqualTo(Reference("x"), literal(34.56))
+ assert In("x", (34.56,)) == EqualTo(Reference("x"), 34.56)
def test_empty_bind_in(table_schema_simple: Schema):
- bound = BoundIn[str](BoundReference(table_schema_simple.find_field(1), table_schema_simple.accessor_for_field(1)), set())
+ bound = BoundIn(BoundReference[str](table_schema_simple.find_field(1), table_schema_simple.accessor_for_field(1)), set())
assert bound == AlwaysFalse()
@@ -257,12 +221,12 @@ def test_bind_not_in_equal_term(table_schema_simple: Schema):
BoundReference(table_schema_simple.find_field(1), table_schema_simple.accessor_for_field(1)), {literal("hello")}
)
assert (
- BoundNotEqualTo[str](
+ BoundNotEqualTo(
term=BoundReference(
field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
accessor=Accessor(position=0, inner=None),
),
- literal=StringLiteral("hello"),
+ literal=literal("hello"),
)
== bound
)
@@ -272,57 +236,69 @@ def test_in_empty():
assert In(Reference("foo"), ()) == AlwaysFalse()
+def test_in_set():
+ assert In(Reference("foo"), {"a", "bc", "def"}).literals == {literal("a"), literal("bc"), literal("def")}
+
+
+def test_in_tuple():
+ assert In(Reference("foo"), ("a", "bc", "def")).literals == {literal("a"), literal("bc"), literal("def")}
+
+
+def test_in_list():
+ assert In(Reference("foo"), ["a", "bc", "def"]).literals == {literal("a"), literal("bc"), literal("def")}
+
+
def test_not_in_empty():
assert NotIn(Reference("foo"), ()) == AlwaysTrue()
def test_not_in_equal():
- assert NotIn(Reference("foo"), (literal("hello"),)) == NotEqualTo(term=Reference(name="foo"), literal=StringLiteral("hello"))
+ assert NotIn(Reference("foo"), ("hello",)) == NotEqualTo(term=Reference(name="foo"), literal="hello")
def test_bind_in(table_schema_simple: Schema):
- bound = BoundIn(
+ bound = BoundIn[str](
BoundReference(table_schema_simple.find_field(1), table_schema_simple.accessor_for_field(1)),
{literal("hello"), literal("world")},
)
- assert In(Reference("foo"), (literal("hello"), literal("world"))).bind(table_schema_simple) == bound
+ assert In(Reference("foo"), ("hello", "world")).bind(table_schema_simple) == bound
def test_bind_in_invert(table_schema_simple: Schema):
- bound = BoundIn(
+ bound = BoundIn[str](
BoundReference(table_schema_simple.find_field(1), table_schema_simple.accessor_for_field(1)),
{literal("hello"), literal("world")},
)
- assert ~bound == BoundNotIn(
+ assert ~bound == BoundNotIn[str](
BoundReference(table_schema_simple.find_field(1), table_schema_simple.accessor_for_field(1)),
{literal("hello"), literal("world")},
)
def test_bind_not_in_invert(table_schema_simple: Schema):
- bound = BoundNotIn(
+ bound = BoundNotIn[str](
BoundReference(table_schema_simple.find_field(1), table_schema_simple.accessor_for_field(1)),
{literal("hello"), literal("world")},
)
- assert ~bound == BoundIn(
+ assert ~bound == BoundIn[str](
BoundReference(table_schema_simple.find_field(1), table_schema_simple.accessor_for_field(1)),
{literal("hello"), literal("world")},
)
def test_bind_dedup(table_schema_simple: Schema):
- bound = BoundIn(
+ bound = BoundIn[str](
BoundReference(table_schema_simple.find_field(1), table_schema_simple.accessor_for_field(1)),
{literal("hello"), literal("world")},
)
- assert In(Reference("foo"), (literal("hello"), literal("world"), literal("world"))).bind(table_schema_simple) == bound
+ assert In(Reference("foo"), ("hello", "world", "world")).bind(table_schema_simple) == bound
def test_bind_dedup_to_eq(table_schema_simple: Schema):
bound = BoundEqualTo(
BoundReference(table_schema_simple.find_field(1), table_schema_simple.accessor_for_field(1)), literal("hello")
)
- assert In(Reference("foo"), (literal("hello"), literal("hello"))).bind(table_schema_simple) == bound
+ assert In(Reference("foo"), ("hello", "hello")).bind(table_schema_simple) == bound
def test_bound_equal_to_invert(table_schema_simple: Schema):
@@ -330,11 +306,11 @@ def test_bound_equal_to_invert(table_schema_simple: Schema):
BoundReference(table_schema_simple.find_field(1), table_schema_simple.accessor_for_field(1)), literal("hello")
)
assert ~bound == BoundNotEqualTo(
- term=BoundReference[str](
+ term=BoundReference(
field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
accessor=Accessor(position=0, inner=None),
),
- literal=StringLiteral("hello"),
+ literal=literal("hello"),
)
@@ -343,11 +319,11 @@ def test_bound_not_equal_to_invert(table_schema_simple: Schema):
BoundReference(table_schema_simple.find_field(1), table_schema_simple.accessor_for_field(1)), literal("hello")
)
assert ~bound == BoundEqualTo(
- term=BoundReference[str](
+ term=BoundReference(
field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
accessor=Accessor(position=0, inner=None),
),
- literal=StringLiteral("hello"),
+ literal=literal("hello"),
)
@@ -356,11 +332,11 @@ def test_bound_greater_than_or_equal_invert(table_schema_simple: Schema):
BoundReference(table_schema_simple.find_field(1), table_schema_simple.accessor_for_field(1)), literal("hello")
)
assert ~bound == BoundLessThan(
- term=BoundReference[str](
+ term=BoundReference(
field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
accessor=Accessor(position=0, inner=None),
),
- literal=StringLiteral("hello"),
+ literal=literal("hello"),
)
@@ -369,11 +345,11 @@ def test_bound_greater_than_invert(table_schema_simple: Schema):
BoundReference(table_schema_simple.find_field(1), table_schema_simple.accessor_for_field(1)), literal("hello")
)
assert ~bound == BoundLessThanOrEqual(
- term=BoundReference[str](
+ term=BoundReference(
field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
accessor=Accessor(position=0, inner=None),
),
- literal=StringLiteral("hello"),
+ literal=literal("hello"),
)
@@ -382,11 +358,11 @@ def test_bound_less_than_invert(table_schema_simple: Schema):
BoundReference(table_schema_simple.find_field(1), table_schema_simple.accessor_for_field(1)), literal("hello")
)
assert ~bound == BoundGreaterThanOrEqual(
- term=BoundReference[str](
+ term=BoundReference(
field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
accessor=Accessor(position=0, inner=None),
),
- literal=StringLiteral("hello"),
+ literal=literal("hello"),
)
@@ -395,11 +371,11 @@ def test_bound_less_than_or_equal_invert(table_schema_simple: Schema):
BoundReference(table_schema_simple.find_field(1), table_schema_simple.accessor_for_field(1)), literal("hello")
)
assert ~bound == BoundGreaterThan(
- term=BoundReference[str](
+ term=BoundReference(
field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
accessor=Accessor(position=0, inner=None),
),
- literal=StringLiteral("hello"),
+ literal=literal("hello"),
)
@@ -409,14 +385,14 @@ def test_not_equal_to_invert():
field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
accessor=Accessor(position=0, inner=None),
),
- literal=StringLiteral("hello"),
+ literal="hello",
)
assert ~bound == EqualTo(
term=BoundReference(
field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
accessor=Accessor(position=0, inner=None),
),
- literal=StringLiteral("hello"),
+ literal="hello",
)
@@ -426,14 +402,14 @@ def test_greater_than_or_equal_invert():
field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
accessor=Accessor(position=0, inner=None),
),
- literal=StringLiteral("hello"),
+ literal="hello",
)
assert ~bound == LessThan(
term=BoundReference(
field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
accessor=Accessor(position=0, inner=None),
),
- literal=StringLiteral("hello"),
+ literal="hello",
)
@@ -443,27 +419,27 @@ def test_less_than_or_equal_invert():
field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
accessor=Accessor(position=0, inner=None),
),
- literal=StringLiteral("hello"),
+ literal="hello",
)
assert ~bound == GreaterThan(
term=BoundReference(
field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
accessor=Accessor(position=0, inner=None),
),
- literal=StringLiteral("hello"),
+ literal="hello",
)
@pytest.mark.parametrize(
"pred",
[
- NotIn(Reference("foo"), (literal("hello"), literal("world"))),
- NotEqualTo(Reference("foo"), literal("hello")),
- EqualTo(Reference("foo"), literal("hello")),
- GreaterThan(Reference("foo"), literal("hello")),
- LessThan(Reference("foo"), literal("hello")),
- GreaterThanOrEqual(Reference("foo"), literal("hello")),
- LessThanOrEqual(Reference("foo"), literal("hello")),
+ NotIn(Reference("foo"), ("hello", "world")),
+ NotEqualTo(Reference("foo"), "hello"),
+ EqualTo(Reference("foo"), "hello"),
+ GreaterThan(Reference("foo"), "hello"),
+ LessThan(Reference("foo"), "hello"),
+ GreaterThanOrEqual(Reference("foo"), "hello"),
+ LessThanOrEqual(Reference("foo"), "hello"),
],
)
def test_bind(pred, table_schema_simple: Schema):
@@ -475,14 +451,14 @@ def test_bind(pred, table_schema_simple: Schema):
@pytest.mark.parametrize(
"pred",
[
- In(Reference("Bar"), (literal(5), literal(2))),
- NotIn(Reference("Bar"), (literal(5), literal(2))),
- NotEqualTo(Reference("Bar"), literal(5)),
- EqualTo(Reference("Bar"), literal(5)),
- GreaterThan(Reference("Bar"), literal(5)),
- LessThan(Reference("Bar"), literal(5)),
- GreaterThanOrEqual(Reference("Bar"), literal(5)),
- LessThanOrEqual(Reference("Bar"), literal(5)),
+ In(Reference("Bar"), (5, 2)),
+ NotIn(Reference("Bar"), (5, 2)),
+ NotEqualTo(Reference("Bar"), 5),
+ EqualTo(Reference("Bar"), 5),
+ GreaterThan(Reference("Bar"), 5),
+ LessThan(Reference("Bar"), 5),
+ GreaterThanOrEqual(Reference("Bar"), 5),
+ LessThanOrEqual(Reference("Bar"), 5),
],
)
def test_bind_case_insensitive(pred, table_schema_simple: Schema):
@@ -508,14 +484,14 @@ def test_bind_case_insensitive(pred, table_schema_simple: Schema):
(ExpressionA(), ExpressionA(), ExpressionB()),
(ExpressionB(), ExpressionB(), ExpressionA()),
(
- In(Reference("foo"), (literal("hello"), literal("world"))),
- In(Reference("foo"), (literal("hello"), literal("world"))),
- In(Reference("not_foo"), (literal("hello"), literal("world"))),
+ In(Reference("foo"), ("hello", "world")),
+ In(Reference("foo"), ("hello", "world")),
+ In(Reference("not_foo"), ("hello", "world")),
),
(
- In(Reference("foo"), (literal("hello"), literal("world"))),
- In(Reference("foo"), (literal("hello"), literal("world"))),
- In(Reference("foo"), (literal("goodbye"), literal("world"))),
+ In(Reference("foo"), ("hello", "world")),
+ In(Reference("foo"), ("hello", "world")),
+ In(Reference("foo"), ("goodbye", "world")),
),
],
)
@@ -539,16 +515,16 @@ def test_eq(exp, testexpra, testexprb):
ExpressionA(),
),
(
- In(Reference("foo"), (literal("hello"), literal("world"))),
- NotIn(Reference("foo"), (literal("hello"), literal("world"))),
+ In(Reference("foo"), ("hello", "world")),
+ NotIn(Reference("foo"), ("hello", "world")),
),
(
- NotIn(Reference("foo"), (literal("hello"), literal("world"))),
- In(Reference("foo"), (literal("hello"), literal("world"))),
+ NotIn(Reference("foo"), ("hello", "world")),
+ In(Reference("foo"), ("hello", "world")),
),
- (GreaterThan(Reference("foo"), literal(5)), LessThanOrEqual(Reference("foo"), literal(5))),
- (LessThan(Reference("foo"), literal(5)), GreaterThanOrEqual(Reference("foo"), literal(5))),
- (EqualTo(Reference("foo"), literal(5)), NotEqualTo(Reference("foo"), literal(5))),
+ (GreaterThan(Reference("foo"), 5), LessThanOrEqual(Reference("foo"), 5)),
+ (LessThan(Reference("foo"), 5), GreaterThanOrEqual(Reference("foo"), 5)),
+ (EqualTo(Reference("foo"), 5), NotEqualTo(Reference("foo"), 5)),
(
ExpressionA(),
ExpressionB(),
@@ -632,24 +608,271 @@ def test_accessor_base_class(foo_struct):
assert Accessor(position=11).get(foo_struct) == b"\x19\x04\x9e?"
-def test_bound_reference_str_and_repr():
- """Test str and repr of BoundReference"""
- field = NestedField(field_id=1, name="foo", field_type=StringType(), required=False)
- position1_accessor = Accessor(position=1)
- bound_ref = BoundReference(field=field, accessor=position1_accessor)
- assert str(bound_ref) == f"BoundReference(field={repr(field)}, accessor={repr(position1_accessor)})"
- assert repr(bound_ref) == f"BoundReference(field={repr(field)}, accessor={repr(position1_accessor)})"
+@pytest.fixture
+def field() -> NestedField:
+ return NestedField(field_id=1, name="foo", field_type=StringType(), required=False)
+
+
+@pytest.fixture
+def accessor() -> Accessor:
+ return Accessor(position=1)
+
+
+@pytest.fixture
+def term(field: NestedField, accessor: Accessor) -> BoundReference:
+ return BoundReference(
+ field=field,
+ accessor=accessor,
+ )
+
+
+def test_bound_reference(field: NestedField, accessor: Accessor) -> None:
+ bound_ref = BoundReference(field=field, accessor=accessor)
+ assert str(bound_ref) == f"BoundReference(field={repr(field)}, accessor={repr(accessor)})"
+ assert repr(bound_ref) == f"BoundReference(field={repr(field)}, accessor={repr(accessor)})"
+ assert bound_ref == eval(repr(bound_ref))
+
+
+def test_reference() -> None:
+ abc = "abc"
+ ref = Reference(abc)
+ assert str(ref) == "Reference(name='abc')"
+ assert repr(ref) == "Reference(name='abc')"
+ assert ref == eval(repr(ref))
+
+
+def test_and() -> None:
+ null = IsNull(Reference("a"))
+ nan = IsNaN(Reference("b"))
+ and_ = And(null, nan)
+ assert str(and_) == f"And(left={str(null)}, right={str(nan)})"
+ assert repr(and_) == f"And(left={repr(null)}, right={repr(nan)})"
+ assert and_ == eval(repr(and_))
+
+
+def test_or() -> None:
+ null = IsNull(Reference("a"))
+ nan = IsNaN(Reference("b"))
+ or_ = Or(null, nan)
+ assert str(or_) == f"Or(left={str(null)}, right={str(nan)})"
+ assert repr(or_) == f"Or(left={repr(null)}, right={repr(nan)})"
+ assert or_ == eval(repr(or_))
+
+
+def test_not() -> None:
+ null = IsNull(Reference("a"))
+ or_ = Not(null)
+ assert str(or_) == f"Not(child={str(null)})"
+ assert repr(or_) == f"Not(child={repr(null)})"
+ assert or_ == eval(repr(or_))
+
+
+def test_always_true() -> None:
+ always_true = AlwaysTrue()
+ assert str(always_true) == "AlwaysTrue()"
+ assert repr(always_true) == "AlwaysTrue()"
+ assert always_true == eval(repr(always_true))
+
+
+def test_always_false() -> None:
+ always_false = AlwaysFalse()
+ assert str(always_false) == "AlwaysFalse()"
+ assert repr(always_false) == "AlwaysFalse()"
+ assert always_false == eval(repr(always_false))
def test_bound_reference_field_property():
- """Test str and repr of BoundReference"""
field = NestedField(field_id=1, name="foo", field_type=StringType(), required=False)
position1_accessor = Accessor(position=1)
bound_ref = BoundReference(field=field, accessor=position1_accessor)
assert bound_ref.field == NestedField(field_id=1, name="foo", field_type=StringType(), required=False)
-def test_bound_reference(table_schema_simple, foo_struct):
+def test_bound_is_null(term: BoundReference) -> None:
+ bound_is_null = BoundIsNull(term)
+ assert str(bound_is_null) == f"BoundIsNull(term={str(term)})"
+ assert repr(bound_is_null) == f"BoundIsNull(term={repr(term)})"
+ assert bound_is_null == eval(repr(bound_is_null))
+
+
+def test_bound_is_not_null(term: BoundReference) -> None:
+ bound_not_null = BoundNotNull(term)
+ assert str(bound_not_null) == f"BoundNotNull(term={str(term)})"
+ assert repr(bound_not_null) == f"BoundNotNull(term={repr(term)})"
+ assert bound_not_null == eval(repr(bound_not_null))
+
+
+def test_is_null() -> None:
+ ref = Reference("a")
+ is_null = IsNull(ref)
+ assert str(is_null) == f"IsNull(term={str(ref)})"
+ assert repr(is_null) == f"IsNull(term={repr(ref)})"
+ assert is_null == eval(repr(is_null))
+
+
+def test_not_null() -> None:
+ ref = Reference("a")
+ non_null = NotNull(ref)
+ assert str(non_null) == f"NotNull(term={str(ref)})"
+ assert repr(non_null) == f"NotNull(term={repr(ref)})"
+ assert non_null == eval(repr(non_null))
+
+
+def test_bound_is_nan(accessor: Accessor) -> None:
+ # We need a FloatType here
+ term = BoundReference[float](
+ field=NestedField(field_id=1, name="foo", field_type=FloatType(), required=False),
+ accessor=accessor,
+ )
+ bound_is_nan = BoundIsNaN(term)
+ assert str(bound_is_nan) == f"BoundIsNaN(term={str(term)})"
+ assert repr(bound_is_nan) == f"BoundIsNaN(term={repr(term)})"
+ assert bound_is_nan == eval(repr(bound_is_nan))
+
+
+def test_bound_is_not_nan(accessor: Accessor) -> None:
+ # We need a FloatType here
+ term = BoundReference[float](
+ field=NestedField(field_id=1, name="foo", field_type=FloatType(), required=False),
+ accessor=accessor,
+ )
+ bound_not_nan = BoundNotNaN(term)
+ assert str(bound_not_nan) == f"BoundNotNaN(term={str(term)})"
+ assert repr(bound_not_nan) == f"BoundNotNaN(term={repr(term)})"
+ assert bound_not_nan == eval(repr(bound_not_nan))
+
+
+def test_is_nan() -> None:
+ ref = Reference("a")
+ is_nan = IsNaN(ref)
+ assert str(is_nan) == f"IsNaN(term={str(ref)})"
+ assert repr(is_nan) == f"IsNaN(term={repr(ref)})"
+ assert is_nan == eval(repr(is_nan))
+
+
+def test_not_nan() -> None:
+ ref = Reference("a")
+ not_nan = NotNaN(ref)
+ assert str(not_nan) == f"NotNaN(term={str(ref)})"
+ assert repr(not_nan) == f"NotNaN(term={repr(ref)})"
+ assert not_nan == eval(repr(not_nan))
+
+
+def test_bound_in(term: BoundReference) -> None:
+ bound_in = BoundIn(term, {literal("a"), literal("b"), literal("c")})
+ assert str(bound_in) == f"BoundIn({str(term)}, {{a, b, c}})"
+ assert repr(bound_in) == f"BoundIn({repr(term)}, {{literal('a'), literal('b'), literal('c')}})"
+ assert bound_in == eval(repr(bound_in))
+
+
+def test_bound_not_in(term: BoundReference) -> None:
+ bound_not_in = BoundNotIn(term, {literal("a"), literal("b"), literal("c")})
+ assert str(bound_not_in) == f"BoundNotIn({str(term)}, {{a, b, c}})"
+ assert repr(bound_not_in) == f"BoundNotIn({repr(term)}, {{literal('a'), literal('b'), literal('c')}})"
+ assert bound_not_in == eval(repr(bound_not_in))
+
+
+def test_in() -> None:
+ ref = Reference("a")
+ unbound_in = In(ref, {"a", "b", "c"})
+ assert str(unbound_in) == f"In({str(ref)}, {{a, b, c}})"
+ assert repr(unbound_in) == f"In({repr(ref)}, {{literal('a'), literal('b'), literal('c')}})"
+ assert unbound_in == eval(repr(unbound_in))
+
+
+def test_not_in() -> None:
+ ref = Reference("a")
+ not_in = NotIn(ref, {"a", "b", "c"})
+ assert str(not_in) == f"NotIn({str(ref)}, {{a, b, c}})"
+ assert repr(not_in) == f"NotIn({repr(ref)}, {{literal('a'), literal('b'), literal('c')}})"
+ assert not_in == eval(repr(not_in))
+
+
+def test_bound_equal_to(term: BoundReference) -> None:
+ bound_equal_to = BoundEqualTo(term, literal("a"))
+ assert str(bound_equal_to) == f"BoundEqualTo(term={str(term)}, literal=literal('a'))"
+ assert repr(bound_equal_to) == f"BoundEqualTo(term={repr(term)}, literal=literal('a'))"
+ assert bound_equal_to == eval(repr(bound_equal_to))
+
+
+def test_bound_not_equal_to(term: BoundReference) -> None:
+ bound_not_equal_to = BoundNotEqualTo(term, literal("a"))
+ assert str(bound_not_equal_to) == f"BoundNotEqualTo(term={str(term)}, literal=literal('a'))"
+ assert repr(bound_not_equal_to) == f"BoundNotEqualTo(term={repr(term)}, literal=literal('a'))"
+ assert bound_not_equal_to == eval(repr(bound_not_equal_to))
+
+
+def test_bound_greater_than_or_equal_to(term: BoundReference) -> None:
+ bound_greater_than_or_equal_to = BoundGreaterThanOrEqual(term, literal("a"))
+ assert str(bound_greater_than_or_equal_to) == f"BoundGreaterThanOrEqual(term={str(term)}, literal=literal('a'))"
+ assert repr(bound_greater_than_or_equal_to) == f"BoundGreaterThanOrEqual(term={repr(term)}, literal=literal('a'))"
+ assert bound_greater_than_or_equal_to == eval(repr(bound_greater_than_or_equal_to))
+
+
+def test_bound_greater_than(term: BoundReference) -> None:
+ bound_greater_than = BoundGreaterThan(term, literal("a"))
+ assert str(bound_greater_than) == f"BoundGreaterThan(term={str(term)}, literal=literal('a'))"
+ assert repr(bound_greater_than) == f"BoundGreaterThan(term={repr(term)}, literal=literal('a'))"
+ assert bound_greater_than == eval(repr(bound_greater_than))
+
+
+def test_bound_less_than(term: BoundReference) -> None:
+ bound_less_than = BoundLessThan(term, literal("a"))
+ assert str(bound_less_than) == f"BoundLessThan(term={str(term)}, literal=literal('a'))"
+ assert repr(bound_less_than) == f"BoundLessThan(term={repr(term)}, literal=literal('a'))"
+ assert bound_less_than == eval(repr(bound_less_than))
+
+
+def test_bound_less_than_or_equal(term: BoundReference) -> None:
+ bound_less_than_or_equal = BoundLessThanOrEqual(term, literal("a"))
+ assert str(bound_less_than_or_equal) == f"BoundLessThanOrEqual(term={str(term)}, literal=literal('a'))"
+ assert repr(bound_less_than_or_equal) == f"BoundLessThanOrEqual(term={repr(term)}, literal=literal('a'))"
+ assert bound_less_than_or_equal == eval(repr(bound_less_than_or_equal))
+
+
+def test_equal_to() -> None:
+ equal_to = EqualTo(Reference("a"), literal("a"))
+ assert str(equal_to) == "EqualTo(term=Reference(name='a'), literal=literal('a'))"
+ assert repr(equal_to) == "EqualTo(term=Reference(name='a'), literal=literal('a'))"
+ assert equal_to == eval(repr(equal_to))
+
+
+def test_not_equal_to() -> None:
+ not_equal_to = NotEqualTo(Reference("a"), literal("a"))
+ assert str(not_equal_to) == "NotEqualTo(term=Reference(name='a'), literal=literal('a'))"
+ assert repr(not_equal_to) == "NotEqualTo(term=Reference(name='a'), literal=literal('a'))"
+ assert not_equal_to == eval(repr(not_equal_to))
+
+
+def test_greater_than_or_equal_to() -> None:
+ greater_than_or_equal_to = GreaterThanOrEqual(Reference("a"), literal("a"))
+ assert str(greater_than_or_equal_to) == "GreaterThanOrEqual(term=Reference(name='a'), literal=literal('a'))"
+ assert repr(greater_than_or_equal_to) == "GreaterThanOrEqual(term=Reference(name='a'), literal=literal('a'))"
+ assert greater_than_or_equal_to == eval(repr(greater_than_or_equal_to))
+
+
+def test_greater_than() -> None:
+ greater_than = GreaterThan(Reference("a"), literal("a"))
+ assert str(greater_than) == "GreaterThan(term=Reference(name='a'), literal=literal('a'))"
+ assert repr(greater_than) == "GreaterThan(term=Reference(name='a'), literal=literal('a'))"
+ assert greater_than == eval(repr(greater_than))
+
+
+def test_less_than() -> None:
+ less_than = LessThan(Reference("a"), literal("a"))
+ assert str(less_than) == "LessThan(term=Reference(name='a'), literal=literal('a'))"
+ assert repr(less_than) == "LessThan(term=Reference(name='a'), literal=literal('a'))"
+ assert less_than == eval(repr(less_than))
+
+
+def test_less_than_or_equal() -> None:
+ less_than_or_equal = LessThanOrEqual(Reference("a"), literal("a"))
+ assert str(less_than_or_equal) == "LessThanOrEqual(term=Reference(name='a'), literal=literal('a'))"
+ assert repr(less_than_or_equal) == "LessThanOrEqual(term=Reference(name='a'), literal=literal('a'))"
+ assert less_than_or_equal == eval(repr(less_than_or_equal))
+
+
+def test_bound_reference_eval(table_schema_simple: Schema, foo_struct: FooStruct) -> None:
"""Test creating a BoundReference and evaluating it on a StructProtocol"""
foo_struct.set(pos=1, value="foovalue")
foo_struct.set(pos=2, value=123)
@@ -672,48 +895,6 @@ def test_bound_reference(table_schema_simple, foo_struct):
assert bound_ref3.eval(foo_struct) is True
-def test_bound_predicate_invert():
- with pytest.raises(NotImplementedError):
- _ = ~BoundPredicate(
- term=BoundReference(
- field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
- accessor=Accessor(position=0, inner=None),
- )
- )
-
-
-def test_bound_unary_predicate_invert():
- with pytest.raises(NotImplementedError):
- _ = ~BoundUnaryPredicate(
- term=BoundReference(
- field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
- accessor=Accessor(position=0, inner=None),
- )
- )
-
-
-def test_bound_set_predicate_invert():
- with pytest.raises(NotImplementedError):
- _ = ~BoundSetPredicate(
- term=BoundReference(
- field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
- accessor=Accessor(position=0, inner=None),
- ),
- literals={literal("hello"), literal("world")},
- )
-
-
-def test_bound_literal_predicate_invert():
- with pytest.raises(NotImplementedError):
- _ = ~BoundLiteralPredicate(
- term=BoundReference(
- field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
- accessor=Accessor(position=0, inner=None),
- ),
- literal=literal("world"),
- )
-
-
def test_non_primitive_from_byte_buffer():
with pytest.raises(ValueError) as exc_info:
_ = _from_byte_buffer(ListType(element_id=1, element_type=StringType()), b"\0x00")
@@ -721,26 +902,25 @@ def test_non_primitive_from_byte_buffer():
assert str(exc_info.value) == "Expected a PrimitiveType, got: <class 'pyiceberg.types.ListType'>"
-def test_unbound_predicate_invert():
- with pytest.raises(NotImplementedError):
- _ = ~UnboundPredicate(term=Reference("a"))
-
+def test_string_argument_unbound_unary():
+ assert IsNull("a") == IsNull(Reference("a"))
-def test_unbound_predicate_bind(table_schema_simple: Schema):
- with pytest.raises(NotImplementedError):
- _ = UnboundPredicate(term=Reference("a")).bind(table_schema_simple)
+def test_string_argument_unbound_literal():
+ assert EqualTo("a", "b") == EqualTo(Reference("a"), "b")
-def test_unbound_unary_predicate_invert():
- with pytest.raises(NotImplementedError):
- _ = ~UnaryPredicate(term=Reference("a"))
+def test_string_argument_unbound_set():
+ assert In("a", {"b", "c"}) == In(Reference("a"), {"b", "c"})
-def test_unbound_set_predicate_invert():
- with pytest.raises(NotImplementedError):
- _ = ~SetPredicate(term=Reference("a"), literals=(literal("hello"), literal("world")))
+# __ __ ___
+# | \/ |_ _| _ \_ _
+# | |\/| | || | _/ || |
+# |_| |_|\_, |_| \_, |
+# |__/ |__/
-def test_unbound_literal_predicate_invert():
- with pytest.raises(NotImplementedError):
- _ = ~LiteralPredicate(term=Reference("a"), literal=literal("hello"))
+assert_type(EqualTo("a", "b"), EqualTo[str])
+assert_type(In("a", ("a", "b", "c")), In[str])
+assert_type(In("a", (1, 2, 3)), In[int])
+assert_type(NotIn("a", ("a", "b", "c")), NotIn[str])
diff --git a/python/tests/expressions/test_literals.py b/python/tests/expressions/test_literals.py
index 96656ba825..d203195930 100644
--- a/python/tests/expressions/test_literals.py
+++ b/python/tests/expressions/test_literals.py
@@ -19,8 +19,10 @@
import datetime
import uuid
from decimal import Decimal
+from typing import Set
import pytest
+from typing_extensions import assert_type
from pyiceberg.expressions.literals import (
BinaryLiteral,
@@ -34,6 +36,7 @@ from pyiceberg.expressions.literals import (
FloatLiteral,
IntAboveMax,
IntBelowMin,
+ Literal,
LongLiteral,
StringLiteral,
TimeLiteral,
@@ -367,13 +370,11 @@ def test_string_to_decimal_literal():
def test_python_date_conversion():
one_day_str = "2022-03-28"
- one_day_date = datetime.date(2022, 3, 28)
from_str_lit = literal(one_day_str).to(DateType())
- from_date_lit = literal(one_day_date)
- assert isinstance(from_date_lit, DateLiteral)
- assert from_str_lit == from_date_lit
+ assert isinstance(from_str_lit, DateLiteral)
+ assert from_str_lit.value == 19079
@pytest.mark.parametrize(
@@ -385,14 +386,12 @@ def test_python_date_conversion():
(literal(34.11), FloatType()),
(literal(3.5028235e38), DoubleType()),
(literal(Decimal(34.55).quantize(Decimal("0.01"))), DecimalType(9, 2)),
- (literal(datetime.date(2017, 8, 18)), DateType()),
(literal("2017-08-18"), DateType()),
(literal("14:21:01.919"), TimeType()),
(literal("2017-08-18T14:21:01.919"), TimestampType()),
(literal("abc"), StringType()),
(literal(uuid.uuid4()), UUIDType()),
(literal(bytes([0x01, 0x02, 0x03])), FixedType(3)),
- (literal(bytearray([0x03, 0x04, 0x05, 0x06])), BinaryType()),
],
)
def test_identity_conversions(lit, primitive_type):
@@ -412,8 +411,8 @@ def test_fixed_literal():
def test_binary_literal():
- bin_lit012 = literal(bytearray([0x00, 0x01, 0x02]))
- bin_lit013 = literal(bytearray([0x00, 0x01, 0x03]))
+ bin_lit012 = literal(bytes([0x00, 0x01, 0x02]))
+ bin_lit013 = literal(bytes([0x00, 0x01, 0x03]))
assert bin_lit012 == bin_lit012
assert bin_lit012 != bin_lit013
assert bin_lit012 < bin_lit013
@@ -424,7 +423,7 @@ def test_binary_literal():
def test_raise_on_comparison_to_none():
- bin_lit012 = literal(bytearray([0x00, 0x01, 0x02]))
+ bin_lit012 = literal(bytes([0x00, 0x01, 0x02]))
fixed_lit012 = literal(bytes([0x00, 0x01, 0x02]))
with pytest.raises(AttributeError):
@@ -453,7 +452,7 @@ def test_raise_on_comparison_to_none():
def test_binary_to_fixed():
- lit = literal(bytearray([0x00, 0x01, 0x02]))
+ lit = literal(bytes([0x00, 0x01, 0x02]))
fixed_lit = lit.to(FixedType(3))
assert fixed_lit is not None
assert lit.value == fixed_lit.value
@@ -464,7 +463,7 @@ def test_binary_to_fixed():
def test_binary_to_smaller_fixed_none():
- lit = literal(bytearray([0x00, 0x01, 0x02]))
+ lit = literal(bytes([0x00, 0x01, 0x02]))
with pytest.raises(TypeError) as e:
_ = lit.to(FixedType(2))
@@ -479,7 +478,7 @@ def test_fixed_to_binary():
def test_fixed_to_smaller_fixed_none():
- lit = literal(bytearray([0x00, 0x01, 0x02])).to(FixedType(3))
+ lit = literal(bytes([0x00, 0x01, 0x02])).to(FixedType(3))
with pytest.raises(ValueError) as e:
lit.to(lit.to(FixedType(2)))
assert "Could not convert b'\\x00\\x01\\x02' into a fixed[2]" in str(e.value)
@@ -734,7 +733,7 @@ def test_invalid_fixed_conversions():
def test_invalid_binary_conversions():
assert_invalid_conversions(
- literal(bytearray([0x00, 0x01, 0x02])),
+ literal(bytes([0x00, 0x01, 0x02])),
[
BooleanType(),
IntegerType(),
@@ -804,3 +803,19 @@ def test_string_to_decimal_type_invalid_value():
with pytest.raises(ValueError) as e:
_ = literal("18.15").to(DecimalType(10, 0))
assert "Could not convert 18.15 into a decimal(10, 0), scales differ 0 <> 2" in str(e.value)
+
+
+# __ __ ___
+# | \/ |_ _| _ \_ _
+# | |\/| | || | _/ || |
+# |_| |_|\_, |_| \_, |
+# |__/ |__/
+
+assert_type(literal("str"), Literal[str])
+assert_type(literal(True), Literal[bool])
+assert_type(literal(123), Literal[int])
+assert_type(literal(123.4), Literal[float])
+assert_type(literal(uuid.UUID("f79c3e09-677c-4bbd-a479-3f349cb785e7")), Literal[uuid.UUID])
+assert_type(literal(bytes([0x01, 0x02, 0x03])), Literal[bytes])
+assert_type(literal(Decimal("19.25")), Literal[Decimal])
+assert_type({literal(1), literal(2), literal(3)}, Set[Literal[int]])
diff --git a/python/tests/expressions/test_visitors.py b/python/tests/expressions/test_visitors.py
index fd91e8a219..62407013fc 100644
--- a/python/tests/expressions/test_visitors.py
+++ b/python/tests/expressions/test_visitors.py
@@ -34,16 +34,12 @@ from pyiceberg.expressions import (
BoundIsNull,
BoundLessThan,
BoundLessThanOrEqual,
- BoundLiteralPredicate,
BoundNotEqualTo,
BoundNotIn,
BoundNotNaN,
BoundNotNull,
- BoundPredicate,
BoundReference,
- BoundSetPredicate,
BoundTerm,
- BoundUnaryPredicate,
EqualTo,
GreaterThan,
GreaterThanOrEqual,
@@ -52,7 +48,6 @@ from pyiceberg.expressions import (
IsNull,
LessThan,
LessThanOrEqual,
- LiteralPredicate,
Not,
NotEqualTo,
NotIn,
@@ -60,16 +55,8 @@ from pyiceberg.expressions import (
NotNull,
Or,
Reference,
- SetPredicate,
- UnaryPredicate,
- UnboundPredicate,
-)
-from pyiceberg.expressions.literals import (
- Literal,
- LongLiteral,
- StringLiteral,
- literal,
)
+from pyiceberg.expressions.literals import Literal, literal
from pyiceberg.expressions.visitors import (
BindVisitor,
BooleanExpressionVisitor,
@@ -289,13 +276,14 @@ def test_boolean_expression_visit_raise_not_implemented_error():
def test_bind_visitor_already_bound(table_schema_simple: Schema):
- bound = BoundEqualTo(
- BoundReference(table_schema_simple.find_field(1), table_schema_simple.accessor_for_field(1)), literal("hello")
+ bound = BoundEqualTo[str](
+ term=BoundReference(table_schema_simple.find_field(1), table_schema_simple.accessor_for_field(1)),
+ literal=literal("hello"),
)
with pytest.raises(TypeError) as exc_info:
- BindVisitor(visit(bound, visitor=BindVisitor(schema=table_schema_simple))) # type: ignore
+ visit(bound, visitor=BindVisitor(schema=table_schema_simple))
assert (
- "Found already bound predicate: BoundEqualTo(term=BoundReference(field=NestedField(field_id=1, name='foo', field_type=StringType(), required=False), accessor=Accessor(position=0,inner=None)), literal=StringLiteral(hello))"
+ "Found already bound predicate: BoundEqualTo(term=BoundReference(field=NestedField(field_id=1, name='foo', field_type=StringType(), required=False), accessor=Accessor(position=0,inner=None)), literal=literal('hello'))"
== str(exc_info.value)
)
@@ -339,61 +327,61 @@ def test_always_false_or_always_true_expression_binding(table_schema_simple: Sch
[
(
And(
- In(Reference("foo"), (literal("foo"), literal("bar"))),
- In(Reference("bar"), (literal(1), literal(2), literal(3))),
+ In(Reference("foo"), {"foo", "bar"}),
+ In(Reference("bar"), {1, 2, 3}),
),
And(
- BoundIn[str](
+ BoundIn(
BoundReference(
field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
accessor=Accessor(position=0, inner=None),
),
- {StringLiteral("foo"), StringLiteral("bar")},
+ {literal("foo"), literal("bar")},
),
BoundIn[int](
BoundReference(
field=NestedField(field_id=2, name="bar", field_type=IntegerType(), required=True),
accessor=Accessor(position=1, inner=None),
),
- {LongLiteral(1), LongLiteral(2), LongLiteral(3)},
+ {literal(1), literal(2), literal(3)},
),
),
),
(
And(
- In(Reference("foo"), (literal("bar"), literal("baz"))),
+ In(Reference("foo"), ("bar", "baz")),
In(
Reference("bar"),
- (literal(1),),
+ (1,),
),
In(
Reference("foo"),
- (literal("baz"),),
+ ("baz",),
),
),
And(
And(
- BoundIn[str](
+ BoundIn(
BoundReference(
field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
accessor=Accessor(position=0, inner=None),
),
- {StringLiteral("bar"), StringLiteral("baz")},
+ {literal("bar"), literal("baz")},
),
BoundEqualTo[int](
BoundReference(
field=NestedField(field_id=2, name="bar", field_type=IntegerType(), required=True),
accessor=Accessor(position=1, inner=None),
),
- LongLiteral(1),
+ literal(1),
),
),
- BoundEqualTo[str](
+ BoundEqualTo(
BoundReference(
field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
accessor=Accessor(position=0, inner=None),
),
- StringLiteral("baz"),
+ literal("baz"),
),
),
),
@@ -410,61 +398,61 @@ def test_and_expression_binding(unbound_and_expression, expected_bound_expressio
[
(
Or(
- In(Reference("foo"), (literal("foo"), literal("bar"))),
- In(Reference("bar"), (literal(1), literal(2), literal(3))),
+ In(Reference("foo"), ("foo", "bar")),
+ In(Reference("bar"), (1, 2, 3)),
),
Or(
- BoundIn[str](
+ BoundIn(
BoundReference(
field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
accessor=Accessor(position=0, inner=None),
),
- {StringLiteral("foo"), StringLiteral("bar")},
+ {literal("foo"), literal("bar")},
),
BoundIn[int](
BoundReference(
field=NestedField(field_id=2, name="bar", field_type=IntegerType(), required=True),
accessor=Accessor(position=1, inner=None),
),
- {LongLiteral(1), LongLiteral(2), LongLiteral(3)},
+ {literal(1), literal(2), literal(3)},
),
),
),
(
Or(
- In(Reference("foo"), (literal("bar"), literal("baz"))),
+ In(Reference("foo"), ("bar", "baz")),
In(
Reference("foo"),
- (literal("bar"),),
+ ("bar",),
),
In(
Reference("foo"),
- (literal("baz"),),
+ ("baz",),
),
),
Or(
Or(
- BoundIn[str](
+ BoundIn(
BoundReference(
field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
accessor=Accessor(position=0, inner=None),
),
- {StringLiteral("bar"), StringLiteral("baz")},
+ {literal("bar"), literal("baz")},
),
- BoundIn[str](
+ BoundIn(
BoundReference(
field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
accessor=Accessor(position=0, inner=None),
),
- {StringLiteral("bar")},
+ {literal("bar")},
),
),
- BoundIn[str](
+ BoundIn(
BoundReference(
field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
accessor=Accessor(position=0, inner=None),
),
- {StringLiteral("baz")},
+ {literal("baz")},
),
),
),
@@ -501,36 +489,36 @@ def test_or_expression_binding(unbound_or_expression, expected_bound_expression,
"unbound_in_expression,expected_bound_expression",
[
(
- In(Reference("foo"), (literal("foo"), literal("bar"))),
- BoundIn[str](
- BoundReference[str](
+ In(Reference("foo"), ("foo", "bar")),
+ BoundIn(
+ BoundReference(
field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
accessor=Accessor(position=0, inner=None),
),
- {StringLiteral("foo"), StringLiteral("bar")},
+ {literal("foo"), literal("bar")},
),
),
(
- In(Reference("foo"), (literal("bar"), literal("baz"))),
- BoundIn[str](
- BoundReference[str](
+ In(Reference("foo"), ("bar", "baz")),
+ BoundIn(
+ BoundReference(
field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
accessor=Accessor(position=0, inner=None),
),
- {StringLiteral("bar"), StringLiteral("baz")},
+ {literal("bar"), literal("baz")},
),
),
(
In(
Reference("foo"),
- (literal("bar"),),
+ ("bar",),
),
BoundEqualTo(
- BoundReference[str](
+ BoundReference(
field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
accessor=Accessor(position=0, inner=None),
),
- StringLiteral("bar"),
+ literal("bar"),
),
),
],
@@ -545,39 +533,39 @@ def test_in_expression_binding(unbound_in_expression, expected_bound_expression,
"unbound_not_expression,expected_bound_expression",
[
(
- Not(In(Reference("foo"), (literal("foo"), literal("bar")))),
+ Not(In(Reference("foo"), ("foo", "bar"))),
Not(
- BoundIn[str](
- BoundReference[str](
+ BoundIn(
+ BoundReference(
field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
accessor=Accessor(position=0, inner=None),
),
- {StringLiteral("foo"), StringLiteral("bar")},
+ {literal("foo"), literal("bar")},
)
),
),
(
Not(
Or(
- In(Reference("foo"), (literal("foo"), literal("bar"))),
- In(Reference("foo"), (literal("foo"), literal("bar"), literal("baz"))),
+ In(Reference("foo"), ("foo", "bar")),
+ In(Reference("foo"), ("foo", "bar", "baz")),
)
),
Not(
Or(
- BoundIn[str](
+ BoundIn(
BoundReference(
field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
accessor=Accessor(position=0, inner=None),
),
- {StringLiteral("foo"), StringLiteral("bar")},
+ {literal("foo"), literal("bar")},
),
- BoundIn[str](
+ BoundIn(
BoundReference(
field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
accessor=Accessor(position=0, inner=None),
),
- {StringLiteral("foo"), StringLiteral("bar"), StringLiteral("baz")},
+ {literal("foo"), literal("bar"), literal("baz")},
),
),
),
@@ -593,19 +581,19 @@ def test_not_expression_binding(unbound_not_expression, expected_bound_expressio
def test_bound_boolean_expression_visitor_and_in():
"""Test visiting an And and In expression with a bound boolean expression visitor"""
bound_expression = And(
- BoundIn[str](
+ BoundIn(
term=BoundReference(
field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
accessor=Accessor(position=0, inner=None),
),
- literals=(StringLiteral("foo"), StringLiteral("bar")),
+ literals={literal("foo"), literal("bar")},
),
- BoundIn[str](
+ BoundIn(
term=BoundReference(
field=NestedField(field_id=2, name="bar", field_type=StringType(), required=False),
accessor=Accessor(position=1, inner=None),
),
- literals=(StringLiteral("baz"), StringLiteral("qux")),
+ literals={literal("baz"), literal("qux")},
),
)
visitor = FooBoundBooleanExpressionVisitor()
@@ -617,21 +605,21 @@ def test_bound_boolean_expression_visitor_or():
"""Test visiting an Or expression with a bound boolean expression visitor"""
bound_expression = Or(
Not(
- BoundIn[str](
- BoundReference[str](
+ BoundIn(
+ BoundReference(
field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
accessor=Accessor(position=0, inner=None),
),
- {StringLiteral("foo"), StringLiteral("bar")},
+ {literal("foo"), literal("bar")},
)
),
Not(
- BoundIn[str](
- BoundReference[str](
+ BoundIn(
+ BoundReference(
field=NestedField(field_id=2, name="bar", field_type=StringType(), required=False),
accessor=Accessor(position=1, inner=None),
),
- {StringLiteral("baz"), StringLiteral("qux")},
+ {literal("baz"), literal("qux")},
)
),
)
@@ -641,12 +629,12 @@ def test_bound_boolean_expression_visitor_or():
def test_bound_boolean_expression_visitor_equal():
- bound_expression = BoundEqualTo[str](
+ bound_expression = BoundEqualTo(
term=BoundReference(
field=NestedField(field_id=2, name="bar", field_type=StringType(), required=False),
accessor=Accessor(position=1, inner=None),
),
- literal=StringLiteral("foo"),
+ literal=literal("foo"),
)
visitor = FooBoundBooleanExpressionVisitor()
result = visit(bound_expression, visitor=visitor)
@@ -654,12 +642,12 @@ def test_bound_boolean_expression_visitor_equal():
def test_bound_boolean_expression_visitor_not_equal():
- bound_expression = BoundNotEqualTo[str](
+ bound_expression = BoundNotEqualTo(
term=BoundReference(
field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
accessor=Accessor(position=0, inner=None),
),
- literal=StringLiteral("foo"),
+ literal=literal("foo"),
)
visitor = FooBoundBooleanExpressionVisitor()
result = visit(bound_expression, visitor=visitor)
@@ -681,12 +669,12 @@ def test_bound_boolean_expression_visitor_always_false():
def test_bound_boolean_expression_visitor_in():
- bound_expression = BoundIn[str](
+ bound_expression = BoundIn(
term=BoundReference(
field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
accessor=Accessor(position=0, inner=None),
),
- literals=(StringLiteral("foo"), StringLiteral("bar")),
+ literals={literal("foo"), literal("bar")},
)
visitor = FooBoundBooleanExpressionVisitor()
result = visit(bound_expression, visitor=visitor)
@@ -694,12 +682,12 @@ def test_bound_boolean_expression_visitor_in():
def test_bound_boolean_expression_visitor_not_in():
- bound_expression = BoundNotIn[str](
+ bound_expression = BoundNotIn(
term=BoundReference(
field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
accessor=Accessor(position=0, inner=None),
),
- literals=(StringLiteral("foo"), StringLiteral("bar")),
+ literals={literal("foo"), literal("bar")},
)
visitor = FooBoundBooleanExpressionVisitor()
result = visit(bound_expression, visitor=visitor)
@@ -707,7 +695,7 @@ def test_bound_boolean_expression_visitor_not_in():
def test_bound_boolean_expression_visitor_is_nan():
- bound_expression = BoundIsNaN[str](
+ bound_expression = BoundIsNaN(
term=BoundReference(
field=NestedField(field_id=3, name="baz", field_type=FloatType(), required=False),
accessor=Accessor(position=0, inner=None),
@@ -719,7 +707,7 @@ def test_bound_boolean_expression_visitor_is_nan():
def test_bound_boolean_expression_visitor_not_nan():
- bound_expression = BoundNotNaN[str](
+ bound_expression = BoundNotNaN(
term=BoundReference(
field=NestedField(field_id=3, name="baz", field_type=FloatType(), required=False),
accessor=Accessor(position=0, inner=None),
@@ -731,7 +719,7 @@ def test_bound_boolean_expression_visitor_not_nan():
def test_bound_boolean_expression_visitor_is_null():
- bound_expression = BoundIsNull[str](
+ bound_expression = BoundIsNull(
term=BoundReference(
field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
accessor=Accessor(position=0, inner=None),
@@ -743,7 +731,7 @@ def test_bound_boolean_expression_visitor_is_null():
def test_bound_boolean_expression_visitor_not_null():
- bound_expression = BoundNotNull[str](
+ bound_expression = BoundNotNull(
term=BoundReference(
field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
accessor=Accessor(position=0, inner=None),
@@ -755,12 +743,12 @@ def test_bound_boolean_expression_visitor_not_null():
def test_bound_boolean_expression_visitor_greater_than():
- bound_expression = BoundGreaterThan[str](
+ bound_expression = BoundGreaterThan(
term=BoundReference(
field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
accessor=Accessor(position=0, inner=None),
),
- literal=StringLiteral("foo"),
+ literal=literal("foo"),
)
visitor = FooBoundBooleanExpressionVisitor()
result = visit(bound_expression, visitor=visitor)
@@ -768,12 +756,12 @@ def test_bound_boolean_expression_visitor_greater_than():
def test_bound_boolean_expression_visitor_greater_than_or_equal():
- bound_expression = BoundGreaterThanOrEqual[str](
+ bound_expression = BoundGreaterThanOrEqual(
term=BoundReference(
field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
accessor=Accessor(position=0, inner=None),
),
- literal=StringLiteral("foo"),
+ literal=literal("foo"),
)
visitor = FooBoundBooleanExpressionVisitor()
result = visit(bound_expression, visitor=visitor)
@@ -781,12 +769,12 @@ def test_bound_boolean_expression_visitor_greater_than_or_equal():
def test_bound_boolean_expression_visitor_less_than():
- bound_expression = BoundLessThan[str](
+ bound_expression = BoundLessThan(
term=BoundReference(
field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
accessor=Accessor(position=0, inner=None),
),
- literal=StringLiteral("foo"),
+ literal=literal("foo"),
)
visitor = FooBoundBooleanExpressionVisitor()
result = visit(bound_expression, visitor=visitor)
@@ -794,12 +782,12 @@ def test_bound_boolean_expression_visitor_less_than():
def test_bound_boolean_expression_visitor_less_than_or_equal():
- bound_expression = BoundLessThanOrEqual[str](
+ bound_expression = BoundLessThanOrEqual(
term=BoundReference(
field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
accessor=Accessor(position=0, inner=None),
),
- literal=StringLiteral("foo"),
+ literal=literal("foo"),
)
visitor = FooBoundBooleanExpressionVisitor()
result = visit(bound_expression, visitor=visitor)
@@ -807,9 +795,9 @@ def test_bound_boolean_expression_visitor_less_than_or_equal():
def test_bound_boolean_expression_visitor_raise_on_unbound_predicate():
- bound_expression = LessThanOrEqual[str](
+ bound_expression = LessThanOrEqual(
term=Reference("foo"),
- literal=StringLiteral("foo"),
+ literal="foo",
)
visitor = FooBoundBooleanExpressionVisitor()
with pytest.raises(TypeError) as exc_info:
@@ -1047,16 +1035,16 @@ def test_not_nan(schema: Schema, manifest: ManifestFile) -> None:
def test_missing_stats(schema: Schema, manifest_no_stats: ManifestFile):
expressions: List[BooleanExpression] = [
- LessThan(Reference[int]("id"), LongLiteral(5)),
- LessThanOrEqual(Reference[int]("id"), LongLiteral(30)),
- EqualTo(Reference[int]("id"), LongLiteral(70)),
- GreaterThan(Reference[int]("id"), LongLiteral(78)),
- GreaterThanOrEqual(Reference[int]("id"), LongLiteral(90)),
- NotEqualTo(Reference[int]("id"), LongLiteral(101)),
- IsNull(Reference[int]("id")),
- NotNull(Reference[int]("id")),
- IsNaN(Reference[float]("float")),
- NotNaN(Reference[float]("float")),
+ LessThan(Reference("id"), 5),
+ LessThanOrEqual(Reference("id"), 30),
+ EqualTo(Reference("id"), 70),
+ GreaterThan(Reference("id"), 78),
+ GreaterThanOrEqual(Reference("id"), 90),
+ NotEqualTo(Reference("id"), 101),
+ IsNull(Reference("id")),
+ NotNull(Reference("id")),
+ IsNaN(Reference("float")),
+ NotNaN(Reference("float")),
]
for expr in expressions:
@@ -1064,11 +1052,11 @@ def test_missing_stats(schema: Schema, manifest_no_stats: ManifestFile):
def test_not(schema: Schema, manifest: ManifestFile):
- assert _ManifestEvalVisitor(schema, Not(LessThan(Reference[int]("id"), LongLiteral(INT_MIN_VALUE - 25)))).eval(
+ assert _ManifestEvalVisitor(schema, Not(LessThan(Reference("id"), INT_MIN_VALUE - 25))).eval(
manifest
), "Should read: not(false)"
- assert not _ManifestEvalVisitor(schema, Not(GreaterThan(Reference[int]("id"), LongLiteral(INT_MIN_VALUE - 25)))).eval(
+ assert not _ManifestEvalVisitor(schema, Not(GreaterThan(Reference("id"), INT_MIN_VALUE - 25))).eval(
manifest
), "Should skip: not(true)"
@@ -1077,24 +1065,24 @@ def test_and(schema: Schema, manifest: ManifestFile):
assert not _ManifestEvalVisitor(
schema,
And(
- LessThan(Reference[int]("id"), LongLiteral(INT_MIN_VALUE - 25)),
- GreaterThanOrEqual(Reference[int]("id"), LongLiteral(INT_MIN_VALUE - 30)),
+ LessThan(Reference("id"), INT_MIN_VALUE - 25),
+ GreaterThanOrEqual(Reference("id"), INT_MIN_VALUE - 30),
),
).eval(manifest), "Should skip: and(false, true)"
assert not _ManifestEvalVisitor(
schema,
And(
- LessThan(Reference[int]("id"), LongLiteral(INT_MIN_VALUE - 25)),
- GreaterThanOrEqual(Reference[int]("id"), LongLiteral(INT_MAX_VALUE + 1)),
+ LessThan(Reference("id"), INT_MIN_VALUE - 25),
+ GreaterThanOrEqual(Reference("id"), INT_MAX_VALUE + 1),
),
).eval(manifest), "Should skip: and(false, false)"
assert _ManifestEvalVisitor(
schema,
And(
- GreaterThan(Reference[int]("id"), LongLiteral(INT_MIN_VALUE - 25)),
- LessThanOrEqual(Reference[int]("id"), LongLiteral(INT_MIN_VALUE)),
+ GreaterThan(Reference("id"), INT_MIN_VALUE - 25),
+ LessThanOrEqual(Reference("id"), INT_MIN_VALUE),
),
).eval(manifest), "Should read: and(true, true)"
@@ -1103,386 +1091,317 @@ def test_or(schema: Schema, manifest: ManifestFile):
assert not _ManifestEvalVisitor(
schema,
Or(
- LessThan(Reference[int]("id"), LongLiteral(INT_MIN_VALUE - 25)),
- GreaterThanOrEqual(Reference[int]("id"), LongLiteral(INT_MAX_VALUE + 1)),
+ LessThan(Reference("id"), INT_MIN_VALUE - 25),
+ GreaterThanOrEqual(Reference("id"), INT_MAX_VALUE + 1),
),
).eval(manifest), "Should skip: or(false, false)"
assert _ManifestEvalVisitor(
schema,
Or(
- LessThan(Reference[int]("id"), LongLiteral(INT_MIN_VALUE - 25)),
- GreaterThanOrEqual(Reference[int]("id"), LongLiteral(INT_MAX_VALUE - 19)),
+ LessThan(Reference("id"), INT_MIN_VALUE - 25),
+ GreaterThanOrEqual(Reference("id"), INT_MAX_VALUE - 19),
),
).eval(manifest), "Should read: or(false, true)"
def test_integer_lt(schema: Schema, manifest: ManifestFile):
- assert not _ManifestEvalVisitor(schema, LessThan(Reference[int]("id"), LongLiteral(INT_MIN_VALUE - 25))).eval(
+ assert not _ManifestEvalVisitor(schema, LessThan(Reference("id"), INT_MIN_VALUE - 25)).eval(
manifest
), "Should not read: id range below lower bound (5 < 30)"
- assert not _ManifestEvalVisitor(schema, LessThan(Reference[int]("id"), LongLiteral(INT_MIN_VALUE))).eval(
+ assert not _ManifestEvalVisitor(schema, LessThan(Reference("id"), INT_MIN_VALUE)).eval(
manifest
), "Should not read: id range below lower bound (30 is not < 30)"
- assert _ManifestEvalVisitor(schema, LessThan(Reference[int]("id"), LongLiteral(INT_MIN_VALUE + 1))).eval(
+ assert _ManifestEvalVisitor(schema, LessThan(Reference("id"), INT_MIN_VALUE + 1)).eval(
manifest
), "Should read: one possible id"
- assert _ManifestEvalVisitor(schema, LessThan(Reference[int]("id"), LongLiteral(INT_MAX_VALUE))).eval(
- manifest
- ), "Should read: may possible ids"
+ assert _ManifestEvalVisitor(schema, LessThan(Reference("id"), INT_MAX_VALUE)).eval(manifest), "Should read: may possible ids"
def test_integer_lt_eq(schema: Schema, manifest: ManifestFile):
- assert not _ManifestEvalVisitor(schema, LessThanOrEqual(Reference[int]("id"), LongLiteral(INT_MIN_VALUE - 25))).eval(
+ assert not _ManifestEvalVisitor(schema, LessThanOrEqual(Reference("id"), INT_MIN_VALUE - 25)).eval(
manifest
), "Should not read: id range below lower bound (5 < 30)"
- assert not _ManifestEvalVisitor(schema, LessThanOrEqual(Reference[int]("id"), LongLiteral(INT_MIN_VALUE - 1))).eval(
+ assert not _ManifestEvalVisitor(schema, LessThanOrEqual(Reference("id"), INT_MIN_VALUE - 1)).eval(
manifest
), "Should not read: id range below lower bound (29 < 30)"
- assert _ManifestEvalVisitor(schema, LessThanOrEqual(Reference[int]("id"), LongLiteral(INT_MIN_VALUE))).eval(
+ assert _ManifestEvalVisitor(schema, LessThanOrEqual(Reference("id"), INT_MIN_VALUE)).eval(
manifest
), "Should read: one possible id"
- assert _ManifestEvalVisitor(schema, LessThanOrEqual(Reference[int]("id"), LongLiteral(INT_MAX_VALUE))).eval(
+ assert _ManifestEvalVisitor(schema, LessThanOrEqual(Reference("id"), INT_MAX_VALUE)).eval(
manifest
), "Should read: many possible ids"
def test_integer_gt(schema: Schema, manifest: ManifestFile):
- assert not _ManifestEvalVisitor(schema, GreaterThan(Reference[int]("id"), LongLiteral(INT_MAX_VALUE + 6))).eval(
+ assert not _ManifestEvalVisitor(schema, GreaterThan(Reference("id"), INT_MAX_VALUE + 6)).eval(
manifest
), "Should not read: id range above upper bound (85 < 79)"
- assert not _ManifestEvalVisitor(schema, GreaterThan(Reference[int]("id"), LongLiteral(INT_MAX_VALUE))).eval(
+ assert not _ManifestEvalVisitor(schema, GreaterThan(Reference("id"), INT_MAX_VALUE)).eval(
manifest
), "Should not read: id range above upper bound (79 is not > 79)"
- assert _ManifestEvalVisitor(schema, GreaterThan(Reference[int]("id"), LongLiteral(INT_MAX_VALUE - 1))).eval(
+ assert _ManifestEvalVisitor(schema, GreaterThan(Reference("id"), INT_MAX_VALUE - 1)).eval(
manifest
), "Should read: one possible id"
- assert _ManifestEvalVisitor(schema, GreaterThan(Reference[int]("id"), LongLiteral(INT_MAX_VALUE - 4))).eval(
+ assert _ManifestEvalVisitor(schema, GreaterThan(Reference("id"), INT_MAX_VALUE - 4)).eval(
manifest
), "Should read: may possible ids"
def test_integer_gt_eq(schema: Schema, manifest: ManifestFile):
- assert not _ManifestEvalVisitor(schema, GreaterThanOrEqual(Reference[int]("id"), LongLiteral(INT_MAX_VALUE + 6))).eval(
+ assert not _ManifestEvalVisitor(schema, GreaterThanOrEqual(Reference("id"), INT_MAX_VALUE + 6)).eval(
manifest
), "Should not read: id range above upper bound (85 < 79)"
- assert not _ManifestEvalVisitor(schema, GreaterThanOrEqual(Reference[int]("id"), LongLiteral(INT_MAX_VALUE + 1))).eval(
+ assert not _ManifestEvalVisitor(schema, GreaterThanOrEqual(Reference("id"), INT_MAX_VALUE + 1)).eval(
manifest
), "Should not read: id range above upper bound (80 > 79)"
- assert _ManifestEvalVisitor(schema, GreaterThanOrEqual(Reference[int]("id"), LongLiteral(INT_MAX_VALUE))).eval(
+ assert _ManifestEvalVisitor(schema, GreaterThanOrEqual(Reference("id"), INT_MAX_VALUE)).eval(
manifest
), "Should read: one possible id"
- assert _ManifestEvalVisitor(schema, GreaterThanOrEqual(Reference[int]("id"), LongLiteral(INT_MAX_VALUE))).eval(
+ assert _ManifestEvalVisitor(schema, GreaterThanOrEqual(Reference("id"), INT_MAX_VALUE)).eval(
manifest
), "Should read: may possible ids"
def test_integer_eq(schema: Schema, manifest: ManifestFile):
- assert not _ManifestEvalVisitor(schema, EqualTo(Reference[int]("id"), LongLiteral(INT_MIN_VALUE - 25))).eval(
+ assert not _ManifestEvalVisitor(schema, EqualTo(Reference("id"), INT_MIN_VALUE - 25)).eval(
manifest
), "Should not read: id below lower bound"
- assert not _ManifestEvalVisitor(schema, EqualTo(Reference[int]("id"), LongLiteral(INT_MIN_VALUE - 1))).eval(
+ assert not _ManifestEvalVisitor(schema, EqualTo(Reference("id"), INT_MIN_VALUE - 1)).eval(
manifest
), "Should not read: id below lower bound"
- assert _ManifestEvalVisitor(schema, EqualTo(Reference[int]("id"), LongLiteral(INT_MIN_VALUE))).eval(
+ assert _ManifestEvalVisitor(schema, EqualTo(Reference("id"), INT_MIN_VALUE)).eval(
manifest
), "Should read: id equal to lower bound"
- assert _ManifestEvalVisitor(schema, EqualTo(Reference[int]("id"), LongLiteral(INT_MAX_VALUE - 4))).eval(
+ assert _ManifestEvalVisitor(schema, EqualTo(Reference("id"), INT_MAX_VALUE - 4)).eval(
manifest
), "Should read: id between lower and upper bounds"
- assert _ManifestEvalVisitor(schema, EqualTo(Reference[int]("id"), LongLiteral(INT_MAX_VALUE))).eval(
+ assert _ManifestEvalVisitor(schema, EqualTo(Reference("id"), INT_MAX_VALUE)).eval(
manifest
), "Should read: id equal to upper bound"
- assert not _ManifestEvalVisitor(schema, EqualTo(Reference[int]("id"), LongLiteral(INT_MAX_VALUE + 1))).eval(
+ assert not _ManifestEvalVisitor(schema, EqualTo(Reference("id"), INT_MAX_VALUE + 1)).eval(
manifest
), "Should not read: id above upper bound"
- assert not _ManifestEvalVisitor(schema, EqualTo(Reference[int]("id"), LongLiteral(INT_MAX_VALUE + 6))).eval(
+ assert not _ManifestEvalVisitor(schema, EqualTo(Reference("id"), INT_MAX_VALUE + 6)).eval(
manifest
), "Should not read: id above upper bound"
def test_integer_not_eq(schema: Schema, manifest: ManifestFile):
- assert _ManifestEvalVisitor(schema, NotEqualTo(Reference[int]("id"), LongLiteral(INT_MIN_VALUE - 25))).eval(
+ assert _ManifestEvalVisitor(schema, NotEqualTo(Reference("id"), INT_MIN_VALUE - 25)).eval(
manifest
), "Should read: id below lower bound"
- assert _ManifestEvalVisitor(schema, NotEqualTo(Reference[int]("id"), LongLiteral(INT_MIN_VALUE - 1))).eval(
+ assert _ManifestEvalVisitor(schema, NotEqualTo(Reference("id"), INT_MIN_VALUE - 1)).eval(
manifest
), "Should read: id below lower bound"
- assert _ManifestEvalVisitor(schema, NotEqualTo(Reference[int]("id"), LongLiteral(INT_MIN_VALUE))).eval(
+ assert _ManifestEvalVisitor(schema, NotEqualTo(Reference("id"), INT_MIN_VALUE)).eval(
manifest
), "Should read: id equal to lower bound"
- assert _ManifestEvalVisitor(schema, NotEqualTo(Reference[int]("id"), LongLiteral(INT_MAX_VALUE - 4))).eval(
+ assert _ManifestEvalVisitor(schema, NotEqualTo(Reference("id"), INT_MAX_VALUE - 4)).eval(
manifest
), "Should read: id between lower and upper bounds"
- assert _ManifestEvalVisitor(schema, NotEqualTo(Reference[int]("id"), LongLiteral(INT_MAX_VALUE))).eval(
+ assert _ManifestEvalVisitor(schema, NotEqualTo(Reference("id"), INT_MAX_VALUE)).eval(
manifest
), "Should read: id equal to upper bound"
- assert _ManifestEvalVisitor(schema, NotEqualTo(Reference[int]("id"), LongLiteral(INT_MAX_VALUE + 1))).eval(
+ assert _ManifestEvalVisitor(schema, NotEqualTo(Reference("id"), INT_MAX_VALUE + 1)).eval(
manifest
), "Should read: id above upper bound"
- assert _ManifestEvalVisitor(schema, NotEqualTo(Reference[int]("id"), LongLiteral(INT_MAX_VALUE + 6))).eval(
+ assert _ManifestEvalVisitor(schema, NotEqualTo(Reference("id"), INT_MAX_VALUE + 6)).eval(
manifest
), "Should read: id above upper bound"
def test_integer_not_eq_rewritten(schema: Schema, manifest: ManifestFile):
- assert _ManifestEvalVisitor(schema, Not(EqualTo(Reference[int]("id"), LongLiteral(INT_MIN_VALUE - 25)))).eval(
+ assert _ManifestEvalVisitor(schema, Not(EqualTo(Reference("id"), INT_MIN_VALUE - 25))).eval(
manifest
), "Should read: id below lower bound"
- assert _ManifestEvalVisitor(schema, Not(EqualTo(Reference[int]("id"), LongLiteral(INT_MIN_VALUE - 1)))).eval(
+ assert _ManifestEvalVisitor(schema, Not(EqualTo(Reference("id"), INT_MIN_VALUE - 1))).eval(
manifest
), "Should read: id below lower bound"
- assert _ManifestEvalVisitor(schema, Not(EqualTo(Reference[int]("id"), LongLiteral(INT_MIN_VALUE)))).eval(
+ assert _ManifestEvalVisitor(schema, Not(EqualTo(Reference("id"), INT_MIN_VALUE))).eval(
manifest
), "Should read: id equal to lower bound"
- assert _ManifestEvalVisitor(schema, Not(EqualTo(Reference[int]("id"), LongLiteral(INT_MAX_VALUE - 4)))).eval(
+ assert _ManifestEvalVisitor(schema, Not(EqualTo(Reference("id"), INT_MAX_VALUE - 4))).eval(
manifest
), "Should read: id between lower and upper bounds"
- assert _ManifestEvalVisitor(schema, Not(EqualTo(Reference[int]("id"), LongLiteral(INT_MAX_VALUE)))).eval(
+ assert _ManifestEvalVisitor(schema, Not(EqualTo(Reference("id"), INT_MAX_VALUE))).eval(
manifest
), "Should read: id equal to upper bound"
- assert _ManifestEvalVisitor(schema, Not(EqualTo(Reference[int]("id"), LongLiteral(INT_MAX_VALUE + 1)))).eval(
+ assert _ManifestEvalVisitor(schema, Not(EqualTo(Reference("id"), INT_MAX_VALUE + 1))).eval(
manifest
), "Should read: id above upper bound"
- assert _ManifestEvalVisitor(schema, Not(EqualTo(Reference[int]("id"), LongLiteral(INT_MAX_VALUE + 6)))).eval(
+ assert _ManifestEvalVisitor(schema, Not(EqualTo(Reference("id"), INT_MAX_VALUE + 6))).eval(
manifest
), "Should read: id above upper bound"
def test_integer_not_eq_rewritten_case_insensitive(schema: Schema, manifest: ManifestFile):
- assert _ManifestEvalVisitor(
- schema, Not(EqualTo(Reference[int]("ID"), LongLiteral(INT_MIN_VALUE - 25))), case_sensitive=False
- ).eval(manifest), "Should read: id below lower bound"
+ assert _ManifestEvalVisitor(schema, Not(EqualTo(Reference("ID"), INT_MIN_VALUE - 25)), case_sensitive=False).eval(
+ manifest
+ ), "Should read: id below lower bound"
- assert _ManifestEvalVisitor(
- schema, Not(EqualTo(Reference[int]("ID"), LongLiteral(INT_MIN_VALUE - 1))), case_sensitive=False
- ).eval(manifest), "Should read: id below lower bound"
+ assert _ManifestEvalVisitor(schema, Not(EqualTo(Reference("ID"), INT_MIN_VALUE - 1)), case_sensitive=False).eval(
+ manifest
+ ), "Should read: id below lower bound"
- assert _ManifestEvalVisitor(
- schema, Not(EqualTo(Reference[int]("ID"), LongLiteral(INT_MIN_VALUE))), case_sensitive=False
- ).eval(manifest), "Should read: id equal to lower bound"
+ assert _ManifestEvalVisitor(schema, Not(EqualTo(Reference("ID"), INT_MIN_VALUE)), case_sensitive=False).eval(
+ manifest
+ ), "Should read: id equal to lower bound"
- assert _ManifestEvalVisitor(
- schema, Not(EqualTo(Reference[int]("ID"), LongLiteral(INT_MAX_VALUE - 4))), case_sensitive=False
- ).eval(manifest), "Should read: id between lower and upper bounds"
+ assert _ManifestEvalVisitor(schema, Not(EqualTo(Reference("ID"), INT_MAX_VALUE - 4)), case_sensitive=False).eval(
+ manifest
+ ), "Should read: id between lower and upper bounds"
- assert _ManifestEvalVisitor(
- schema, Not(EqualTo(Reference[int]("ID"), LongLiteral(INT_MAX_VALUE))), case_sensitive=False
- ).eval(manifest), "Should read: id equal to upper bound"
+ assert _ManifestEvalVisitor(schema, Not(EqualTo(Reference("ID"), INT_MAX_VALUE)), case_sensitive=False).eval(
+ manifest
+ ), "Should read: id equal to upper bound"
- assert _ManifestEvalVisitor(
- schema, Not(EqualTo(Reference[int]("ID"), LongLiteral(INT_MAX_VALUE + 1))), case_sensitive=False
- ).eval(manifest), "Should read: id above upper bound"
+ assert _ManifestEvalVisitor(schema, Not(EqualTo(Reference("ID"), INT_MAX_VALUE + 1)), case_sensitive=False).eval(
+ manifest
+ ), "Should read: id above upper bound"
- assert _ManifestEvalVisitor(
- schema, Not(EqualTo(Reference[int]("ID"), LongLiteral(INT_MAX_VALUE + 6))), case_sensitive=False
- ).eval(manifest), "Should read: id above upper bound"
+ assert _ManifestEvalVisitor(schema, Not(EqualTo(Reference("ID"), INT_MAX_VALUE + 6)), case_sensitive=False).eval(
+ manifest
+ ), "Should read: id above upper bound"
def test_integer_in(schema: Schema, manifest: ManifestFile):
- assert not _ManifestEvalVisitor(
- schema, In(Reference[int]("id"), (LongLiteral(INT_MIN_VALUE - 25), LongLiteral(INT_MIN_VALUE - 24)))
- ).eval(manifest), "Should not read: id below lower bound (5 < 30, 6 < 30)"
+ assert not _ManifestEvalVisitor(schema, In(Reference("id"), (INT_MIN_VALUE - 25, INT_MIN_VALUE - 24))).eval(
+ manifest
+ ), "Should not read: id below lower bound (5 < 30, 6 < 30)"
- assert not _ManifestEvalVisitor(
- schema, In(Reference[int]("id"), (LongLiteral(INT_MIN_VALUE - 2), LongLiteral(INT_MIN_VALUE - 1)))
- ).eval(manifest), "Should not read: id below lower bound (28 < 30, 29 < 30)"
+ assert not _ManifestEvalVisitor(schema, In(Reference("id"), (INT_MIN_VALUE - 2, INT_MIN_VALUE - 1))).eval(
+ manifest
+ ), "Should not read: id below lower bound (28 < 30, 29 < 30)"
- assert _ManifestEvalVisitor(
- schema, In(Reference[int]("id"), (LongLiteral(INT_MIN_VALUE - 1), LongLiteral(INT_MIN_VALUE)))
- ).eval(manifest), "Should read: id equal to lower bound (30 == 30)"
+ assert _ManifestEvalVisitor(schema, In(Reference("id"), (INT_MIN_VALUE - 1, INT_MIN_VALUE))).eval(
+ manifest
+ ), "Should read: id equal to lower bound (30 == 30)"
- assert _ManifestEvalVisitor(
- schema, In(Reference[int]("id"), (LongLiteral(INT_MAX_VALUE - 4), LongLiteral(INT_MAX_VALUE - 3)))
- ).eval(manifest), "Should read: id between lower and upper bounds (30 < 75 < 79, 30 < 76 < 79)"
+ assert _ManifestEvalVisitor(schema, In(Reference("id"), (INT_MAX_VALUE - 4, INT_MAX_VALUE - 3))).eval(
+ manifest
+ ), "Should read: id between lower and upper bounds (30 < 75 < 79, 30 < 76 < 79)"
- assert _ManifestEvalVisitor(
- schema, In(Reference[int]("id"), (LongLiteral(INT_MAX_VALUE), LongLiteral(INT_MAX_VALUE + 1)))
- ).eval(manifest), "Should read: id equal to upper bound (79 == 79)"
+ assert _ManifestEvalVisitor(schema, In(Reference("id"), (INT_MAX_VALUE, INT_MAX_VALUE + 1))).eval(
+ manifest
+ ), "Should read: id equal to upper bound (79 == 79)"
- assert not _ManifestEvalVisitor(
- schema, In(Reference[int]("id"), (LongLiteral(INT_MAX_VALUE + 1), LongLiteral(INT_MAX_VALUE + 2)))
- ).eval(manifest), "Should not read: id above upper bound (80 > 79, 81 > 79)"
+ assert not _ManifestEvalVisitor(schema, In(Reference("id"), (INT_MAX_VALUE + 1, INT_MAX_VALUE + 2))).eval(
+ manifest
+ ), "Should not read: id above upper bound (80 > 79, 81 > 79)"
- assert not _ManifestEvalVisitor(
- schema, In(Reference[int]("id"), (LongLiteral(INT_MAX_VALUE + 6), LongLiteral(INT_MAX_VALUE + 7)))
- ).eval(manifest), "Should not read: id above upper bound (85 > 79, 86 > 79)"
+ assert not _ManifestEvalVisitor(schema, In(Reference("id"), (INT_MAX_VALUE + 6, INT_MAX_VALUE + 7))).eval(
+ manifest
+ ), "Should not read: id above upper bound (85 > 79, 86 > 79)"
- assert not _ManifestEvalVisitor(
- schema, In(Reference[str]("all_nulls_missing_nan"), (StringLiteral("abc"), StringLiteral("def")))
- ).eval(manifest), "Should skip: in on all nulls column"
+ assert not _ManifestEvalVisitor(schema, In(Reference("all_nulls_missing_nan"), ("abc", "def"))).eval(
+ manifest
+ ), "Should skip: in on all nulls column"
- assert _ManifestEvalVisitor(schema, In(Reference[str]("some_nulls"), (StringLiteral("abc"), StringLiteral("def")))).eval(
+ assert _ManifestEvalVisitor(schema, In(Reference("some_nulls"), ("abc", "def"))).eval(
manifest
), "Should read: in on some nulls column"
- assert _ManifestEvalVisitor(schema, In(Reference[str]("no_nulls"), (StringLiteral("abc"), StringLiteral("def")))).eval(
+ assert _ManifestEvalVisitor(schema, In(Reference("no_nulls"), ("abc", "def"))).eval(
manifest
), "Should read: in on no nulls column"
def test_integer_not_in(schema: Schema, manifest: ManifestFile):
- assert _ManifestEvalVisitor(
- schema, NotIn(Reference[int]("id"), (LongLiteral(INT_MIN_VALUE - 25), LongLiteral(INT_MIN_VALUE - 24)))
- ).eval(manifest), "Should read: id below lower bound (5 < 30, 6 < 30)"
+ assert _ManifestEvalVisitor(schema, NotIn(Reference("id"), (INT_MIN_VALUE - 25, INT_MIN_VALUE - 24))).eval(
+ manifest
+ ), "Should read: id below lower bound (5 < 30, 6 < 30)"
- assert _ManifestEvalVisitor(
- schema, NotIn(Reference[int]("id"), (LongLiteral(INT_MIN_VALUE - 2), LongLiteral(INT_MIN_VALUE - 1)))
- ).eval(manifest), "Should read: id below lower bound (28 < 30, 29 < 30)"
+ assert _ManifestEvalVisitor(schema, NotIn(Reference("id"), (INT_MIN_VALUE - 2, INT_MIN_VALUE - 1))).eval(
+ manifest
+ ), "Should read: id below lower bound (28 < 30, 29 < 30)"
- assert _ManifestEvalVisitor(
- schema, NotIn(Reference[int]("id"), (LongLiteral(INT_MIN_VALUE - 1), LongLiteral(INT_MIN_VALUE)))
- ).eval(manifest), "Should read: id equal to lower bound (30 == 30)"
+ assert _ManifestEvalVisitor(schema, NotIn(Reference("id"), (INT_MIN_VALUE - 1, INT_MIN_VALUE))).eval(
+ manifest
+ ), "Should read: id equal to lower bound (30 == 30)"
- assert _ManifestEvalVisitor(
- schema, NotIn(Reference[int]("id"), (LongLiteral(INT_MAX_VALUE - 4), LongLiteral(INT_MAX_VALUE - 3)))
- ).eval(manifest), "Should read: id between lower and upper bounds (30 < 75 < 79, 30 < 76 < 79)"
+ assert _ManifestEvalVisitor(schema, NotIn(Reference("id"), (INT_MAX_VALUE - 4, INT_MAX_VALUE - 3))).eval(
+ manifest
+ ), "Should read: id between lower and upper bounds (30 < 75 < 79, 30 < 76 < 79)"
- assert _ManifestEvalVisitor(
- schema, NotIn(Reference[int]("id"), (LongLiteral(INT_MAX_VALUE), LongLiteral(INT_MAX_VALUE + 1)))
- ).eval(manifest), "Should read: id equal to upper bound (79 == 79)"
+ assert _ManifestEvalVisitor(schema, NotIn(Reference("id"), (INT_MAX_VALUE, INT_MAX_VALUE + 1))).eval(
+ manifest
+ ), "Should read: id equal to upper bound (79 == 79)"
- assert _ManifestEvalVisitor(
- schema, NotIn(Reference[int]("id"), (LongLiteral(INT_MAX_VALUE + 1), LongLiteral(INT_MAX_VALUE + 2)))
- ).eval(manifest), "Should read: id above upper bound (80 > 79, 81 > 79)"
+ assert _ManifestEvalVisitor(schema, NotIn(Reference("id"), (INT_MAX_VALUE + 1, INT_MAX_VALUE + 2))).eval(
+ manifest
+ ), "Should read: id above upper bound (80 > 79, 81 > 79)"
- assert _ManifestEvalVisitor(
- schema, NotIn(Reference[int]("id"), (LongLiteral(INT_MAX_VALUE + 6), LongLiteral(INT_MAX_VALUE + 7)))
- ).eval(manifest), "Should read: id above upper bound (85 > 79, 86 > 79)"
+ assert _ManifestEvalVisitor(schema, NotIn(Reference("id"), (INT_MAX_VALUE + 6, INT_MAX_VALUE + 7))).eval(
+ manifest
+ ), "Should read: id above upper bound (85 > 79, 86 > 79)"
- assert _ManifestEvalVisitor(
- schema, NotIn(Reference[str]("all_nulls_missing_nan"), (StringLiteral("abc"), StringLiteral("def")))
- ).eval(manifest), "Should read: notIn on no nulls column"
+ assert _ManifestEvalVisitor(schema, NotIn(Reference("all_nulls_missing_nan"), ("abc", "def"))).eval(
+ manifest
+ ), "Should read: notIn on no nulls column"
- assert _ManifestEvalVisitor(schema, NotIn(Reference[str]("some_nulls"), (StringLiteral("abc"), StringLiteral("def")))).eval(
+ assert _ManifestEvalVisitor(schema, NotIn(Reference("some_nulls"), ("abc", "def"))).eval(
manifest
), "Should read: in on some nulls column"
- assert _ManifestEvalVisitor(schema, NotIn(Reference[str]("no_nulls"), (StringLiteral("abc"), StringLiteral("def")))).eval(
+ assert _ManifestEvalVisitor(schema, NotIn(Reference("no_nulls"), ("abc", "def"))).eval(
manifest
), "Should read: in on no nulls column"
-def test_bound_predicate_invert():
- with pytest.raises(NotImplementedError):
- _ = ~BoundPredicate(
- term=BoundReference(
- field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
- accessor=Accessor(position=0, inner=None),
- )
- )
-
-
-def test_bound_unary_predicate_invert():
- with pytest.raises(NotImplementedError):
- _ = ~BoundUnaryPredicate(
- term=BoundReference(
- field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
- accessor=Accessor(position=0, inner=None),
- )
- )
-
-
-def test_bound_set_predicate_invert():
- with pytest.raises(NotImplementedError):
- _ = ~BoundSetPredicate(
- term=BoundReference(
- field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
- accessor=Accessor(position=0, inner=None),
- ),
- literals={literal("hello"), literal("world")},
- )
-
-
-def test_bound_literal_predicate_invert():
- with pytest.raises(NotImplementedError):
- _ = ~BoundLiteralPredicate(
- term=BoundReference(
- field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
- accessor=Accessor(position=0, inner=None),
- ),
- literal=literal("world"),
- )
-
-
-def test_unbound_predicate_invert():
- with pytest.raises(NotImplementedError):
- _ = ~UnboundPredicate(term=Reference("a"))
-
-
-def test_unbound_predicate_bind(table_schema_simple: Schema):
- with pytest.raises(NotImplementedError):
- _ = UnboundPredicate(term=Reference("a")).bind(table_schema_simple)
-
-
-def test_unbound_unary_predicate_invert():
- with pytest.raises(NotImplementedError):
- _ = ~UnaryPredicate(term=Reference("a"))
-
-
-def test_unbound_set_predicate_invert():
- with pytest.raises(NotImplementedError):
- _ = ~SetPredicate(term=Reference("a"), literals=(literal("hello"), literal("world")))
-
-
-def test_unbound_literal_predicate_invert():
- with pytest.raises(NotImplementedError):
- _ = ~LiteralPredicate(term=Reference("a"), literal=literal("hello"))
-
-
def test_rewrite_not_equal_to():
- assert rewrite_not(Not(EqualTo(Reference("x"), literal(34.56)))) == NotEqualTo(Reference("x"), literal(34.56))
+ assert rewrite_not(Not(EqualTo(Reference("x"), 34.56))) == NotEqualTo(Reference("x"), 34.56)
def test_rewrite_not_not_equal_to():
- assert rewrite_not(Not(NotEqualTo(Reference("x"), literal(34.56)))) == EqualTo(Reference("x"), literal(34.56))
+ assert rewrite_not(Not(NotEqualTo(Reference("x"), 34.56))) == EqualTo(Reference("x"), 34.56)
def test_rewrite_not_in():
- assert rewrite_not(Not(In(Reference("x"), (literal(34.56),)))) == NotIn(Reference("x"), (literal(34.56),))
+ assert rewrite_not(Not(In(Reference("x"), (34.56,)))) == NotIn(Reference("x"), (34.56,))
def test_rewrite_and():
- assert rewrite_not(Not(And(EqualTo(Reference("x"), literal(34.56)), EqualTo(Reference("y"), literal(34.56)),))) == Or(
- NotEqualTo(term=Reference(name="x"), literal=literal(34.56)),
- NotEqualTo(term=Reference(name="y"), literal=literal(34.56)),
+ assert rewrite_not(Not(And(EqualTo(Reference("x"), 34.56), EqualTo(Reference("y"), 34.56),))) == Or(
+ NotEqualTo(term=Reference(name="x"), literal=34.56),
+ NotEqualTo(term=Reference(name="y"), literal=34.56),
)
def test_rewrite_or():
- assert rewrite_not(Not(Or(EqualTo(Reference("x"), literal(34.56)), EqualTo(Reference("y"), literal(34.56)),))) == And(
- NotEqualTo(term=Reference(name="x"), literal=literal(34.56)),
- NotEqualTo(term=Reference(name="y"), literal=literal(34.56)),
+ assert rewrite_not(Not(Or(EqualTo(Reference("x"), 34.56), EqualTo(Reference("y"), 34.56),))) == And(
+ NotEqualTo(term=Reference(name="x"), literal=34.56),
+ NotEqualTo(term=Reference(name="y"), literal=34.56),
)
diff --git a/python/tests/table/test_init.py b/python/tests/table/test_init.py
index e20320701c..8e4dc7820e 100644
--- a/python/tests/table/test_init.py
+++ b/python/tests/table/test_init.py
@@ -199,18 +199,18 @@ def test_table_scan_select(table: Table):
def test_table_scan_row_filter(table: Table):
scan = table.scan()
assert scan.row_filter == AlwaysTrue()
- assert scan.filter_rows(EqualTo("x", 10)).row_filter == EqualTo("x", 10) # type: ignore
- assert scan.filter_rows(EqualTo("x", 10)).filter_rows(In("y", (10, 11))).row_filter == And( # type: ignore
- EqualTo("x", 10), In("y", (10, 11)) # type: ignore
+ assert scan.filter_rows(EqualTo("x", 10)).row_filter == EqualTo("x", 10)
+ assert scan.filter_rows(EqualTo("x", 10)).filter_rows(In("y", (10, 11))).row_filter == And(
+ EqualTo("x", 10), In("y", (10, 11))
)
def test_table_scan_partition_filter(table: Table):
scan = table.scan()
assert scan.row_filter == AlwaysTrue()
- assert scan.filter_partitions(EqualTo("x", 10)).partition_filter == EqualTo("x", 10) # type: ignore
- assert scan.filter_partitions(EqualTo("x", 10)).filter_partitions(In("y", (10, 11))).partition_filter == And( # type: ignore
- EqualTo("x", 10), In("y", (10, 11)) # type: ignore
+ assert scan.filter_partitions(EqualTo("x", 10)).partition_filter == EqualTo("x", 10)
+ assert scan.filter_partitions(EqualTo("x", 10)).filter_partitions(In("y", (10, 11))).partition_filter == And(
+ EqualTo("x", 10), In("y", (10, 11))
)