Repository: apache/airflow
File: airflow-core/tests/unit/serialization/test_serialized_objects.py (Python)

Code before:
    obj = [[input]]
    serialized = BaseSerialization.serialize(obj)  # does not raise
    # Verify the result is JSON-serializable
    json.dumps(serialized)  # does not raise


@pytest.mark.parametrize("reference", REFERENCE_TYPES)
def test_serialize_deserialize_deadline_alert(reference):
    public_deadline_alert_fields = {
        field.lower() for field in vars(DeadlineAlertFields) if not field.startswith("_")
    }
    original = DeadlineAlert(
        reference=reference,
        interval=timedelta(hours=1),
        callback=AsyncCallback(empty_callback_for_deadline, kwargs=TEST_CALLBACK_KWARGS),
    )

    # Use BaseSerialization like assets do
    serialized = BaseSerialization.serialize(original)
    assert serialized[Encoding.TYPE] == DAT.DEADLINE_ALERT
    assert set(serialized[Encoding.VAR].keys()) == public_deadline_alert_fields

    deserialized = BaseSerialization.deserialize(serialized)
    assert deserialized.reference.serialize_reference() == reference.serialize_reference()
    assert deserialized.interval == original.interval
    # Callback is deserialized as SerializedDeadlineAlert, which may have different callback representation
    assert deserialized.callback is not None


@pytest.mark.parametrize(
    "conn_uri",
    [
        pytest.param("aws://", id="only-conn-type"),
        pytest.param(
            "postgres://username:password@ec2.compute.com:5432/the_database",
            id="all-non-extra",
        ),
        pytest.param(
            "///?__extra__=%7B%22foo%22%3A+%22bar%22%2C+%22answer%22%3A+42%2C+%22"
            "nullable%22%3A+null%2C+%22empty%22%3A+%22%22%2C+%22zero%22%3A+0%7D",
            id="extra",
        ),
    ],
)
def test_backcompat_deserialize_connection(conn_uri):
    """Test deserialize connection which serialised by previous serializer implementation."""
    from airflow.serialization.serialized_objects import BaseSerialization

    conn_obj = {
        Encoding.TYPE: DAT.CONNECTION,
        Encoding.VAR: {"conn_id": "TEST_ID", "uri": conn_uri},

Review comment (suggestion):
Shouldn't serializing then deserializing return the original?  Or at least "a new object containing equal values", not the literal same object.

Code after:

    serialized = BaseSerialization.serialize(input)  # does not raise
    json.dumps(serialized)  # does not raise
    if encoded_type is not None:
        assert serialized[Encoding.TYPE] == encoded_type
        assert serialized[Encoding.VAR] is not None
    if cmp_func is not None:
        deserialized = BaseSerialization.deserialize(serialized)
        assert cmp_func(input, deserialized)

    # Verify recursive behavior
    obj = [[input]]
    serialized = BaseSerialization.serialize(obj)  # does not raise
    # Verify the result is JSON-serializable
    json.dumps(serialized)  # does not raise


@pytest.mark.parametrize("reference", REFERENCE_TYPES)
def test_serialize_deserialize_deadline_alert(reference):
    public_deadline_alert_fields = {
        field.lower() for field in vars(DeadlineAlertFields) if not field.startswith("_")
    }
    original = DeadlineAlert(
        reference=reference,
        interval=timedelta(hours=1),
        callback=AsyncCallback(empty_callback_for_deadline, kwargs=TEST_CALLBACK_KWARGS),
    )

    # Use BaseSerialization like assets do
    serialized = BaseSerialization.serialize(original)
    assert serialized[Encoding.TYPE] == DAT.DEADLINE_ALERT
    assert set(serialized[Encoding.VAR].keys()) == public_deadline_alert_fields

    deserialized = BaseSerialization.deserialize(serialized)
    assert deserialized.reference.serialize_reference() == reference.serialize_reference()
    assert deserialized.interval == original.interval
    assert deserialized.callback == original.callback


@pytest.mark.parametrize(
    "conn_uri",
    [
        pytest.param("aws://", id="only-conn-type"),
        pytest.param(
            "postgres://username:password@ec2.compute.com:5432/the_database",
            id="all-non-extra",
        ),
        pytest.param(
            "///?__extra__=%7B%22foo%22%3A+%22bar%22%2C+%22answer%22%3A+42%2C+%22"
            "nullable%22%3A+null%2C+%22empty%22%3A+%22%22%2C+%22zero%22%3A+0%7D",
            id="extra",