samredai commented on a change in pull request #4262: URL: https://github.com/apache/iceberg/pull/4262#discussion_r821087191
########## File path: python/tests/expression/test_literals.py ########## @@ -0,0 +1,479 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +import math +import uuid +from datetime import datetime +from decimal import Decimal + +import dateutil.parser +import pytest +from fastavro.write import LOGICAL_WRITERS +from pytest import raises + +import iceberg.expression.literals +from iceberg.types import ( + BinaryType, + BooleanType, + DateType, + DecimalType, + DoubleType, + FixedType, + FloatType, + IntegerType, + LongType, + StringType, + TimestampType, + TimestamptzType, + TimeType, + UUIDType, +) + +# Numeric + + +def test_integer_to_long_conversion(): + lit = iceberg.expression.literals.of(34) + long_lit = lit.to(LongType()) + + assert lit.value == long_lit.value + + +def test_integer_to_float_conversion(): + lit = iceberg.expression.literals.of(34) + float_lit = lit.to(FloatType()) + + assert math.isclose(lit.value, float_lit.value) + + +def test_integer_to_double_conversion(): + lit = iceberg.expression.literals.of(34) + dbl_lit = lit.to(DoubleType()) + + assert math.isclose(lit.value, dbl_lit.value) + + +def test_integer_to_decimal_conversion(type_val_tuples): + lit = iceberg.expression.literals.of(34) + + assert lit.to(type_val_tuples[0]).value.as_tuple() == Decimal(type_val_tuples[1]).as_tuple() + + +def test_integer_to_date_conversion(): + lit = iceberg.expression.literals.of(20220303) + dbl_lit = lit.to(DateType()) + + assert isinstance(dbl_lit, iceberg.expression.literals.DateLiteral) + + +def test_long_to_integer(): + lit = iceberg.expression.literals.of(34).to(LongType()) + int_lit = lit.to(IntegerType()) + + assert lit.value == int_lit.value + + +def test_long_to_float_conversion(): + lit = iceberg.expression.literals.of(34).to(LongType()) + float_lit = lit.to(FloatType()) + + assert math.isclose(lit.value, float_lit.value) + + +def test_long_to_double_conversion(): + lit = iceberg.expression.literals.of(34).to(LongType()) + dbl_lit = lit.to(DoubleType()) + + assert math.isclose(lit.value, dbl_lit.value) + + +def test_long_to_decimal_conversion(type_val_tuples): + lit = iceberg.expression.literals.of(34).to(LongType()) + + assert lit.to(type_val_tuples[0]).value.as_tuple() == Decimal(type_val_tuples[1]).as_tuple() + + +def test_float_to_double(): + lit = iceberg.expression.literals.of(34.56) + dbl_lit = lit.to(DoubleType()) + + assert math.isclose(lit.value, dbl_lit.value) + + +def test_float_to_decimal_conversion(float_type_val_tuples): + lit = iceberg.expression.literals.of(34.56) + + assert lit.to(float_type_val_tuples[0]).value.as_tuple() == Decimal(float_type_val_tuples[1]).as_tuple() + + +def test_double_to_float(): + lit = iceberg.expression.literals.of(34.56).to(DoubleType()) + float_lit = lit.to(FloatType()) + + assert math.isclose(lit.value, float_lit.value) + + +def test_double_to_decimal_conversion(float_type_val_tuples): + lit = iceberg.expression.literals.of(34.56).to(DoubleType()) + + assert lit.to(float_type_val_tuples[0]).value.as_tuple() == Decimal(float_type_val_tuples[1]).as_tuple() + + +def test_decimal_to_decimal_conversion(): + lit = iceberg.expression.literals.of(Decimal("34.11").quantize(Decimal(".01"))) + + assert lit.value.as_tuple() == lit.to(DecimalType(9, 2)).value.as_tuple() + assert lit.value.as_tuple() == lit.to(DecimalType(11, 2)).value.as_tuple() + assert lit.to(DecimalType(9, 0)) is None + assert lit.to(DecimalType(9, 1)) is None + assert lit.to(DecimalType(9, 3)) is None + + +# STRING + + +def test_string_to_string_literal(): + assert iceberg.expression.literals.of("abc") == iceberg.expression.literals.of("abc").to(StringType()) + + +def test_string_to_date_literal(): + date_str = iceberg.expression.literals.of("2017-08-18") + date = date_str.to(DateType()) + + avro_val = LOGICAL_WRITERS["int-date"](datetime.strptime("2017-08-18", "%Y-%m-%d"), None) + assert avro_val == date.value + + +def test_string_to_time_literal(): + time_str = iceberg.expression.literals.of("14:21:01.919") + time_lit = time_str.to(TimeType()) + + avro_val = LOGICAL_WRITERS["long-time-micros"](datetime.strptime("14:21:01.919", "%H:%M:%S.%f").time(), None) + + assert avro_val == time_lit.value + + +def test_string_to_timestamp_literal(): + timestamp_str = iceberg.expression.literals.of("2017-08-18T14:21:01.919+00:00") + timestamp = timestamp_str.to(TimestamptzType()) + + avro_val = LOGICAL_WRITERS["long-timestamp-micros"](dateutil.parser.parse("2017-08-18T14:21:01.919+00:00"), None) + assert avro_val == timestamp.value + + timestamp_str = iceberg.expression.literals.of("2017-08-18T14:21:01.919") + timestamp = timestamp_str.to(TimestampType()) + assert avro_val == timestamp.value + + timestamp_str = iceberg.expression.literals.of("2017-08-18T14:21:01.919-07:00") + timestamp = timestamp_str.to(TimestamptzType()) + avro_val = LOGICAL_WRITERS["long-timestamp-micros"](dateutil.parser.parse("2017-08-18T21:21:01.919+00:00"), None) + assert avro_val == timestamp.value + + +def test_timestamp_with_zone_without_zone_in_literal(): + with raises(RuntimeError): + timestamp_str = iceberg.expression.literals.of("2017-08-18T14:21:01.919") + timestamp_str.to(TimestamptzType()) + + +def test_timestamp_without_zone_with_zone_in_literal(): + with raises(RuntimeError): + timestamp_str = iceberg.expression.literals.of("2017-08-18T14:21:01.919+07:00") + timestamp_str.to(TimestampType()) + + +def test_string_to_uuid_literal(): + expected = uuid.uuid4() + uuid_str = iceberg.expression.literals.of(str(expected)) + uuid_lit = uuid_str.to(UUIDType()) + + assert expected == uuid_lit.value + + +def test_string_to_decimal_literal(): + decimal_str = iceberg.expression.literals.of("34.560") + decimal_lit = decimal_str.to(DecimalType(9, 3)) + + assert 3 == abs(decimal_lit.value.as_tuple().exponent) + assert Decimal("34.560").as_tuple() == decimal_lit.value.as_tuple() + + assert decimal_str.to(DecimalType(9, 2)) is None + assert decimal_str.to(DecimalType(9, 4)) is None + + +# MISC + + +def test_identity_conversions(): Review comment: parametrize from pytest would be better here since it will create a test for every pair. Something like: ```py @pytest.mark.parametrize( "literal, primitive_type", [ (iceberg.expression.literals.of(True), BooleanType()), (iceberg.expression.literals.of(34), IntegerType()), (iceberg.expression.literals.of(3400000000), LongType()), (iceberg.expression.literals.of(34.11), FloatType()), (iceberg.expression.literals.of(34.11), DoubleType()), (iceberg.expression.literals.of(Decimal(34.55).quantize(Decimal("0.01"))), DecimalType(9, 2)), (iceberg.expression.literals.of("2017-08-18"), DateType()), (iceberg.expression.literals.of("14:21:01.919"), TimeType()), (iceberg.expression.literals.of("2017-08-18T14:21:01.919"), TimestampType()), (iceberg.expression.literals.of("abc"), StringType()), (iceberg.expression.literals.of(uuid.uuid4()), UUIDType()), (iceberg.expression.literals.of(bytes([0x01, 0x02, 0x03])), FixedType(3)), (iceberg.expression.literals.of(bytearray([0x03, 0x04, 0x05, 0x06])), BinaryType()), ], ) def test_identity_conversions(literal, primitive_type): expected = literal.to(primitive_type) assert expected is expected.to(primitive_type) ``` -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected] --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
