Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 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
39 changes: 38 additions & 1 deletion tortoise/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,14 @@

from collections.abc import Mapping
from dataclasses import dataclass, field
from typing import Any
from typing import TYPE_CHECKING, Any

from tortoise.exceptions import ConfigurationError

if TYPE_CHECKING:
from collections.abc import Iterable
from types import ModuleType


@dataclass(frozen=True)
class DBUrlConfig:
Expand Down Expand Up @@ -202,3 +206,36 @@ def from_dict(cls, data: Mapping[str, Any]) -> TortoiseConfig:
use_tz=data.get("use_tz"),
timezone=data.get("timezone"),
)

@classmethod
def merge_args(
Comment thread
waketzheng marked this conversation as resolved.
Outdated

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure the method name is clear, merge_args seems to create a merged configuration from config, config_file, db_url and modules, but this is actually not the case.

Maybe generate_config could be a better name.

Moreover, maybe we need to normalize the classmethods in this class:

@classmethod
def generate_config(
    cls,
    config: dict[str, Any] | Self | None = None,
    config_file: str | None = None,
    db_url: str | None = None,
    modules: dict[str, Iterable[str | ModuleType]] | None = None,
) -> Self:
    ...

@classmethod
def generate_config_from_db_url_and_modules(cls, db_url: str, modules: dict[str, Iterable[str | ModuleType]]) -> Self:
    ...

@classmethod
def generate_config_from_config_file(cls, config_file: str) -> Self:
    ...

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the suggestions. I’ve updated the naming:

  1. To keep consistent with from_dict, I’ll use from_db_url_and_modules / from_config_file.

  2. Since there’s already a parameter called config, I used resolve_args instead of generate_config to avoid confusion.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like the from_* convention and it's consistent with the existing code. Maybe we can rename resolve_args to from_args? 🤔

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we can rename resolve_args to from_args?

That is one solution. However, I strongly recommend using resolve_* instead of from_* for this function, because:

  1. resolve_* checks whether arguments conflict, whereas from_* does not.
  2. resolve indicates that this function will parse the arguments, not just load configuration from them.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think from_* is clearer, but we can let @abondar decide...

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@seladb Cloud you review #2170

Comment thread
waketzheng marked this conversation as resolved.
Outdated
cls,
config: dict[str, Any] | TortoiseConfig | None = None,
config_file: str | None = None,
db_url: str | None = None,
modules: dict[str, Iterable[str | ModuleType]] | None = None,
) -> TortoiseConfig:
# Handle config_file: load it as config dict
if config_file is not None:
from tortoise import Tortoise
Comment thread
waketzheng marked this conversation as resolved.
Outdated

if config is not None:
raise ConfigurationError("Cannot specify both 'config' and 'config_file'")
config = Tortoise._get_config_from_config_file(config_file)

# Convert input to TortoiseConfig for typed access
typed_config: TortoiseConfig
if config is None:
from tortoise.backends.base.config_generator import generate_config

if db_url is None or modules is None:
raise ConfigurationError(
"Must provide either 'config', 'config_file', or both 'db_url' and 'modules'"
)
config_dict = generate_config(db_url, app_modules=modules)
typed_config = cls.from_dict(config_dict)
elif isinstance(config, dict):
typed_config = cls.from_dict(config)
else:
typed_config = config
return typed_config
21 changes: 1 addition & 20 deletions tortoise/context.py
Original file line number Diff line number Diff line change
Expand Up @@ -303,26 +303,7 @@ async def init(
"""
from tortoise.apps import Apps

# Handle config_file: load it as config dict
if config_file is not None:
if config is not None:
raise ConfigurationError("Cannot specify both 'config' and 'config_file'")
config = self._get_config_from_config_file(config_file)

# Convert input to TortoiseConfig for typed access
typed_config: TortoiseConfig
if config is None:
if db_url is None or modules is None:
raise ConfigurationError(
"Must provide either 'config', 'config_file', or both 'db_url' and 'modules'"
)
config_dict = generate_config(db_url, app_modules=modules)
typed_config = TortoiseConfig.from_dict(config_dict)
elif isinstance(config, TortoiseConfig):
typed_config = config
else:
typed_config = TortoiseConfig.from_dict(config)

typed_config = TortoiseConfig.merge_args(config, config_file, db_url, modules)
config_dict = typed_config.to_dict()
connections_config = config_dict["connections"]
apps_config = config_dict["apps"]
Expand Down
Loading