diff --git a/.changes/unreleased/Fixes-20230906-142213.yaml b/.changes/unreleased/Fixes-20230906-142213.yaml new file mode 100644 index 00000000000..175ffc9afd0 --- /dev/null +++ b/.changes/unreleased/Fixes-20230906-142213.yaml @@ -0,0 +1,6 @@ +kind: Fixes +body: make version comparison insensitive to order +time: 2023-09-06T14:22:13.114549-04:00 +custom: + Author: michelleark + Issue: "8571" diff --git a/core/dbt/contracts/graph/unparsed.py b/core/dbt/contracts/graph/unparsed.py index 69c8d55ffd0..2e976db3a89 100644 --- a/core/dbt/contracts/graph/unparsed.py +++ b/core/dbt/contracts/graph/unparsed.py @@ -163,14 +163,9 @@ class UnparsedVersion(dbtClassMixin): def __lt__(self, other): try: - v = type(other.v)(self.v) - return v < other.v + return float(self.v) < float(other.v) except ValueError: - try: - other_v = type(self.v)(other.v) - return self.v < other_v - except ValueError: - return str(self.v) < str(other.v) + return str(self.v) < str(other.v) @property def include_exclude(self) -> dbt.helper_types.IncludeExclude: diff --git a/tests/unit/test_contracts_graph_unparsed.py b/tests/unit/test_contracts_graph_unparsed.py index ad9f6d74922..2bff9e5fade 100644 --- a/tests/unit/test_contracts_graph_unparsed.py +++ b/tests/unit/test_contracts_graph_unparsed.py @@ -1,5 +1,6 @@ -import pickle from datetime import timedelta +import pickle +import pytest from dbt.contracts.graph.unparsed import ( UnparsedNode, @@ -940,3 +941,25 @@ def test_bad_version_no_v(self): version = self.get_ok_dict() del version["v"] self.assert_fails_validation(version) + + +@pytest.mark.parametrize( + "left,right,expected_lt", + [ + # same types + (2, 12, True), + (12, 2, False), + ("a", "b", True), + ("b", "a", False), + # mismatched types - numeric + (2, 12.0, True), + (12.0, 2, False), + (2, "12", True), + ("12", 2, False), + # mismatched types + (1, "test", True), + ("test", 1, False), + ], +) +def test_unparsed_version_lt(left, right, expected_lt): + assert (UnparsedVersion(left) < UnparsedVersion(right)) == expected_lt diff --git a/tests/unit/test_graph_selector_methods.py b/tests/unit/test_graph_selector_methods.py index c307aa382d0..4345f762b55 100644 --- a/tests/unit/test_graph_selector_methods.py +++ b/tests/unit/test_graph_selector_methods.py @@ -638,6 +638,21 @@ def versioned_model_v3(seed): ) +@pytest.fixture +def versioned_model_v12_string(seed): + return make_model( + "pkg", + "versioned_model", + 'select * from {{ ref("seed") }}', + config_kwargs={"materialized": "table"}, + refs=[seed], + sources=[], + path="subdirectory/versioned_model_v12.sql", + version="12", + latest_version=2, + ) + + @pytest.fixture def versioned_model_v4_nested_dir(seed): return make_model( @@ -732,6 +747,7 @@ def manifest( versioned_model_v2, versioned_model_v3, versioned_model_v4_nested_dir, + versioned_model_v12_string, ext_source_2, ext_source_other, ext_source_other_2, @@ -760,6 +776,7 @@ def manifest( versioned_model_v2, versioned_model_v3, versioned_model_v4_nested_dir, + versioned_model_v12_string, ext_model, table_id_unique, table_id_not_null, @@ -823,6 +840,7 @@ def test_select_fqn(manifest): "versioned_model.v2", "versioned_model.v3", "versioned_model.v4", + "versioned_model.v12", "table_model", "table_model_py", "table_model_csv", @@ -840,6 +858,7 @@ def test_select_fqn(manifest): "versioned_model.v2", "versioned_model.v3", "versioned_model.v4", + "versioned_model.v12", } assert search_manifest_using_method(manifest, method, "versioned_model.v1") == { "versioned_model.v1" @@ -1051,6 +1070,7 @@ def test_select_package(manifest): "versioned_model.v2", "versioned_model.v3", "versioned_model.v4", + "versioned_model.v12", "table_model", "table_model_py", "table_model_csv", @@ -1103,6 +1123,7 @@ def test_select_config_materialized(manifest): "versioned_model.v2", "versioned_model.v3", "versioned_model.v4", + "versioned_model.v12", "mynamespace.union_model", } @@ -1189,6 +1210,7 @@ def test_select_version(manifest): assert search_manifest_using_method(manifest, method, "prerelease") == { "versioned_model.v3", "versioned_model.v4", + "versioned_model.v12", } assert search_manifest_using_method(manifest, method, "none") == { "table_model_py",