diff --git a/NEXT_CHANGELOG.md b/NEXT_CHANGELOG.md
index 602d003e75..3a2cbd4688 100644
--- a/NEXT_CHANGELOG.md
+++ b/NEXT_CHANGELOG.md
@@ -3,6 +3,7 @@
 ## Release v0.258.0
 
 ### Notable Changes
+* Switch default-python template to use pyproject.toml + dynamic\_version in dev target. uv is now required. ([#3042](https://github.com/databricks/cli/pull/3042))
 
 ### Dependency updates
 * Upgraded TF provider to 1.84.0 ([#3151](https://github.com/databricks/cli/pull/3151))
diff --git a/acceptance/bundle/templates/default-python/classic/out.compare-vs-serverless.diff b/acceptance/bundle/templates/default-python/classic/out.compare-vs-serverless.diff
index 51dd3a6aa4..25307e2031 100644
--- a/acceptance/bundle/templates/default-python/classic/out.compare-vs-serverless.diff
+++ b/acceptance/bundle/templates/default-python/classic/out.compare-vs-serverless.diff
@@ -1,3 +1,17 @@
+--- [TESTROOT]/bundle/templates/default-python/classic/../serverless/output/my_default_python/databricks.yml
++++ output/my_default_python/databricks.yml
+@@ -25,4 +25,11 @@
+       host: [DATABRICKS_URL]
+
++    presets:
++      # Set dynamic_version: true on all artifacts of type "whl".
++      # This makes "bundle deploy" add a timestamp to wheel's version before uploading,
++      # new wheel takes over the previous installation even if actual wheel version is unchanged.
++      # See https://docs.databricks.com/aws/en/dev-tools/bundles/settings
++      artifacts_dynamic_version: true
++
+   prod:
+     mode: production
 --- [TESTROOT]/bundle/templates/default-python/classic/../serverless/output/my_default_python/resources/my_default_python.job.yml
 +++ output/my_default_python/resources/my_default_python.job.yml
 @@ -17,4 +17,5 @@
diff --git a/acceptance/bundle/templates/default-python/classic/output/my_default_python/README.md b/acceptance/bundle/templates/default-python/classic/output/my_default_python/README.md
index 10f570bf46..f3b5d153b2 100644
--- a/acceptance/bundle/templates/default-python/classic/output/my_default_python/README.md
+++ b/acceptance/bundle/templates/default-python/classic/output/my_default_python/README.md
@@ -4,6 +4,8 @@ The 'my_default_python' project was generated by using the default-python templa
 
 ## Getting started
 
+0. Install UV: https://docs.astral.sh/uv/getting-started/installation/
+
 1. Install the Databricks CLI from https://docs.databricks.com/dev-tools/cli/databricks-cli.html
 
 2. Authenticate to your Databricks workspace, if you have not done so already:
diff --git a/acceptance/bundle/templates/default-python/classic/output/my_default_python/databricks.yml b/acceptance/bundle/templates/default-python/classic/output/my_default_python/databricks.yml
index 91c01f25da..ed3d53b999 100644
--- a/acceptance/bundle/templates/default-python/classic/output/my_default_python/databricks.yml
+++ b/acceptance/bundle/templates/default-python/classic/output/my_default_python/databricks.yml
@@ -4,6 +4,11 @@ bundle:
   name: my_default_python
   uuid: [UUID]
 
+artifacts:
+  python_artifact:
+    type: whl
+    build: uv build --wheel
+
 include:
   - resources/*.yml
   - resources/*/*.yml
@@ -19,6 +24,13 @@ targets:
     workspace:
       host: [DATABRICKS_URL]
 
+    presets:
+      # Set dynamic_version: true on all artifacts of type "whl".
+      # This makes "bundle deploy" add a timestamp to wheel's version before uploading,
+      # new wheel takes over the previous installation even if actual wheel version is unchanged.
+      # See https://docs.databricks.com/aws/en/dev-tools/bundles/settings
+      artifacts_dynamic_version: true
+
   prod:
     mode: production
     workspace:
diff --git a/acceptance/bundle/templates/default-python/classic/output/my_default_python/pyproject.toml b/acceptance/bundle/templates/default-python/classic/output/my_default_python/pyproject.toml
new file mode 100644
index 0000000000..f0fa52bc62
--- /dev/null
+++ b/acceptance/bundle/templates/default-python/classic/output/my_default_python/pyproject.toml
@@ -0,0 +1,41 @@
+[project]
+name = "my_default_python"
+version = "0.0.1"
+authors = [{ name = "[USERNAME]" }]
+requires-python = ">= 3.11"
+
+[project.optional-dependencies]
+dev = [
+    "pytest",
+
+    # Code completion support for DLT, also install databricks-connect
+    "databricks-dlt",
+
+    # databricks-connect can be used to run parts of this project locally.
+    # See https://docs.databricks.com/dev-tools/databricks-connect.html.
+    #
+    # Note, databricks-connect is automatically installed if you're using Databricks
+    # extension for Visual Studio Code
+    # (https://docs.databricks.com/dev-tools/vscode-ext/dev-tasks/databricks-connect.html).
+    #
+    # To manually install databricks-connect, uncomment the line below to install a version
+    # of db-connect that corresponds to the Databricks Runtime version used for this project.
+    # See https://docs.databricks.com/dev-tools/databricks-connect.html
+    # "databricks-connect>=15.4,<15.5",
+]
+
+[tool.pytest.ini_options]
+pythonpath = "src"
+testpaths = [
+    "tests",
+]
+
+[build-system]
+requires = ["hatchling"]
+build-backend = "hatchling.build"
+
+[tool.hatch.build.targets.wheel]
+packages = ["src/my_default_python"]
+
+[project.scripts]
+main = "my_default_python.main:main"
diff --git a/acceptance/bundle/templates/default-python/classic/output/my_default_python/pytest.ini b/acceptance/bundle/templates/default-python/classic/output/my_default_python/pytest.ini
deleted file mode 100644
index 80432c2203..0000000000
--- a/acceptance/bundle/templates/default-python/classic/output/my_default_python/pytest.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[pytest]
-testpaths = tests
-pythonpath = src
diff --git a/acceptance/bundle/templates/default-python/classic/output/my_default_python/requirements-dev.txt b/acceptance/bundle/templates/default-python/classic/output/my_default_python/requirements-dev.txt
deleted file mode 100644
index 0ffbf6aed0..0000000000
--- a/acceptance/bundle/templates/default-python/classic/output/my_default_python/requirements-dev.txt
+++ /dev/null
@@ -1,29 +0,0 @@
-## requirements-dev.txt: dependencies for local development.
-##
-## For defining dependencies used by jobs in Databricks Workflows, see
-## https://docs.databricks.com/dev-tools/bundles/library-dependencies.html
-
-## Add code completion support for DLT
-databricks-dlt
-
-## pytest is the default package used for testing
-pytest
-
-## Dependencies for building wheel files
-setuptools
-wheel
-
-## databricks-connect can be used to run parts of this project locally.
-## See https://docs.databricks.com/dev-tools/databricks-connect.html.
-##
-## databricks-connect is automatically installed if you're using Databricks
-## extension for Visual Studio Code
-## (https://docs.databricks.com/dev-tools/vscode-ext/dev-tasks/databricks-connect.html).
-##
-## To manually install databricks-connect, either follow the instructions
-## at https://docs.databricks.com/dev-tools/databricks-connect.html
-## to install the package system-wide. Or uncomment the line below to install a
-## version of db-connect that corresponds to the Databricks Runtime version used
-## for this project.
-#
-# databricks-connect>=15.4,<15.5
diff --git a/acceptance/bundle/templates/default-python/classic/output/my_default_python/setup.py b/acceptance/bundle/templates/default-python/classic/output/my_default_python/setup.py
deleted file mode 100644
index 548f1035eb..0000000000
--- a/acceptance/bundle/templates/default-python/classic/output/my_default_python/setup.py
+++ /dev/null
@@ -1,41 +0,0 @@
-"""
-setup.py configuration script describing how to build and package this project.
-
-This file is primarily used by the setuptools library and typically should not
-be executed directly. See README.md for how to deploy, test, and run
-the my_default_python project.
-"""
-
-from setuptools import setup, find_packages
-
-import sys
-
-sys.path.append("./src")
-
-import datetime
-import my_default_python
-
-local_version = datetime.datetime.utcnow().strftime("%Y%m%d.%H%M%S")
-
-setup(
-    name="my_default_python",
-    # We use timestamp as Local version identifier (https://peps.python.org/pep-0440/#local-version-identifiers.)
-    # to ensure that changes to wheel package are picked up when used on all-purpose clusters
-    version=my_default_python.__version__ + "+" + local_version,
-    url="https://databricks.com",
-    author="[USERNAME]",
-    description="wheel file based on my_default_python/src",
-    packages=find_packages(where="./src"),
-    package_dir={"": "src"},
-    entry_points={
-        "packages": [
-            "main=my_default_python.main:main",
-        ],
-    },
-    install_requires=[
-        # Dependencies in case the output wheel file is used as a library dependency.
-        # For defining dependencies, when this package is used in Databricks, see:
-        # https://docs.databricks.com/dev-tools/bundles/library-dependencies.html
-        "setuptools"
-    ],
-)
diff --git a/acceptance/bundle/templates/default-python/classic/output/my_default_python/src/my_default_python/__init__.py b/acceptance/bundle/templates/default-python/classic/output/my_default_python/src/my_default_python/__init__.py
index f102a9cadf..e69de29bb2 100644
--- a/acceptance/bundle/templates/default-python/classic/output/my_default_python/src/my_default_python/__init__.py
+++ b/acceptance/bundle/templates/default-python/classic/output/my_default_python/src/my_default_python/__init__.py
@@ -1 +0,0 @@
-__version__ = "0.0.1"
diff --git a/acceptance/bundle/templates/default-python/combinations/check_output.py b/acceptance/bundle/templates/default-python/combinations/check_output.py
index 7eda54518e..8190f4fe16 100755
--- a/acceptance/bundle/templates/default-python/combinations/check_output.py
+++ b/acceptance/bundle/templates/default-python/combinations/check_output.py
@@ -1,6 +1,7 @@
 #!/usr/bin/env python3
 import sys
 import os
+import re
 import subprocess
 
 SERVERLESS = os.environ["SERVERLESS"] == "yes"
@@ -11,7 +12,7 @@
     sys.exit(f"SKIP_TEST SERVERLESS=yes but TEST_METASTORE_ID is empty in this env {CLOUD_ENV=}")
 
 BUILDING = "Building python_artifact"
-UPLOADING = "Uploading dist/"
+UPLOADING_WHL = re.compile("Uploading .*whl")
 STATE = "Updating deployment state"
 
 
@@ -21,7 +22,7 @@ def is_printable_line(line):
         return False
 
     # only shown when include_python=yes
-    if line.startswith(UPLOADING):
+    if UPLOADING_WHL.match(line):
         return False
 
     # not shown when all settings are equal to "no"
@@ -33,19 +34,19 @@ def is_printable_line(line):
 
 p = subprocess.run(sys.argv[1:], stdout=subprocess.PIPE, stderr=subprocess.PIPE, encoding="utf-8")
 try:
-    assert p.returncode == 0
+    assert p.returncode == 0, p.returncode
     assert p.stdout == ""
+    if INCLUDE_PYTHON:
+        assert BUILDING in p.stderr, BUILDING
+        assert UPLOADING_WHL.search(p.stderr), UPLOADING_WHL
+    else:
+        assert BUILDING not in p.stderr, BUILDING
+        assert not UPLOADING_WHL.search(p.stderr), UPLOADING_WHL
+
     for line in p.stderr.strip().split("\n"):
         if is_printable_line(line):
             print(line.strip())
 
-    if INCLUDE_PYTHON:
-        assert BUILDING in p.stderr
-        assert UPLOADING in p.stderr
-    else:
-        assert BUILDING not in p.stderr
-        assert UPLOADING not in p.stderr
-
 except:
     print(f"STDOUT: {len(p.stdout)} chars")
     if p.stdout:
diff --git a/acceptance/bundle/templates/default-python/integration_classic/out.validate.dev.json b/acceptance/bundle/templates/default-python/integration_classic/out.validate.dev.json
index b0f1a4b716..a910125276 100644
--- a/acceptance/bundle/templates/default-python/integration_classic/out.validate.dev.json
+++ b/acceptance/bundle/templates/default-python/integration_classic/out.validate.dev.json
@@ -1,7 +1,8 @@
 {
   "artifacts": {
     "python_artifact": {
-      "build": "python3 setup.py bdist_wheel",
+      "build": "uv build --wheel",
+      "dynamic_version": true,
       "files": [
         {
           "source": "[TEST_TMP_DIR]/project_name_[UNIQUE_NAME]/dist/*.whl"
@@ -32,6 +33,7 @@
     "resources/project_name_[UNIQUE_NAME].pipeline.yml"
   ],
   "presets": {
+    "artifacts_dynamic_version": true,
     "jobs_max_concurrent_runs": 4,
     "name_prefix": "[dev [USERNAME]] ",
     "pipelines_development": true,
diff --git a/acceptance/bundle/templates/default-python/integration_classic/output.txt b/acceptance/bundle/templates/default-python/integration_classic/output.txt
index 3cde56fe05..774101e755 100644
--- a/acceptance/bundle/templates/default-python/integration_classic/output.txt
+++ b/acceptance/bundle/templates/default-python/integration_classic/output.txt
@@ -26,7 +26,7 @@ Validation OK!
 
 >>> [CLI] bundle deploy -t dev
 Building python_artifact...
-Uploading dist/project_name_[UNIQUE_NAME]-0.0.1+[NUMID].[NUMID]-py3-none-any.whl...
+Uploading .databricks/bundle/dev/patched_wheels/python_artifact_project_name_[UNIQUE_NAME]/project_name_[UNIQUE_NAME]-0.0.1+[NUMID]-py3-none-any.whl...
 Uploading bundle files to /Workspace/Users/[USERNAME]/.bundle/project_name_[UNIQUE_NAME]/dev/files...
 Deploying resources...
 Updating deployment state...
@@ -54,13 +54,13 @@ Resources:
 >>> diff.py ../out.validate.dev.json ../out.summary.dev.json
 --- ../out.validate.dev.json
 +++ ../out.summary.dev.json
-@@ -50,4 +50,5 @@
+@@ -52,4 +52,5 @@
          "edit_mode": "UI_LOCKED",
          "format": "MULTI_TASK",
 +        "id": "[NUMID]",
          "job_clusters": [
            {
-@@ -118,5 +119,6 @@
+@@ -120,5 +121,6 @@
              "unit": "DAYS"
            }
 -        }
@@ -68,13 +68,13 @@ Resources:
 +        "url": "[DATABRICKS_URL]/jobs/[NUMID]"
        }
      },
-@@ -133,4 +135,5 @@
+@@ -135,4 +137,5 @@
          "development": true,
          "edition": "ADVANCED",
 +        "id": "[UUID]",
          "libraries": [
            {
-@@ -142,5 +145,6 @@
+@@ -144,5 +147,6 @@
          "name": "[dev [USERNAME]] project_name_[UNIQUE_NAME]_pipeline",
          "permissions": [],
 -        "schema": "project_name_[UNIQUE_NAME]_dev"
@@ -108,7 +108,13 @@ Validation OK!
 >>> diff.py ../out.validate.dev.json ../out.validate.prod.json
 --- ../out.validate.dev.json
 +++ ../out.validate.prod.json
-@@ -13,16 +13,11 @@
+@@ -3,5 +3,4 @@
+     "python_artifact": {
+       "build": "uv build --wheel",
+-      "dynamic_version": true,
+       "files": [
+         {
+@@ -14,16 +13,11 @@
    },
    "bundle": {
 -    "deployment": {
@@ -128,10 +134,11 @@ Validation OK!
 +    "target": "prod",
      "terraform": {},
      "uuid": "[UUID]"
-@@ -32,13 +27,10 @@
+@@ -33,14 +27,10 @@
      "resources/project_name_[UNIQUE_NAME].pipeline.yml"
    ],
 -  "presets": {
+-    "artifacts_dynamic_version": true,
 -    "jobs_max_concurrent_runs": 4,
 -    "name_prefix": "[dev [USERNAME]] ",
 -    "pipelines_development": true,
@@ -148,14 +155,14 @@ Validation OK!
 +  ],
    "resources": {
      "jobs": {
-@@ -46,5 +38,5 @@
+@@ -48,5 +38,5 @@
          "deployment": {
            "kind": "BUNDLE",
 -          "metadata_file_path": "/Workspace/Users/[USERNAME]/.bundle/project_name_[UNIQUE_NAME]/dev/state/metadata.json"
 +          "metadata_file_path": "/Workspace/Users/[USERNAME]/.bundle/project_name_[UNIQUE_NAME]/prod/state/metadata.json"
          },
          "edit_mode": "UI_LOCKED",
-@@ -65,12 +57,9 @@
+@@ -67,12 +57,9 @@
            }
          ],
 -        "max_concurrent_runs": 4,
@@ -170,21 +177,21 @@ Validation OK!
 -          "dev": "[USERNAME]"
          },
          "tasks": [
-@@ -78,5 +67,5 @@
+@@ -80,5 +67,5 @@
              "job_cluster_key": "job_cluster",
              "notebook_task": {
 -              "notebook_path": "/Workspace/Users/[USERNAME]/.bundle/project_name_[UNIQUE_NAME]/dev/files/src/notebook"
 +              "notebook_path": "/Workspace/Users/[USERNAME]/.bundle/project_name_[UNIQUE_NAME]/prod/files/src/notebook"
              },
              "task_key": "notebook_task"
-@@ -113,5 +102,5 @@
+@@ -115,5 +102,5 @@
          ],
          "trigger": {
 -          "pause_status": "PAUSED",
 +          "pause_status": "UNPAUSED",
            "periodic": {
              "interval": 1,
-@@ -125,22 +114,21 @@
+@@ -127,22 +114,21 @@
          "channel": "CURRENT",
          "configuration": {
 -          "bundle.sourcePath": "/Workspace/Users/[USERNAME]/.bundle/project_name_[UNIQUE_NAME]/dev/files/src"
@@ -212,7 +219,7 @@ Validation OK!
 +        "schema": "project_name_[UNIQUE_NAME]_prod"
        }
      }
-@@ -153,10 +141,10 @@
+@@ -155,10 +141,10 @@
    "targets": null,
    "workspace": {
 -    "artifact_path": "/Workspace/Users/[USERNAME]/.bundle/project_name_[UNIQUE_NAME]/dev/artifacts",
@@ -231,7 +238,7 @@ Validation OK!
 
 >>> [CLI] bundle deploy -t prod
 Building python_artifact...
-Uploading dist/project_name_[UNIQUE_NAME]-0.0.1+[NUMID].[NUMID]-py3-none-any.whl...
+Uploading dist/project_name_[UNIQUE_NAME]-0.0.1-py3-none-any.whl...
 Uploading bundle files to /Workspace/Users/[USERNAME]/.bundle/project_name_[UNIQUE_NAME]/prod/files...
 Deploying resources...
 Updating deployment state...
@@ -259,7 +266,13 @@ Resources:
 >>> diff.py ../out.summary.dev.json ../out.summary.prod.json
 --- ../out.summary.dev.json
 +++ ../out.summary.prod.json
-@@ -13,16 +13,11 @@
+@@ -3,5 +3,4 @@
+     "python_artifact": {
+       "build": "uv build --wheel",
+-      "dynamic_version": true,
+       "files": [
+         {
+@@ -14,16 +13,11 @@
    },
    "bundle": {
 -    "deployment": {
@@ -279,10 +292,11 @@ Resources:
 +    "target": "prod",
      "terraform": {},
      "uuid": "[UUID]"
-@@ -32,13 +27,10 @@
+@@ -33,14 +27,10 @@
      "resources/project_name_[UNIQUE_NAME].pipeline.yml"
    ],
 -  "presets": {
+-    "artifacts_dynamic_version": true,
 -    "jobs_max_concurrent_runs": 4,
 -    "name_prefix": "[dev [USERNAME]] ",
 -    "pipelines_development": true,
@@ -299,14 +313,14 @@ Resources:
 +  ],
    "resources": {
      "jobs": {
-@@ -46,5 +38,5 @@
+@@ -48,5 +38,5 @@
          "deployment": {
            "kind": "BUNDLE",
 -          "metadata_file_path": "/Workspace/Users/[USERNAME]/.bundle/project_name_[UNIQUE_NAME]/dev/state/metadata.json"
 +          "metadata_file_path": "/Workspace/Users/[USERNAME]/.bundle/project_name_[UNIQUE_NAME]/prod/state/metadata.json"
          },
          "edit_mode": "UI_LOCKED",
-@@ -66,12 +58,9 @@
+@@ -68,12 +58,9 @@
            }
          ],
 -        "max_concurrent_runs": 4,
@@ -321,21 +335,21 @@ Resources:
 -          "dev": "[USERNAME]"
          },
          "tasks": [
-@@ -79,5 +68,5 @@
+@@ -81,5 +68,5 @@
              "job_cluster_key": "job_cluster",
              "notebook_task": {
 -              "notebook_path": "/Workspace/Users/[USERNAME]/.bundle/project_name_[UNIQUE_NAME]/dev/files/src/notebook"
 +              "notebook_path": "/Workspace/Users/[USERNAME]/.bundle/project_name_[UNIQUE_NAME]/prod/files/src/notebook"
              },
              "task_key": "notebook_task"
-@@ -114,5 +103,5 @@
+@@ -116,5 +103,5 @@
          ],
          "trigger": {
 -          "pause_status": "PAUSED",
 +          "pause_status": "UNPAUSED",
            "periodic": {
              "interval": 1,
-@@ -127,11 +116,10 @@
+@@ -129,11 +116,10 @@
          "channel": "CURRENT",
          "configuration": {
 -          "bundle.sourcePath": "/Workspace/Users/[USERNAME]/.bundle/project_name_[UNIQUE_NAME]/dev/files/src"
@@ -349,7 +363,7 @@ Resources:
 -        "development": true,
          "edition": "ADVANCED",
          "id": "[UUID]",
-@@ -139,11 +127,11 @@
+@@ -141,11 +127,11 @@
            {
              "notebook": {
 -              "path": "/Workspace/Users/[USERNAME]/.bundle/project_name_[UNIQUE_NAME]/dev/files/src/dlt_pipeline"
@@ -364,7 +378,7 @@ Resources:
 +        "schema": "project_name_[UNIQUE_NAME]_prod",
          "url": "[DATABRICKS_URL]/pipelines/[UUID]"
        }
-@@ -157,10 +145,10 @@
+@@ -159,10 +145,10 @@
    "targets": null,
    "workspace": {
 -    "artifact_path": "/Workspace/Users/[USERNAME]/.bundle/project_name_[UNIQUE_NAME]/dev/artifacts",
diff --git a/acceptance/bundle/templates/default-python/serverless/output/my_default_python/README.md b/acceptance/bundle/templates/default-python/serverless/output/my_default_python/README.md
index 10f570bf46..f3b5d153b2 100644
--- a/acceptance/bundle/templates/default-python/serverless/output/my_default_python/README.md
+++ b/acceptance/bundle/templates/default-python/serverless/output/my_default_python/README.md
@@ -4,6 +4,8 @@ The 'my_default_python' project was generated by using the default-python templa
 
 ## Getting started
 
+0. Install UV: https://docs.astral.sh/uv/getting-started/installation/
+
 1. Install the Databricks CLI from https://docs.databricks.com/dev-tools/cli/databricks-cli.html
 
 2. Authenticate to your Databricks workspace, if you have not done so already:
diff --git a/acceptance/bundle/templates/default-python/serverless/output/my_default_python/databricks.yml b/acceptance/bundle/templates/default-python/serverless/output/my_default_python/databricks.yml
index 91c01f25da..bdbe7080bc 100644
--- a/acceptance/bundle/templates/default-python/serverless/output/my_default_python/databricks.yml
+++ b/acceptance/bundle/templates/default-python/serverless/output/my_default_python/databricks.yml
@@ -4,6 +4,11 @@ bundle:
   name: my_default_python
   uuid: [UUID]
 
+artifacts:
+  python_artifact:
+    type: whl
+    build: uv build --wheel
+
 include:
   - resources/*.yml
   - resources/*/*.yml
diff --git a/acceptance/bundle/templates/default-python/serverless/output/my_default_python/pyproject.toml b/acceptance/bundle/templates/default-python/serverless/output/my_default_python/pyproject.toml
new file mode 100644
index 0000000000..f0fa52bc62
--- /dev/null
+++ b/acceptance/bundle/templates/default-python/serverless/output/my_default_python/pyproject.toml
@@ -0,0 +1,41 @@
+[project]
+name = "my_default_python"
+version = "0.0.1"
+authors = [{ name = "[USERNAME]" }]
+requires-python = ">= 3.11"
+
+[project.optional-dependencies]
+dev = [
+    "pytest",
+
+    # Code completion support for DLT, also install databricks-connect
+    "databricks-dlt",
+
+    # databricks-connect can be used to run parts of this project locally.
+    # See https://docs.databricks.com/dev-tools/databricks-connect.html.
+    #
+    # Note, databricks-connect is automatically installed if you're using Databricks
+    # extension for Visual Studio Code
+    # (https://docs.databricks.com/dev-tools/vscode-ext/dev-tasks/databricks-connect.html).
+    #
+    # To manually install databricks-connect, uncomment the line below to install a version
+    # of db-connect that corresponds to the Databricks Runtime version used for this project.
+    # See https://docs.databricks.com/dev-tools/databricks-connect.html
+    # "databricks-connect>=15.4,<15.5",
+]
+
+[tool.pytest.ini_options]
+pythonpath = "src"
+testpaths = [
+    "tests",
+]
+
+[build-system]
+requires = ["hatchling"]
+build-backend = "hatchling.build"
+
+[tool.hatch.build.targets.wheel]
+packages = ["src/my_default_python"]
+
+[project.scripts]
+main = "my_default_python.main:main"
diff --git a/acceptance/bundle/templates/default-python/serverless/output/my_default_python/pytest.ini b/acceptance/bundle/templates/default-python/serverless/output/my_default_python/pytest.ini
deleted file mode 100644
index 80432c2203..0000000000
--- a/acceptance/bundle/templates/default-python/serverless/output/my_default_python/pytest.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[pytest]
-testpaths = tests
-pythonpath = src
diff --git a/acceptance/bundle/templates/default-python/serverless/output/my_default_python/requirements-dev.txt b/acceptance/bundle/templates/default-python/serverless/output/my_default_python/requirements-dev.txt
deleted file mode 100644
index 0ffbf6aed0..0000000000
--- a/acceptance/bundle/templates/default-python/serverless/output/my_default_python/requirements-dev.txt
+++ /dev/null
@@ -1,29 +0,0 @@
-## requirements-dev.txt: dependencies for local development.
-##
-## For defining dependencies used by jobs in Databricks Workflows, see
-## https://docs.databricks.com/dev-tools/bundles/library-dependencies.html
-
-## Add code completion support for DLT
-databricks-dlt
-
-## pytest is the default package used for testing
-pytest
-
-## Dependencies for building wheel files
-setuptools
-wheel
-
-## databricks-connect can be used to run parts of this project locally.
-## See https://docs.databricks.com/dev-tools/databricks-connect.html.
-##
-## databricks-connect is automatically installed if you're using Databricks
-## extension for Visual Studio Code
-## (https://docs.databricks.com/dev-tools/vscode-ext/dev-tasks/databricks-connect.html).
-##
-## To manually install databricks-connect, either follow the instructions
-## at https://docs.databricks.com/dev-tools/databricks-connect.html
-## to install the package system-wide. Or uncomment the line below to install a
-## version of db-connect that corresponds to the Databricks Runtime version used
-## for this project.
-#
-# databricks-connect>=15.4,<15.5
diff --git a/acceptance/bundle/templates/default-python/serverless/output/my_default_python/setup.py b/acceptance/bundle/templates/default-python/serverless/output/my_default_python/setup.py
deleted file mode 100644
index 548f1035eb..0000000000
--- a/acceptance/bundle/templates/default-python/serverless/output/my_default_python/setup.py
+++ /dev/null
@@ -1,41 +0,0 @@
-"""
-setup.py configuration script describing how to build and package this project.
-
-This file is primarily used by the setuptools library and typically should not
-be executed directly. See README.md for how to deploy, test, and run
-the my_default_python project.
-"""
-
-from setuptools import setup, find_packages
-
-import sys
-
-sys.path.append("./src")
-
-import datetime
-import my_default_python
-
-local_version = datetime.datetime.utcnow().strftime("%Y%m%d.%H%M%S")
-
-setup(
-    name="my_default_python",
-    # We use timestamp as Local version identifier (https://peps.python.org/pep-0440/#local-version-identifiers.)
-    # to ensure that changes to wheel package are picked up when used on all-purpose clusters
-    version=my_default_python.__version__ + "+" + local_version,
-    url="https://databricks.com",
-    author="[USERNAME]",
-    description="wheel file based on my_default_python/src",
-    packages=find_packages(where="./src"),
-    package_dir={"": "src"},
-    entry_points={
-        "packages": [
-            "main=my_default_python.main:main",
-        ],
-    },
-    install_requires=[
-        # Dependencies in case the output wheel file is used as a library dependency.
-        # For defining dependencies, when this package is used in Databricks, see:
-        # https://docs.databricks.com/dev-tools/bundles/library-dependencies.html
-        "setuptools"
-    ],
-)
diff --git a/acceptance/bundle/templates/default-python/serverless/output/my_default_python/src/my_default_python/__init__.py b/acceptance/bundle/templates/default-python/serverless/output/my_default_python/src/my_default_python/__init__.py
index f102a9cadf..e69de29bb2 100644
--- a/acceptance/bundle/templates/default-python/serverless/output/my_default_python/src/my_default_python/__init__.py
+++ b/acceptance/bundle/templates/default-python/serverless/output/my_default_python/src/my_default_python/__init__.py
@@ -1 +0,0 @@
-__version__ = "0.0.1"
diff --git a/acceptance/bundle/templates/telemetry/default-python/out.databricks.yml b/acceptance/bundle/templates/telemetry/default-python/out.databricks.yml
index 5adba2b4d8..687383d471 100644
--- a/acceptance/bundle/templates/telemetry/default-python/out.databricks.yml
+++ b/acceptance/bundle/templates/telemetry/default-python/out.databricks.yml
@@ -4,6 +4,11 @@ bundle:
   name: my_default_python
   uuid: [BUNDLE-UUID]
 
+artifacts:
+  python_artifact:
+    type: whl
+    build: uv build --wheel
+
 include:
   - resources/*.yml
   - resources/*/*.yml
@@ -19,6 +24,13 @@ targets:
     workspace:
       host: [DATABRICKS_URL]
 
+    presets:
+      # Set dynamic_version: true on all artifacts of type "whl".
+      # This makes "bundle deploy" add a timestamp to wheel's version before uploading,
+      # new wheel takes over the previous installation even if actual wheel version is unchanged.
+      # See https://docs.databricks.com/aws/en/dev-tools/bundles/settings
+      artifacts_dynamic_version: true
+
   prod:
     mode: production
     workspace:
diff --git a/libs/template/templates/default-python/template/{{.project_name}}/README.md.tmpl b/libs/template/templates/default-python/template/{{.project_name}}/README.md.tmpl
index b8811fa3ec..bc4fe07b54 100644
--- a/libs/template/templates/default-python/template/{{.project_name}}/README.md.tmpl
+++ b/libs/template/templates/default-python/template/{{.project_name}}/README.md.tmpl
@@ -4,6 +4,8 @@ The '{{.project_name}}' project was generated by using the default-python templa
 
 ## Getting started
 
+0. Install UV: https://docs.astral.sh/uv/getting-started/installation/
+
 1. Install the Databricks CLI from https://docs.databricks.com/dev-tools/cli/databricks-cli.html
 
 2. Authenticate to your Databricks workspace, if you have not done so already:
diff --git a/libs/template/templates/default-python/template/{{.project_name}}/databricks.yml.tmpl b/libs/template/templates/default-python/template/{{.project_name}}/databricks.yml.tmpl
index 3bbfd4c7f3..99e9d3b7c2 100644
--- a/libs/template/templates/default-python/template/{{.project_name}}/databricks.yml.tmpl
+++ b/libs/template/templates/default-python/template/{{.project_name}}/databricks.yml.tmpl
@@ -1,9 +1,16 @@
+{{$with_classic := (ne .serverless "yes") -}}
+{{$with_python := (eq .include_python "yes") -}}
 # This is a Databricks asset bundle definition for {{.project_name}}.
 # See https://docs.databricks.com/dev-tools/bundles/index.html for documentation.
 bundle:
   name: {{.project_name}}
   uuid: {{bundle_uuid}}
-
+{{ if $with_python }}
+artifacts:
+  python_artifact:
+    type: whl
+    build: uv build --wheel
+{{ end }}
 include:
   - resources/*.yml
   - resources/*/*.yml
@@ -18,7 +25,14 @@ targets:
     default: true
     workspace:
       host: {{workspace_host}}
-
+{{ if ($with_classic) }}
+    presets:
+      # Set dynamic_version: true on all artifacts of type "whl".
+      # This makes "bundle deploy" add a timestamp to wheel's version before uploading,
+      # new wheel takes over the previous installation even if actual wheel version is unchanged.
+      # See https://docs.databricks.com/aws/en/dev-tools/bundles/settings
+      artifacts_dynamic_version: true
+{{ end }}
   prod:
     mode: production
     workspace:
diff --git a/libs/template/templates/default-python/template/{{.project_name}}/pyproject.toml.tmpl b/libs/template/templates/default-python/template/{{.project_name}}/pyproject.toml.tmpl
new file mode 100644
index 0000000000..5c06441fe8
--- /dev/null
+++ b/libs/template/templates/default-python/template/{{.project_name}}/pyproject.toml.tmpl
@@ -0,0 +1,41 @@
+[project]
+name = "{{.project_name}}"
+version = "0.0.1"
+authors = [{ name = "{{user_name}}" }]
+requires-python = ">= 3.11"
+
+[project.optional-dependencies]
+dev = [
+    "pytest",
+
+    # Code completion support for DLT, also install databricks-connect
+    "databricks-dlt",
+
+    # databricks-connect can be used to run parts of this project locally.
+    # See https://docs.databricks.com/dev-tools/databricks-connect.html.
+    #
+    # Note, databricks-connect is automatically installed if you're using Databricks
+    # extension for Visual Studio Code
+    # (https://docs.databricks.com/dev-tools/vscode-ext/dev-tasks/databricks-connect.html).
+    #
+    # To manually install databricks-connect, uncomment the line below to install a version
+    # of db-connect that corresponds to the Databricks Runtime version used for this project.
+    # See https://docs.databricks.com/dev-tools/databricks-connect.html
+    # "databricks-connect{{template "latest_lts_db_connect_version_spec"}}",
+]
+
+[tool.pytest.ini_options]
+pythonpath = "src"
+testpaths = [
+    "tests",
+]
+
+[build-system]
+requires = ["hatchling"]
+build-backend = "hatchling.build"
+
+[tool.hatch.build.targets.wheel]
+packages = ["src/{{.project_name}}"]
+
+[project.scripts]
+main = "{{.project_name}}.main:main"
diff --git a/libs/template/templates/default-python/template/{{.project_name}}/pytest.ini b/libs/template/templates/default-python/template/{{.project_name}}/pytest.ini
deleted file mode 100644
index 80432c2203..0000000000
--- a/libs/template/templates/default-python/template/{{.project_name}}/pytest.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[pytest]
-testpaths = tests
-pythonpath = src
diff --git a/libs/template/templates/default-python/template/{{.project_name}}/requirements-dev.txt.tmpl b/libs/template/templates/default-python/template/{{.project_name}}/requirements-dev.txt.tmpl
deleted file mode 100644
index 93dd4c4802..0000000000
--- a/libs/template/templates/default-python/template/{{.project_name}}/requirements-dev.txt.tmpl
+++ /dev/null
@@ -1,29 +0,0 @@
-## requirements-dev.txt: dependencies for local development.
-##
-## For defining dependencies used by jobs in Databricks Workflows, see
-## https://docs.databricks.com/dev-tools/bundles/library-dependencies.html
-
-## Add code completion support for DLT
-databricks-dlt
-
-## pytest is the default package used for testing
-pytest
-
-## Dependencies for building wheel files
-setuptools
-wheel
-
-## databricks-connect can be used to run parts of this project locally.
-## See https://docs.databricks.com/dev-tools/databricks-connect.html.
-##
-## databricks-connect is automatically installed if you're using Databricks
-## extension for Visual Studio Code
-## (https://docs.databricks.com/dev-tools/vscode-ext/dev-tasks/databricks-connect.html).
-##
-## To manually install databricks-connect, either follow the instructions
-## at https://docs.databricks.com/dev-tools/databricks-connect.html
-## to install the package system-wide. Or uncomment the line below to install a
-## version of db-connect that corresponds to the Databricks Runtime version used
-## for this project.
-#
-# databricks-connect{{template "latest_lts_db_connect_version_spec"}}
diff --git a/libs/template/templates/default-python/template/{{.project_name}}/setup.py.tmpl b/libs/template/templates/default-python/template/{{.project_name}}/setup.py.tmpl
deleted file mode 100644
index e3b70c6055..0000000000
--- a/libs/template/templates/default-python/template/{{.project_name}}/setup.py.tmpl
+++ /dev/null
@@ -1,41 +0,0 @@
-"""
-setup.py configuration script describing how to build and package this project.
-
-This file is primarily used by the setuptools library and typically should not
-be executed directly. See README.md for how to deploy, test, and run
-the {{.project_name}} project.
-"""
-
-from setuptools import setup, find_packages
-
-import sys
-
-sys.path.append("./src")
-
-import datetime
-import {{.project_name}}
-
-local_version = datetime.datetime.utcnow().strftime("%Y%m%d.%H%M%S")
-
-setup(
-    name="{{.project_name}}",
-    # We use timestamp as Local version identifier (https://peps.python.org/pep-0440/#local-version-identifiers.)
-    # to ensure that changes to wheel package are picked up when used on all-purpose clusters
-    version={{.project_name}}.__version__ + "+" + local_version,
-    url="https://databricks.com",
-    author="{{user_name}}",
-    description="wheel file based on {{.project_name}}/src",
-    packages=find_packages(where="./src"),
-    package_dir={"": "src"},
-    entry_points={
-        "packages": [
-            "main={{.project_name}}.main:main",
-        ],
-    },
-    install_requires=[
-        # Dependencies in case the output wheel file is used as a library dependency.
-        # For defining dependencies, when this package is used in Databricks, see:
-        # https://docs.databricks.com/dev-tools/bundles/library-dependencies.html
-        "setuptools"
-    ],
-)
diff --git a/libs/template/templates/default-python/template/{{.project_name}}/src/{{.project_name}}/__init__.py b/libs/template/templates/default-python/template/{{.project_name}}/src/{{.project_name}}/__init__.py
index f102a9cadf..e69de29bb2 100644
--- a/libs/template/templates/default-python/template/{{.project_name}}/src/{{.project_name}}/__init__.py
+++ b/libs/template/templates/default-python/template/{{.project_name}}/src/{{.project_name}}/__init__.py
@@ -1 +0,0 @@
-__version__ = "0.0.1"
