From 79303dd13fff01bb38fba6b12554b7b5152a40e0 Mon Sep 17 00:00:00 2001
From: Kiyoon Kim <kiyoon@users.noreply.github.com>
Date: Wed, 25 Dec 2024 15:00:48 +0900
Subject: [PATCH 1/3] fix(version): exec code with lazy type in dataclass

---
 backend/src/hatchling/version/source/code.py | 1 +
 1 file changed, 1 insertion(+)

diff --git a/backend/src/hatchling/version/source/code.py b/backend/src/hatchling/version/source/code.py
index dc708aee7..92fc7c4a0 100644
--- a/backend/src/hatchling/version/source/code.py
+++ b/backend/src/hatchling/version/source/code.py
@@ -46,6 +46,7 @@ def get_version_data(self) -> dict:
 
         spec = spec_from_file_location(os.path.splitext(path)[0], path)
         module = module_from_spec(spec)  # type: ignore[arg-type]
+        sys.modules[os.path.splitext(path)[0]] = module
 
         old_search_paths = list(sys.path)
         try:

From e09a581a1e61a90e38a8d7c33bea020e2e869f4d Mon Sep 17 00:00:00 2001
From: Kiyoon Kim <kiyoon@users.noreply.github.com>
Date: Wed, 25 Dec 2024 15:24:08 +0900
Subject: [PATCH 2/3] docs: PEP 563 with dataclasses fix

---
 backend/src/hatchling/version/source/code.py | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/backend/src/hatchling/version/source/code.py b/backend/src/hatchling/version/source/code.py
index 92fc7c4a0..4e611b078 100644
--- a/backend/src/hatchling/version/source/code.py
+++ b/backend/src/hatchling/version/source/code.py
@@ -46,6 +46,9 @@ def get_version_data(self) -> dict:
 
         spec = spec_from_file_location(os.path.splitext(path)[0], path)
         module = module_from_spec(spec)  # type: ignore[arg-type]
+
+        # This fixes using PEP 563 (__future__ annotations) with dataclasses.
+        # https://github.com/pypa/hatch/issues/1863
         sys.modules[os.path.splitext(path)[0]] = module
 
         old_search_paths = list(sys.path)

From b41b5207dd90dec41d27f9729f55b7761e1b65c5 Mon Sep 17 00:00:00 2001
From: Kiyoon Kim <kiyoon@users.noreply.github.com>
Date: Wed, 25 Dec 2024 15:38:23 +0900
Subject: [PATCH 3/3] test: postponed evaluation of annotation with dataclasses

---
 tests/backend/version/source/test_code.py | 62 +++++++++++++++++++++++
 1 file changed, 62 insertions(+)

diff --git a/tests/backend/version/source/test_code.py b/tests/backend/version/source/test_code.py
index 1e1cf639e..18c67d1d3 100644
--- a/tests/backend/version/source/test_code.py
+++ b/tests/backend/version/source/test_code.py
@@ -125,3 +125,65 @@ def foo(version_info):
 
     with temp_dir.as_cwd():
         assert source.get_version_data()['version'] == '1.0.0.1.dev0'
+
+
+def test_pep563_with_dataclasses_1(temp_dir, helpers):
+    """
+    Test postponed evaluation of annotations (using __future__) with dataclasses.
+
+    References:
+       - https://github.com/pypa/hatch/issues/1863
+    """
+    source = CodeSource(str(temp_dir), {'path': 'a/b.py'})
+
+    file_path = temp_dir / 'a' / 'b.py'
+    file_path.ensure_parent_dir_exists()
+    file_path.write_text(
+        helpers.dedent(
+            """
+            from __future__ import annotations
+
+            from dataclasses import dataclass
+
+            @dataclass
+            class VersionConfig:
+                test_dir: str | None = None
+                verbose: bool = False
+
+            __version__ = "0.1.1"
+            """
+        )
+    )
+
+    with temp_dir.as_cwd():
+        assert source.get_version_data()['version'] == '0.1.1'
+
+
+def test_pep563_with_dataclasses_2(temp_dir, helpers):
+    """
+    Test postponed evaluation of annotations (using "type" string) with dataclasses.
+
+    References:
+       - https://github.com/pypa/hatch/issues/1863
+    """
+    source = CodeSource(str(temp_dir), {'path': 'a/b.py'})
+
+    file_path = temp_dir / 'a' / 'b.py'
+    file_path.ensure_parent_dir_exists()
+    file_path.write_text(
+        helpers.dedent(
+            """
+            from dataclasses import dataclass
+
+            @dataclass
+            class VersionConfig:
+                test_dir: "str | None" = None
+                verbose: bool = False
+
+            __version__ = "0.1.1"
+            """
+        )
+    )
+
+    with temp_dir.as_cwd():
+        assert source.get_version_data()['version'] == '0.1.1'