fastlib-py 0.2.4__tar.gz → 0.2.5__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {fastlib_py-0.2.4 → fastlib_py-0.2.5}/PKG-INFO +1 -1
- {fastlib_py-0.2.4 → fastlib_py-0.2.5}/fastlib/__init__.py +2 -0
- fastlib_py-0.2.5/fastlib/config/base.py +8 -0
- {fastlib_py-0.2.4 → fastlib_py-0.2.5}/fastlib/config/utils.py +1 -1
- {fastlib_py-0.2.4 → fastlib_py-0.2.5}/fastlib/exception/base.py +1 -2
- fastlib_py-0.2.5/fastlib/i18n/__init__.py +1 -0
- {fastlib_py-0.2.4 → fastlib_py-0.2.5}/fastlib/i18n/manager.py +5 -5
- {fastlib_py-0.2.4 → fastlib_py-0.2.5}/fastlib/logging/__init__.py +4 -1
- fastlib_py-0.2.5/fastlib/logging/config.py +102 -0
- fastlib_py-0.2.5/fastlib/logging/handlers.py +172 -0
- {fastlib_py-0.2.4 → fastlib_py-0.2.5}/fastlib/middleware/jwt.py +2 -2
- {fastlib_py-0.2.4/fastlib/schema → fastlib_py-0.2.5/fastlib}/response.py +4 -2
- fastlib_py-0.2.4/fastlib/schema/base.py → fastlib_py-0.2.5/fastlib/schema.py +11 -12
- {fastlib_py-0.2.4 → fastlib_py-0.2.5}/fastlib/session/db_engine.py +0 -2
- {fastlib_py-0.2.4 → fastlib_py-0.2.5}/fastlib_py.egg-info/PKG-INFO +1 -1
- {fastlib_py-0.2.4 → fastlib_py-0.2.5}/fastlib_py.egg-info/SOURCES.txt +8 -12
- {fastlib_py-0.2.4 → fastlib_py-0.2.5}/pyproject.toml +126 -126
- fastlib_py-0.2.4/fastlib/config/base.py +0 -17
- fastlib_py-0.2.4/fastlib/enums/__init__.py +0 -9
- fastlib_py-0.2.4/fastlib/logging/config.py +0 -75
- fastlib_py-0.2.4/fastlib/logging/handlers.py +0 -221
- fastlib_py-0.2.4/fastlib/openapi/__init__.py +0 -5
- fastlib_py-0.2.4/fastlib/router/__init__.py +0 -5
- fastlib_py-0.2.4/fastlib/schema/__init__.py +0 -19
- fastlib_py-0.2.4/fastlib/service/impl/__init__.py +0 -0
- {fastlib_py-0.2.4 → fastlib_py-0.2.5}/LICENSE +0 -0
- {fastlib_py-0.2.4 → fastlib_py-0.2.5}/README.md +0 -0
- {fastlib_py-0.2.4 → fastlib_py-0.2.5}/fastlib/cache/__init__.py +0 -0
- {fastlib_py-0.2.4 → fastlib_py-0.2.5}/fastlib/cache/base.py +0 -0
- {fastlib_py-0.2.4 → fastlib_py-0.2.5}/fastlib/cache/disk_cache.py +0 -0
- {fastlib_py-0.2.4 → fastlib_py-0.2.5}/fastlib/cache/manager.py +0 -0
- {fastlib_py-0.2.4 → fastlib_py-0.2.5}/fastlib/cache/redis_cache.py +0 -0
- {fastlib_py-0.2.4 → fastlib_py-0.2.5}/fastlib/config/__init__.py +0 -0
- {fastlib_py-0.2.4 → fastlib_py-0.2.5}/fastlib/config/database_config.py +0 -0
- {fastlib_py-0.2.4 → fastlib_py-0.2.5}/fastlib/config/loader.py +0 -0
- {fastlib_py-0.2.4 → fastlib_py-0.2.5}/fastlib/config/manager.py +0 -0
- {fastlib_py-0.2.4 → fastlib_py-0.2.5}/fastlib/config/registry.py +0 -0
- {fastlib_py-0.2.4 → fastlib_py-0.2.5}/fastlib/config/security_config.py +0 -0
- {fastlib_py-0.2.4 → fastlib_py-0.2.5}/fastlib/config/server_config.py +0 -0
- {fastlib_py-0.2.4 → fastlib_py-0.2.5}/fastlib/constant/__init__.py +0 -0
- {fastlib_py-0.2.4 → fastlib_py-0.2.5}/fastlib/constant/constant.py +0 -0
- {fastlib_py-0.2.4/fastlib/context → fastlib_py-0.2.5/fastlib}/contextvars.py +0 -0
- /fastlib_py-0.2.4/fastlib/enums/base.py → /fastlib_py-0.2.5/fastlib/enums.py +0 -0
- {fastlib_py-0.2.4 → fastlib_py-0.2.5}/fastlib/exception/__init__.py +0 -0
- {fastlib_py-0.2.4 → fastlib_py-0.2.5}/fastlib/exception/exception_handler.py +0 -0
- {fastlib_py-0.2.4 → fastlib_py-0.2.5}/fastlib/exception/exception_manager.py +0 -0
- {fastlib_py-0.2.4 → fastlib_py-0.2.5}/fastlib/i18n/messages.py +0 -0
- {fastlib_py-0.2.4 → fastlib_py-0.2.5}/fastlib/i18n/types.py +0 -0
- {fastlib_py-0.2.4 → fastlib_py-0.2.5}/fastlib/i18n/utils.py +0 -0
- {fastlib_py-0.2.4/fastlib/context → fastlib_py-0.2.5/fastlib/mapper}/__init__.py +0 -0
- {fastlib_py-0.2.4 → fastlib_py-0.2.5}/fastlib/mapper/base_mapper.py +0 -0
- {fastlib_py-0.2.4/fastlib/mapper → fastlib_py-0.2.5/fastlib/mapper/impl}/__init__.py +0 -0
- {fastlib_py-0.2.4 → fastlib_py-0.2.5}/fastlib/mapper/impl/base_mapper_impl.py +0 -0
- {fastlib_py-0.2.4 → fastlib_py-0.2.5}/fastlib/middleware/__init__.py +0 -0
- {fastlib_py-0.2.4 → fastlib_py-0.2.5}/fastlib/middleware/db_session.py +0 -0
- {fastlib_py-0.2.4 → fastlib_py-0.2.5}/fastlib/middleware/i18n.py +0 -0
- {fastlib_py-0.2.4/fastlib/migrate → fastlib_py-0.2.5/fastlib}/migrate.py +0 -0
- /fastlib_py-0.2.4/fastlib/openapi/offline.py → /fastlib_py-0.2.5/fastlib/openapi.py +0 -0
- /fastlib_py-0.2.4/fastlib/router/base.py → /fastlib_py-0.2.5/fastlib/router.py +0 -0
- {fastlib_py-0.2.4 → fastlib_py-0.2.5}/fastlib/security/__init__.py +0 -0
- {fastlib_py-0.2.4 → fastlib_py-0.2.5}/fastlib/security/security.py +0 -0
- {fastlib_py-0.2.4 → fastlib_py-0.2.5}/fastlib/security/utils.py +0 -0
- {fastlib_py-0.2.4/fastlib/mapper/impl → fastlib_py-0.2.5/fastlib/service}/__init__.py +0 -0
- {fastlib_py-0.2.4 → fastlib_py-0.2.5}/fastlib/service/base_service.py +0 -0
- {fastlib_py-0.2.4/fastlib/service → fastlib_py-0.2.5/fastlib/service/impl}/__init__.py +0 -0
- {fastlib_py-0.2.4 → fastlib_py-0.2.5}/fastlib/service/impl/base_service_impl.py +0 -0
- {fastlib_py-0.2.4 → fastlib_py-0.2.5}/fastlib/session/__init__.py +0 -0
- {fastlib_py-0.2.4 → fastlib_py-0.2.5}/fastlib/session/db_session.py +0 -0
- {fastlib_py-0.2.4 → fastlib_py-0.2.5}/fastlib/utils/__init__.py +0 -0
- {fastlib_py-0.2.4 → fastlib_py-0.2.5}/fastlib/utils/excel_util.py +0 -0
- {fastlib_py-0.2.4 → fastlib_py-0.2.5}/fastlib/utils/file_util.py +0 -0
- {fastlib_py-0.2.4 → fastlib_py-0.2.5}/fastlib/utils/http_util.py +0 -0
- {fastlib_py-0.2.4 → fastlib_py-0.2.5}/fastlib/utils/ip_util.py +0 -0
- {fastlib_py-0.2.4 → fastlib_py-0.2.5}/fastlib/utils/snowflake_util.py +0 -0
- {fastlib_py-0.2.4 → fastlib_py-0.2.5}/fastlib/utils/str_util.py +0 -0
- {fastlib_py-0.2.4 → fastlib_py-0.2.5}/fastlib_py.egg-info/dependency_links.txt +0 -0
- {fastlib_py-0.2.4 → fastlib_py-0.2.5}/fastlib_py.egg-info/requires.txt +0 -0
- {fastlib_py-0.2.4 → fastlib_py-0.2.5}/fastlib_py.egg-info/top_level.txt +0 -0
- {fastlib_py-0.2.4 → fastlib_py-0.2.5}/setup.cfg +0 -0
|
@@ -5,10 +5,12 @@ from .config import ConfigManager as ConfigManager
|
|
|
5
5
|
from .constant import constant as constant
|
|
6
6
|
from .logging import LogConfig as LogConfig
|
|
7
7
|
from .logging import Logger as Logger
|
|
8
|
+
from .openapi import register_offline_openapi as register_offline_openapi
|
|
8
9
|
|
|
9
10
|
__all__ = [
|
|
10
11
|
"ConfigManager",
|
|
11
12
|
"Logger",
|
|
12
13
|
"LogConfig",
|
|
13
14
|
"constant",
|
|
15
|
+
"register_offline_openapi",
|
|
14
16
|
]
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# SPDX-License-Identifier: MIT
|
|
@@ -56,11 +56,6 @@ class I18nContext:
|
|
|
56
56
|
_language_context.reset(self._token)
|
|
57
57
|
|
|
58
58
|
|
|
59
|
-
def with_language(language: Language) -> I18nContext:
|
|
60
|
-
"""Helper to create context manager"""
|
|
61
|
-
return I18nContext(language)
|
|
62
|
-
|
|
63
|
-
|
|
64
59
|
def _language_context_decorator(
|
|
65
60
|
language: Language, is_async: bool = False
|
|
66
61
|
) -> Callable[[F], F]:
|
|
@@ -97,3 +92,8 @@ def async_language_context(
|
|
|
97
92
|
) -> Callable[[Callable[..., Awaitable[Any]]], Callable[..., Awaitable[Any]]]:
|
|
98
93
|
"""Decorator: run an async function within a language context"""
|
|
99
94
|
return _language_context_decorator(language, is_async=True)
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def i18n_context(language: Language) -> I18nContext:
|
|
98
|
+
"""Helper to create context manager"""
|
|
99
|
+
return I18nContext(language)
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
# SPDX-License-Identifier: MIT
|
|
2
|
+
"""
|
|
3
|
+
Log configuration and logging utility for the application.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
from typing import Literal, Optional
|
|
8
|
+
|
|
9
|
+
from fastlib.config.base import BaseConfig
|
|
10
|
+
from fastlib.config.manager import config_class
|
|
11
|
+
from fastlib.config.utils import ProjectInfo
|
|
12
|
+
|
|
13
|
+
LogLevel = Literal["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"]
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@config_class("log")
|
|
17
|
+
class LogConfig(BaseConfig):
|
|
18
|
+
"""Configuration for logging settings."""
|
|
19
|
+
|
|
20
|
+
def __init__(
|
|
21
|
+
self,
|
|
22
|
+
log_dir: str = "/var/log",
|
|
23
|
+
app_name: str = None,
|
|
24
|
+
log_level: LogLevel = "INFO",
|
|
25
|
+
log_rotation: str = "1 day",
|
|
26
|
+
log_retention: str = "90 days",
|
|
27
|
+
enable_console_log: bool = True,
|
|
28
|
+
enable_json_logs: bool = False,
|
|
29
|
+
error_log_rotation: str = "1 day",
|
|
30
|
+
error_log_retention: str = "90 days",
|
|
31
|
+
enable_async: bool = True,
|
|
32
|
+
max_file_size: Optional[str] = "10 MB",
|
|
33
|
+
time_format: str = "YYYY-MM-DD",
|
|
34
|
+
**kwargs,
|
|
35
|
+
):
|
|
36
|
+
"""
|
|
37
|
+
Initialize LogConfig with logging settings.
|
|
38
|
+
|
|
39
|
+
Args:
|
|
40
|
+
log_dir: Directory where log files will be stored
|
|
41
|
+
app_name: Name of the application for log file naming
|
|
42
|
+
log_level: Minimum log level to record
|
|
43
|
+
log_rotation: How often to rotate log files
|
|
44
|
+
log_retention: How long to keep log files
|
|
45
|
+
enable_console_log: Whether to output logs to console
|
|
46
|
+
enable_json_logs: Whether to use JSON format for logs
|
|
47
|
+
error_log_rotation: How often to rotate error log files
|
|
48
|
+
error_log_retention: How long to keep error log files
|
|
49
|
+
enable_async: Whether to use asynchronous logging
|
|
50
|
+
max_file_size: Maximum size for log files before rotation
|
|
51
|
+
time_format: Format string for timestamps in log file names
|
|
52
|
+
**kwargs: Additional keyword arguments for base class
|
|
53
|
+
"""
|
|
54
|
+
# Set app_name default if not provided
|
|
55
|
+
if app_name is None:
|
|
56
|
+
app_name = ProjectInfo.from_pyproject().name
|
|
57
|
+
|
|
58
|
+
# Initialize instance attributes directly
|
|
59
|
+
self.log_dir = log_dir
|
|
60
|
+
self.app_name = app_name
|
|
61
|
+
self.log_level = log_level
|
|
62
|
+
self.log_rotation = log_rotation
|
|
63
|
+
self.log_retention = log_retention
|
|
64
|
+
self.enable_console_log = enable_console_log
|
|
65
|
+
self.enable_json_logs = enable_json_logs
|
|
66
|
+
self.error_log_rotation = error_log_rotation
|
|
67
|
+
self.error_log_retention = error_log_retention
|
|
68
|
+
self.enable_async = enable_async
|
|
69
|
+
self.max_file_size = max_file_size
|
|
70
|
+
self.time_format = time_format
|
|
71
|
+
|
|
72
|
+
# Handle any additional kwargs for base class
|
|
73
|
+
if kwargs:
|
|
74
|
+
# If base class needs special handling, you can add it here
|
|
75
|
+
# For now, we'll set them as instance attributes
|
|
76
|
+
for key, value in kwargs.items():
|
|
77
|
+
setattr(self, key, value)
|
|
78
|
+
|
|
79
|
+
@property
|
|
80
|
+
def default_format(self) -> str:
|
|
81
|
+
"""Default log format string."""
|
|
82
|
+
return "{time:YYYY-MM-DD HH:mm:ss.SSS} | {level: <8} | {name}:{function}:{line} | {message}"
|
|
83
|
+
|
|
84
|
+
@property
|
|
85
|
+
def log_file_pattern(self) -> str:
|
|
86
|
+
"""Returns the main log file pattern with timestamp."""
|
|
87
|
+
return f"{{time:{self.time_format}}}_{self.app_name}.log"
|
|
88
|
+
|
|
89
|
+
@property
|
|
90
|
+
def error_log_file_pattern(self) -> str:
|
|
91
|
+
"""Returns the error log file pattern with timestamp."""
|
|
92
|
+
return f"{{time:{self.time_format}}}_error_{self.app_name}.log"
|
|
93
|
+
|
|
94
|
+
@property
|
|
95
|
+
def log_file_path(self) -> Path:
|
|
96
|
+
"""Returns the full path for the main log file."""
|
|
97
|
+
return Path(self.log_dir) / self.log_file_pattern
|
|
98
|
+
|
|
99
|
+
@property
|
|
100
|
+
def error_log_file_path(self) -> Path:
|
|
101
|
+
"""Returns the full path for the error log file."""
|
|
102
|
+
return Path(self.log_dir) / self.error_log_file_pattern
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
# SPDX-License-Identifier: MIT
|
|
2
|
+
"""
|
|
3
|
+
A comprehensive logging tool for the application.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
import sys
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
from typing import Optional
|
|
9
|
+
|
|
10
|
+
from loguru import logger
|
|
11
|
+
|
|
12
|
+
from fastlib.config.manager import ConfigManager
|
|
13
|
+
from fastlib.logging.config import LogConfig
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class Logger:
|
|
17
|
+
"""
|
|
18
|
+
Enhanced logging tool support structured logging.
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
_instances: dict[str, "Logger"] = {}
|
|
22
|
+
_config: Optional[LogConfig] = None
|
|
23
|
+
_is_configured: bool = False
|
|
24
|
+
|
|
25
|
+
@classmethod
|
|
26
|
+
def initialize(cls) -> "Logger":
|
|
27
|
+
"""
|
|
28
|
+
Initialize the logging system.
|
|
29
|
+
|
|
30
|
+
Returns:
|
|
31
|
+
Logger instance
|
|
32
|
+
"""
|
|
33
|
+
if not cls._is_configured:
|
|
34
|
+
# Load configuration first
|
|
35
|
+
cls._config = cls._get_config()
|
|
36
|
+
# Create and configure the logger
|
|
37
|
+
instance = cls.get_instance()
|
|
38
|
+
cls._is_configured = True
|
|
39
|
+
return instance
|
|
40
|
+
return cls.get_instance()
|
|
41
|
+
|
|
42
|
+
@classmethod
|
|
43
|
+
def _get_config(cls) -> LogConfig:
|
|
44
|
+
"""Lazy load configuration."""
|
|
45
|
+
if cls._config is None:
|
|
46
|
+
cls._config = ConfigManager.get_config_instance("log")
|
|
47
|
+
return cls._config
|
|
48
|
+
|
|
49
|
+
@classmethod
|
|
50
|
+
def get_instance(
|
|
51
|
+
cls,
|
|
52
|
+
name: Optional[str] = None,
|
|
53
|
+
) -> "Logger":
|
|
54
|
+
"""
|
|
55
|
+
Get or create a named logger instance.
|
|
56
|
+
|
|
57
|
+
Args:
|
|
58
|
+
name: Logger instance name
|
|
59
|
+
|
|
60
|
+
Returns:
|
|
61
|
+
Logger instance
|
|
62
|
+
"""
|
|
63
|
+
# Ensure config is loaded
|
|
64
|
+
if cls._config is None:
|
|
65
|
+
cls._config = cls._get_config()
|
|
66
|
+
|
|
67
|
+
if not name:
|
|
68
|
+
name = cls._config.app_name
|
|
69
|
+
|
|
70
|
+
if name not in cls._instances:
|
|
71
|
+
cls._instances[name] = cls(name)
|
|
72
|
+
return cls._instances[name]
|
|
73
|
+
|
|
74
|
+
def __init__(self, name: str):
|
|
75
|
+
"""Initialize the Logger with optional overrides."""
|
|
76
|
+
self.name = name
|
|
77
|
+
|
|
78
|
+
# Get configuration
|
|
79
|
+
self._config = self._get_config()
|
|
80
|
+
|
|
81
|
+
# Only setup logging once globally
|
|
82
|
+
if not self.__class__._is_configured:
|
|
83
|
+
self._setup_logging()
|
|
84
|
+
|
|
85
|
+
def _setup_logging(self) -> None:
|
|
86
|
+
"""Configure loguru logger with handlers based on configuration."""
|
|
87
|
+
# Remove default handler
|
|
88
|
+
logger.remove()
|
|
89
|
+
|
|
90
|
+
config = self._config
|
|
91
|
+
|
|
92
|
+
# Create log directory
|
|
93
|
+
Path(config.log_dir).mkdir(parents=True, exist_ok=True)
|
|
94
|
+
|
|
95
|
+
# Console handler
|
|
96
|
+
if config.enable_console_log:
|
|
97
|
+
logger.add(
|
|
98
|
+
sys.stderr,
|
|
99
|
+
format=self._get_format_string(),
|
|
100
|
+
level=config.log_level,
|
|
101
|
+
colorize=True,
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
# Main file handler
|
|
105
|
+
rotation = config.max_file_size or config.log_rotation
|
|
106
|
+
|
|
107
|
+
logger.add(
|
|
108
|
+
str(config.log_file_path),
|
|
109
|
+
format=self._get_format_string(),
|
|
110
|
+
level=config.log_level,
|
|
111
|
+
rotation=rotation,
|
|
112
|
+
retention=config.log_retention,
|
|
113
|
+
compression="zip",
|
|
114
|
+
serialize=config.enable_json_logs,
|
|
115
|
+
enqueue=config.enable_async,
|
|
116
|
+
)
|
|
117
|
+
|
|
118
|
+
# Error log handler - only add if log level is not ERROR or CRITICAL
|
|
119
|
+
if config.log_level not in ["ERROR", "CRITICAL"]:
|
|
120
|
+
logger.add(
|
|
121
|
+
str(config.error_log_file_path),
|
|
122
|
+
format=self._get_format_string(),
|
|
123
|
+
level="ERROR",
|
|
124
|
+
rotation=config.error_log_rotation,
|
|
125
|
+
retention=config.error_log_retention,
|
|
126
|
+
compression="zip",
|
|
127
|
+
serialize=config.enable_json_logs,
|
|
128
|
+
enqueue=config.enable_async,
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
def _get_format_string(self) -> str:
|
|
132
|
+
"""Get the log format string."""
|
|
133
|
+
config = self._config
|
|
134
|
+
|
|
135
|
+
if config.enable_json_logs:
|
|
136
|
+
# JSON logs don't need format string
|
|
137
|
+
return "{message}"
|
|
138
|
+
|
|
139
|
+
return config.default_format
|
|
140
|
+
|
|
141
|
+
# Convenience methods for logging
|
|
142
|
+
def debug(self, message: str, **kwargs) -> None:
|
|
143
|
+
"""Log debug message."""
|
|
144
|
+
logger.bind(logger_name=self.name).debug(message, **kwargs)
|
|
145
|
+
|
|
146
|
+
def info(self, message: str, **kwargs) -> None:
|
|
147
|
+
"""Log info message."""
|
|
148
|
+
logger.bind(logger_name=self.name).info(message, **kwargs)
|
|
149
|
+
|
|
150
|
+
def warning(self, message: str, **kwargs) -> None:
|
|
151
|
+
"""Log warning message."""
|
|
152
|
+
logger.bind(logger_name=self.name).warning(message, **kwargs)
|
|
153
|
+
|
|
154
|
+
def error(self, message: str, **kwargs) -> None:
|
|
155
|
+
"""Log error message."""
|
|
156
|
+
logger.bind(logger_name=self.name).error(message, **kwargs)
|
|
157
|
+
|
|
158
|
+
def critical(self, message: str, **kwargs) -> None:
|
|
159
|
+
"""Log critical message."""
|
|
160
|
+
logger.bind(logger_name=self.name).critical(message, **kwargs)
|
|
161
|
+
|
|
162
|
+
def exception(self, message: str, **kwargs) -> None:
|
|
163
|
+
"""Log exception with traceback."""
|
|
164
|
+
logger.bind(logger_name=self.name).exception(message, **kwargs)
|
|
165
|
+
|
|
166
|
+
@classmethod
|
|
167
|
+
def reset(cls) -> None:
|
|
168
|
+
"""Reset all logger instances and configuration (useful for testing)."""
|
|
169
|
+
cls._instances.clear()
|
|
170
|
+
cls._config = None
|
|
171
|
+
cls._is_configured = False
|
|
172
|
+
logger.remove()
|
|
@@ -10,8 +10,8 @@ from loguru import logger
|
|
|
10
10
|
from starlette.responses import JSONResponse
|
|
11
11
|
|
|
12
12
|
from fastlib import ConfigManager, constant, security
|
|
13
|
-
from fastlib.
|
|
14
|
-
from fastlib.enums
|
|
13
|
+
from fastlib.contextvars import current_user_id
|
|
14
|
+
from fastlib.enums import MediaTypeEnum
|
|
15
15
|
from fastlib.schema import UserCredential
|
|
16
16
|
|
|
17
17
|
# Load configuration
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# SPDX-License-Identifier: MIT
|
|
2
2
|
"""Standardized HTTP response model for API implementations."""
|
|
3
3
|
|
|
4
|
-
from typing import Any, Generic, Optional, TypeVar, Union
|
|
4
|
+
from typing import Any, Generic, Optional, TypeVar, Union, overload
|
|
5
5
|
|
|
6
6
|
from pydantic import BaseModel, model_serializer
|
|
7
7
|
|
|
@@ -57,6 +57,7 @@ class HttpResponse(BaseModel, Generic[T]):
|
|
|
57
57
|
return HttpResponse[T](code=code, message=message, data=data)
|
|
58
58
|
|
|
59
59
|
@staticmethod
|
|
60
|
+
@overload
|
|
60
61
|
def fail(
|
|
61
62
|
message: str = str,
|
|
62
63
|
code: int = DEFAULT_FAIL_CODE,
|
|
@@ -76,7 +77,8 @@ class HttpResponse(BaseModel, Generic[T]):
|
|
|
76
77
|
return HttpResponse[Any](code=code, message=message, data=data)
|
|
77
78
|
|
|
78
79
|
@staticmethod
|
|
79
|
-
|
|
80
|
+
@overload
|
|
81
|
+
def fail(
|
|
80
82
|
error: Union[ErrorDetail, tuple[int, str]], # Supports multiple error types
|
|
81
83
|
extra_msg: Optional[str] = None,
|
|
82
84
|
) -> "HttpResponse[Any]":
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# SPDX-License-Identifier: MIT
|
|
2
2
|
"""Common schema with data validation."""
|
|
3
3
|
|
|
4
|
-
from typing import Generic, Optional, TypeVar
|
|
4
|
+
from typing import Generic, Literal, Optional, TypeVar
|
|
5
5
|
|
|
6
6
|
from pydantic import BaseModel, Field
|
|
7
7
|
|
|
@@ -53,18 +53,18 @@ class SortItem(BaseModel):
|
|
|
53
53
|
"""
|
|
54
54
|
|
|
55
55
|
field: str
|
|
56
|
-
order:
|
|
56
|
+
order: Literal["asc", "desc"]
|
|
57
57
|
|
|
58
58
|
|
|
59
|
-
class
|
|
59
|
+
class ListRequest(BaseModel):
|
|
60
60
|
"""
|
|
61
|
-
Pagination parameters for
|
|
61
|
+
Pagination and sorting parameters for list endpoints.
|
|
62
62
|
|
|
63
63
|
Attributes:
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
64
|
+
current: Current page number (1-based). Default: 1.
|
|
65
|
+
page_size: Items per page (1-1000). Default: 10.
|
|
66
|
+
count: Whether to return total count. Default: True.
|
|
67
|
+
sort_str: Optional sorting string (e.g., "field:asc,field2:desc").
|
|
68
68
|
"""
|
|
69
69
|
|
|
70
70
|
current: int = Field(default=1, gt=0, description="Current page number (1-based)")
|
|
@@ -74,9 +74,8 @@ class PaginationRequest(BaseModel):
|
|
|
74
74
|
le=1000,
|
|
75
75
|
description="Number of items per page (1-1000)",
|
|
76
76
|
)
|
|
77
|
-
count: bool = Field(
|
|
78
|
-
default=True, description="Flag to request total count of items"
|
|
79
|
-
)
|
|
77
|
+
count: bool = Field(default=True, description="Whether to return total count")
|
|
80
78
|
sort_str: Optional[str] = Field(
|
|
81
|
-
default=None,
|
|
79
|
+
default=None,
|
|
80
|
+
description='Optional sorting string (e.g., "field:asc,field2:desc")',
|
|
82
81
|
)
|
|
@@ -2,6 +2,13 @@ LICENSE
|
|
|
2
2
|
README.md
|
|
3
3
|
pyproject.toml
|
|
4
4
|
fastlib/__init__.py
|
|
5
|
+
fastlib/contextvars.py
|
|
6
|
+
fastlib/enums.py
|
|
7
|
+
fastlib/migrate.py
|
|
8
|
+
fastlib/openapi.py
|
|
9
|
+
fastlib/response.py
|
|
10
|
+
fastlib/router.py
|
|
11
|
+
fastlib/schema.py
|
|
5
12
|
fastlib/cache/__init__.py
|
|
6
13
|
fastlib/cache/base.py
|
|
7
14
|
fastlib/cache/disk_cache.py
|
|
@@ -18,14 +25,11 @@ fastlib/config/server_config.py
|
|
|
18
25
|
fastlib/config/utils.py
|
|
19
26
|
fastlib/constant/__init__.py
|
|
20
27
|
fastlib/constant/constant.py
|
|
21
|
-
fastlib/context/__init__.py
|
|
22
|
-
fastlib/context/contextvars.py
|
|
23
|
-
fastlib/enums/__init__.py
|
|
24
|
-
fastlib/enums/base.py
|
|
25
28
|
fastlib/exception/__init__.py
|
|
26
29
|
fastlib/exception/base.py
|
|
27
30
|
fastlib/exception/exception_handler.py
|
|
28
31
|
fastlib/exception/exception_manager.py
|
|
32
|
+
fastlib/i18n/__init__.py
|
|
29
33
|
fastlib/i18n/manager.py
|
|
30
34
|
fastlib/i18n/messages.py
|
|
31
35
|
fastlib/i18n/types.py
|
|
@@ -41,14 +45,6 @@ fastlib/middleware/__init__.py
|
|
|
41
45
|
fastlib/middleware/db_session.py
|
|
42
46
|
fastlib/middleware/i18n.py
|
|
43
47
|
fastlib/middleware/jwt.py
|
|
44
|
-
fastlib/migrate/migrate.py
|
|
45
|
-
fastlib/openapi/__init__.py
|
|
46
|
-
fastlib/openapi/offline.py
|
|
47
|
-
fastlib/router/__init__.py
|
|
48
|
-
fastlib/router/base.py
|
|
49
|
-
fastlib/schema/__init__.py
|
|
50
|
-
fastlib/schema/base.py
|
|
51
|
-
fastlib/schema/response.py
|
|
52
48
|
fastlib/security/__init__.py
|
|
53
49
|
fastlib/security/security.py
|
|
54
50
|
fastlib/security/utils.py
|