Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support python3.13 #11343

Open
wants to merge 11 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .changes/unreleased/Features-20250228-000153.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
kind: Features
body: Support Python 3.13
time: 2025-02-28T00:01:53.832242792+09:00
custom:
Author: FomalhautWeisszwerg
Issue: "11106"
4 changes: 2 additions & 2 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ jobs:
strategy:
fail-fast: false
matrix:
python-version: [ "3.9", "3.10", "3.11", "3.12" ]
python-version: [ "3.9", "3.10", "3.11", "3.12", "3.13" ]

env:
TOXENV: "unit"
Expand Down Expand Up @@ -162,7 +162,7 @@ jobs:
strategy:
fail-fast: false
matrix:
python-version: [ "3.9", "3.10", "3.11", "3.12" ]
python-version: [ "3.9", "3.10", "3.11", "3.12", "3.13" ]
os: [ubuntu-20.04]
split-group: ${{ fromJson(needs.integration-metadata.outputs.split-groups) }}
include: ${{ fromJson(needs.integration-metadata.outputs.include) }}
Expand Down
5 changes: 4 additions & 1 deletion core/dbt/artifacts/schemas/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import functools
from datetime import datetime
from typing import Any, ClassVar, Dict, Optional, Type, TypeVar
from zoneinfo import ZoneInfo

from mashumaro.jsonschema import build_json_schema
from mashumaro.jsonschema.dialects import DRAFT_2020_12
Expand Down Expand Up @@ -55,7 +56,9 @@ def read(cls, path: str):
class BaseArtifactMetadata(dbtClassMixin):
dbt_schema_version: str
dbt_version: str = __version__
generated_at: datetime = dataclasses.field(default_factory=datetime.utcnow)
generated_at: datetime = dataclasses.field(
default_factory=(lambda: datetime.now(ZoneInfo("UTC")))
)
invocation_id: Optional[str] = dataclasses.field(default_factory=get_invocation_id)
invocation_started_at: Optional[datetime] = dataclasses.field(
default_factory=get_invocation_started_at
Expand Down
5 changes: 3 additions & 2 deletions core/dbt/artifacts/schemas/results.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from dataclasses import dataclass
from datetime import datetime
from typing import Any, Callable, Dict, List, Optional, Sequence, Union
from zoneinfo import ZoneInfo

from dbt.contracts.graph.nodes import ResultNode
from dbt_common.dataclass_schema import StrEnum, dbtClassMixin
Expand All @@ -21,10 +22,10 @@ class TimingInfo(dbtClassMixin):
completed_at: Optional[datetime] = None

def begin(self):
self.started_at = datetime.utcnow()
self.started_at = datetime.now(ZoneInfo("UTC"))

def end(self):
self.completed_at = datetime.utcnow()
self.completed_at = datetime.now(ZoneInfo("UTC"))

def to_msg_dict(self):
msg_dict = {"name": str(self.name)}
Expand Down
3 changes: 2 additions & 1 deletion core/dbt/artifacts/schemas/run/v5/run.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from dataclasses import dataclass, field
from datetime import datetime
from typing import Any, Dict, Iterable, Optional, Sequence, Tuple
from zoneinfo import ZoneInfo

# https://github.com/dbt-labs/dbt-core/issues/10098
# Needed for Mashumaro serialization of RunResult below
Expand Down Expand Up @@ -101,7 +102,7 @@ class RunExecutionResult(
):
results: Sequence[RunResult]
args: Dict[str, Any] = field(default_factory=dict)
generated_at: datetime = field(default_factory=datetime.utcnow)
generated_at: datetime = field(default_factory=(lambda: datetime.now(ZoneInfo("UTC"))))

def write(self, path: str):
writable = RunResultsArtifact.from_execution_results(
Expand Down
2 changes: 1 addition & 1 deletion core/dbt/config/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ def load_raw_project(project_root: str) -> Dict[str, Any]:


def _query_comment_from_cfg(
cfg_query_comment: Union[QueryComment, NoValue, str, None]
cfg_query_comment: Union[QueryComment, NoValue, str, None],
) -> QueryComment:
if not cfg_query_comment:
return QueryComment(comment="")
Expand Down
3 changes: 2 additions & 1 deletion core/dbt/contracts/graph/node_args.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from dataclasses import dataclass, field
from datetime import datetime
from typing import List, Optional
from zoneinfo import ZoneInfo

from dbt.artifacts.resources import NodeVersion
from dbt.node_types import AccessType, NodeType
Expand All @@ -18,7 +19,7 @@ class ModelNodeArgs:
latest_version: Optional[NodeVersion] = None
deprecation_date: Optional[datetime] = None
access: Optional[str] = AccessType.Protected.value
generated_at: datetime = field(default_factory=datetime.utcnow)
generated_at: datetime = field(default_factory=(lambda: datetime.now(ZoneInfo("UTC"))))
depends_on_nodes: List[str] = field(default_factory=list)
enabled: bool = True

Expand Down
7 changes: 4 additions & 3 deletions core/dbt/contracts/sql.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from dataclasses import dataclass, field
from datetime import datetime
from typing import Any, Dict, List, Optional, Sequence
from zoneinfo import ZoneInfo

from dbt.artifacts.schemas.base import VersionedSchema, schema_version
from dbt.artifacts.schemas.results import ExecutionResult, TimingInfo
Expand All @@ -28,7 +29,7 @@ class RemoteCompileResultMixin(VersionedSchema):
@dataclass
@schema_version("remote-compile-result", 1)
class RemoteCompileResult(RemoteCompileResultMixin):
generated_at: datetime = field(default_factory=datetime.utcnow)
generated_at: datetime = field(default_factory=(lambda: datetime.now(ZoneInfo("UTC"))))

@property
def error(self) -> None:
Expand All @@ -41,7 +42,7 @@ def error(self) -> None:
class RemoteExecutionResult(ExecutionResult):
results: Sequence[RunResult]
args: Dict[str, Any] = field(default_factory=dict)
generated_at: datetime = field(default_factory=datetime.utcnow)
generated_at: datetime = field(default_factory=(lambda: datetime.now(ZoneInfo("UTC"))))

def write(self, path: str) -> None:
writable = RunResultsArtifact.from_execution_results(
Expand Down Expand Up @@ -76,4 +77,4 @@ class ResultTable(dbtClassMixin):
@schema_version("remote-run-result", 1)
class RemoteRunResult(RemoteCompileResultMixin):
table: ResultTable
generated_at: datetime = field(default_factory=datetime.utcnow)
generated_at: datetime = field(default_factory=(lambda: datetime.now(ZoneInfo("UTC"))))
2 changes: 1 addition & 1 deletion core/dbt/parser/manifest.py
Original file line number Diff line number Diff line change
Expand Up @@ -951,7 +951,7 @@ def read_manifest_for_partial_parse(self) -> Optional[Manifest]:
is_partial_parsable, reparse_reason = self.is_partial_parsable(manifest)
if is_partial_parsable:
# We don't want to have stale generated_at dates
manifest.metadata.generated_at = datetime.datetime.utcnow()
manifest.metadata.generated_at = datetime.datetime.now(datetime.UTC)
# or invocation_ids
manifest.metadata.invocation_id = get_invocation_id()
return manifest
Expand Down
2 changes: 1 addition & 1 deletion core/dbt/parser/schema_yaml_readers.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@


def parse_where_filter(
where: Optional[Union[List[str], str]]
where: Optional[Union[List[str], str]],
) -> Optional[WhereFilterIntersection]:
if where is None:
return None
Expand Down
3 changes: 2 additions & 1 deletion core/dbt/task/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from datetime import datetime
from pathlib import Path
from typing import Any, Dict, List, Optional, Set
from zoneinfo import ZoneInfo

import dbt.exceptions
import dbt_common.exceptions.base
Expand Down Expand Up @@ -210,7 +211,7 @@ def run_with_hooks(self, manifest):

result = self.safe_run(manifest)
self.node.update_event_status(
node_status=result.status, finished_at=datetime.utcnow().isoformat()
node_status=result.status, finished_at=datetime.now(ZoneInfo("UTC")).isoformat()
)

if not self.node.is_ephemeral_model:
Expand Down
5 changes: 3 additions & 2 deletions core/dbt/task/docs/generate.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from datetime import datetime
from itertools import chain
from typing import Any, Dict, Iterable, List, Optional, Set, Tuple
from zoneinfo import ZoneInfo

import agate

Expand Down Expand Up @@ -223,7 +224,7 @@ def run(self) -> CatalogArtifact:
return CatalogArtifact.from_results(
nodes={},
sources={},
generated_at=datetime.utcnow(),
generated_at=datetime.now(ZoneInfo("UTC")),
errors=None,
compile_results=compile_results,
)
Expand Down Expand Up @@ -303,7 +304,7 @@ def run(self) -> CatalogArtifact:
results = self.get_catalog_results(
nodes=nodes,
sources=sources,
generated_at=datetime.utcnow(),
generated_at=datetime.now(ZoneInfo("UTC")),
compile_results=compile_results,
errors=errors,
)
Expand Down
7 changes: 4 additions & 3 deletions core/dbt/task/run.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from datetime import datetime
from multiprocessing.pool import ThreadPool
from typing import AbstractSet, Any, Dict, Iterable, List, Optional, Set, Tuple, Type
from zoneinfo import ZoneInfo

from dbt import tracking, utils
from dbt.adapters.base import BaseAdapter, BaseRelation
Expand Down Expand Up @@ -913,7 +914,7 @@ def safe_run_hooks(
adapter, hook, hook.index, num_hooks, extra_context
)

started_at = timing[0].started_at or datetime.utcnow()
started_at = timing[0].started_at or datetime.now(ZoneInfo("UTC"))
hook.update_event_status(
started_at=started_at.isoformat(), node_status=RunningStatus.Started
)
Expand All @@ -930,7 +931,7 @@ def safe_run_hooks(
with collect_timing_info("execute", timing.append):
status, message = get_execution_status(sql, adapter)

finished_at = timing[1].completed_at or datetime.utcnow()
finished_at = timing[1].completed_at or datetime.now(ZoneInfo("UTC"))
hook.update_event_status(finished_at=finished_at.isoformat())
execution_time = (finished_at - started_at).total_seconds()
failures = 0 if status == RunStatus.Success else 1
Expand Down Expand Up @@ -1038,7 +1039,7 @@ def after_run(self, adapter, results) -> None:
run_result = self.get_result(
results=self.node_results,
elapsed_time=time.time() - self.started_at,
generated_at=datetime.utcnow(),
generated_at=datetime.now(ZoneInfo("UTC")),
)

if self.args.write_json and hasattr(run_result, "write"):
Expand Down
3 changes: 2 additions & 1 deletion core/dbt/task/run_operation.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import traceback
from datetime import datetime
from typing import TYPE_CHECKING, List
from zoneinfo import ZoneInfo

import dbt_common.exceptions
from dbt.adapters.factory import get_adapter
Expand Down Expand Up @@ -116,7 +117,7 @@ def run(self) -> RunResultsArtifact:
)

results = RunResultsArtifact.from_execution_results(
generated_at=end or datetime.utcnow(),
generated_at=end or datetime.now(ZoneInfo("UTC")),
elapsed_time=execution_time,
args={
k: v
Expand Down
12 changes: 8 additions & 4 deletions core/dbt/task/runnable.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from multiprocessing.dummy import Pool as ThreadPool
from pathlib import Path
from typing import AbstractSet, Dict, Iterable, List, Optional, Set, Tuple, Type, Union
from zoneinfo import ZoneInfo

import dbt.exceptions
import dbt.tracking
Expand Down Expand Up @@ -225,7 +226,8 @@ def get_runner(self, node) -> BaseRunner:
def call_runner(self, runner: BaseRunner) -> RunResult:
with log_contextvars(node_info=runner.node.node_info):
runner.node.update_event_status(
started_at=datetime.utcnow().isoformat(), node_status=RunningStatus.Started
started_at=datetime.now(ZoneInfo("UTC")).isoformat(),
node_status=RunningStatus.Started,
)
fire_event(
NodeStart(
Expand Down Expand Up @@ -430,7 +432,7 @@ def execute_nodes(self):
run_result = self.get_result(
results=self.node_results,
elapsed_time=time.time() - self.started_at,
generated_at=datetime.utcnow(),
generated_at=datetime.now(ZoneInfo("UTC")),
)

if self.args.write_json and hasattr(run_result, "write"):
Expand Down Expand Up @@ -562,7 +564,9 @@ def execute_with_hooks(self, selected_uids: AbstractSet[str]):
elapsed = time.time() - self.started_at
self.print_results_line(self.node_results, elapsed)
result = self.get_result(
results=self.node_results, elapsed_time=elapsed, generated_at=datetime.utcnow()
results=self.node_results,
elapsed_time=elapsed,
generated_at=datetime.now(ZoneInfo("UTC")),
)

return result
Expand All @@ -585,7 +589,7 @@ def run(self):
warn_or_error(NothingToDo())
result = self.get_result(
results=[],
generated_at=datetime.utcnow(),
generated_at=datetime.now(ZoneInfo("UTC")),
elapsed_time=0.0,
)
else:
Expand Down
9 changes: 5 additions & 4 deletions core/dbt/task/sql.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from abc import abstractmethod
from datetime import datetime
from typing import Generic, TypeVar
from zoneinfo import ZoneInfo

import dbt.exceptions
import dbt_common.exceptions.base
Expand Down Expand Up @@ -68,7 +69,7 @@ def execute(self, compiled_node, manifest) -> RemoteCompileResult:
compiled_code=compiled_node.compiled_code,
node=compiled_node,
timing=[], # this will get added later
generated_at=datetime.utcnow(),
generated_at=datetime.now(ZoneInfo("UTC")),
)

def from_run_result(self, result, start_time, timing_info) -> RemoteCompileResult:
Expand All @@ -77,7 +78,7 @@ def from_run_result(self, result, start_time, timing_info) -> RemoteCompileResul
compiled_code=result.compiled_code,
node=result.node,
timing=timing_info,
generated_at=datetime.utcnow(),
generated_at=datetime.now(ZoneInfo("UTC")),
)


Expand All @@ -96,7 +97,7 @@ def execute(self, compiled_node, manifest) -> RemoteRunResult:
node=compiled_node,
table=table,
timing=[],
generated_at=datetime.utcnow(),
generated_at=datetime.now(ZoneInfo("UTC")),
)

def from_run_result(self, result, start_time, timing_info) -> RemoteRunResult:
Expand All @@ -106,5 +107,5 @@ def from_run_result(self, result, start_time, timing_info) -> RemoteRunResult:
node=result.node,
table=result.table,
timing=timing_info,
generated_at=datetime.utcnow(),
generated_at=datetime.now(ZoneInfo("UTC")),
)
5 changes: 4 additions & 1 deletion core/dbt/tests/fixtures/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from datetime import datetime
from pathlib import Path
from typing import Mapping
from zoneinfo import ZoneInfo

import pytest # type: ignore
import yaml
Expand Down Expand Up @@ -75,7 +76,9 @@
def prefix():
# create a directory name that will be unique per test session
_randint = random.randint(0, 9999)
_runtime_timedelta = datetime.utcnow() - datetime(1970, 1, 1, 0, 0, 0)
_runtime_timedelta = datetime.now(ZoneInfo("UTC")) - datetime(
1970, 1, 1, 0, 0, 0, tzinfo=ZoneInfo("UTC")
)
_runtime = (int(_runtime_timedelta.total_seconds() * 1e6)) + _runtime_timedelta.microseconds
prefix = f"test{_runtime}{_randint:04}"
return prefix
Expand Down
3 changes: 2 additions & 1 deletion core/dbt/tests/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from io import StringIO
from typing import Any, Callable, Dict, List, Optional
from unittest import mock
from zoneinfo import ZoneInfo

import pytz
import yaml
Expand Down Expand Up @@ -284,7 +285,7 @@ def check_result_nodes_by_unique_id(results, unique_ids):
def check_datetime_between(timestr, start, end=None):
datefmt = "%Y-%m-%dT%H:%M:%S.%fZ"
if end is None:
end = datetime.utcnow()
end = datetime.now(ZoneInfo("UTC"))
parsed = datetime.strptime(timestr, datefmt)
assert start <= parsed
assert end >= parsed
Expand Down
2 changes: 1 addition & 1 deletion core/dbt/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ def add_ephemeral_model_prefix(s: str) -> str:
def timestring() -> str:
"""Get the current datetime as an RFC 3339-compliant string"""
# isoformat doesn't include the mandatory trailing 'Z' for UTC.
return datetime.datetime.utcnow().isoformat() + "Z"
return datetime.datetime.now(datetime.UTC).isoformat() + "Z"


def humanize_execution_time(execution_time: int) -> str:
Expand Down
2 changes: 2 additions & 0 deletions core/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,10 +89,12 @@
"Operating System :: Microsoft :: Windows",
"Operating System :: MacOS :: MacOS X",
"Operating System :: POSIX :: Linux",
"Programming Language :: Python :: 3 :: Only",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
],
python_requires=">=3.9",
)
Loading
Loading