Skip to content
Merged
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
10 changes: 3 additions & 7 deletions fastapi_mctools/commands/_templates/settings.py-tpl
Original file line number Diff line number Diff line change
@@ -1,14 +1,10 @@
from pathlib import Path
from decouple import AutoConfig
from zoneinfo import ZoneInfo, tz
from pydantic_settings import BaseSettings


BASE_DIR = Path(__file__).resolve().parent.parent
config = AutoConfig(search_path=BASE_DIR)
from zoneinfo import ZoneInfo
from pydantic_settings import BaseSettings, SettingsConfigDict


class AppSettings(BaseSettings):
model_config = SettingsConfigDict(env_file=".env", env_file_encoding="utf-8")
DEBUG: bool = config("DEBUG", cast=bool, default=True)
OPENAPI_URL: str | None = "/openapi.json" if DEBUG else None
Comment on lines 8 to 9

Choose a reason for hiding this comment

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

critical

These lines will cause NameError exceptions at runtime.

  1. On line 8, the config function is no longer defined since python-decouple was removed. With pydantic-settings, you can just declare the attribute with a default value.
  2. On line 9, DEBUG is not a defined variable in the class scope, so it cannot be used to define OPENAPI_URL.

To fix this and preserve the intended logic, you should use a Pydantic model_validator. This requires importing model_validator from pydantic.

Here's an example of the full implementation:

from pathlib import Path
from zoneinfo import ZoneInfo
from pydantic import model_validator
from pydantic_settings import BaseSettings, SettingsConfigDict


class AppSettings(BaseSettings):
    model_config = SettingsConfigDict(env_file=".env", env_file_encoding="utf-8")
    DEBUG: bool = True
    OPENAPI_URL: str | None = None
    API_PREFIX: str = "/api/v1"
    # ... other settings

    @model_validator(mode='after')
    def set_openapi_url(self) -> 'AppSettings':
        if self.DEBUG:
            self.OPENAPI_URL = "/openapi.json"
        return self

The suggested code below provides a minimal fix to make the template parsable, but I strongly recommend implementing the validator pattern for correct behavior.

    DEBUG: bool = True
    OPENAPI_URL: str | None = "/openapi.json"

API_PREFIX: str = "/api/v1"
Expand Down
6 changes: 3 additions & 3 deletions fastapi_mctools/db/sqlalchemy.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,11 @@ class AsyncDB:
get_db = AsyncDB(db_url)
"""

def __init__(self, db_url: str, meta: MetaData = None, **kwargs) -> None:
def __init__(self, db_url: str, meta: MetaData = None, engine_config: dict = {}, session_config: dict = {}) -> None:
self.db_url = db_url
self.meta = meta
self.__engine = create_async_engine(db_url)
self.__async_session = async_sessionmaker(self.__engine, **kwargs)
self.__engine = create_async_engine(db_url, **engine_config)
self.__async_session = async_sessionmaker(self.__engine, **session_config)
Comment on lines +34 to +38

Choose a reason for hiding this comment

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

high

Using mutable default arguments like {} for engine_config and session_config can lead to unexpected behavior. The same dictionary object will be reused across different calls to the constructor if no value is provided, which can cause side effects if the dictionary is modified in-place. The recommended practice is to use None as the default and create a new dictionary inside the method if one isn't provided.

Suggested change
def __init__(self, db_url: str, meta: MetaData = None, engine_config: dict = {}, session_config: dict = {}) -> None:
self.db_url = db_url
self.meta = meta
self.__engine = create_async_engine(db_url)
self.__async_session = async_sessionmaker(self.__engine, **kwargs)
self.__engine = create_async_engine(db_url, **engine_config)
self.__async_session = async_sessionmaker(self.__engine, **session_config)
def __init__(self, db_url: str, meta: MetaData = None, engine_config: dict | None = None, session_config: dict | None = None) -> None:
self.db_url = db_url
self.meta = meta
self.__engine = create_async_engine(db_url, **(engine_config or {}))
self.__async_session = async_sessionmaker(self.__engine, **(session_config or {}))


@property
def engine(self) -> Engine:
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "fastapi-mctools"
version = "0.5.2"
version = "0.6.0"
description = "Fastapi mc style tools to make it easier to develop."
authors = [
{name = "Jungminchae", email = "minchae3618@gmail.com"}
Expand Down