fastlib-py 0.3.4__tar.gz → 0.3.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.
Files changed (78) hide show
  1. {fastlib_py-0.3.4 → fastlib_py-0.3.5}/PKG-INFO +2 -3
  2. {fastlib_py-0.3.4 → fastlib_py-0.3.5}/fastlib/_logging/config.py +2 -2
  3. {fastlib_py-0.3.4 → fastlib_py-0.3.5}/fastlib/_logging/handlers.py +3 -4
  4. {fastlib_py-0.3.4 → fastlib_py-0.3.5}/fastlib/cache/_disk_cache.py +6 -6
  5. {fastlib_py-0.3.4 → fastlib_py-0.3.5}/fastlib/cache/_redis_cache.py +5 -5
  6. {fastlib_py-0.3.4 → fastlib_py-0.3.5}/fastlib/cache/base.py +7 -7
  7. {fastlib_py-0.3.4 → fastlib_py-0.3.5}/fastlib/config/loader.py +3 -3
  8. {fastlib_py-0.3.4 → fastlib_py-0.3.5}/fastlib/config/manager.py +7 -7
  9. {fastlib_py-0.3.4 → fastlib_py-0.3.5}/fastlib/config/registry.py +3 -3
  10. {fastlib_py-0.3.4 → fastlib_py-0.3.5}/fastlib/config/utils.py +3 -3
  11. {fastlib_py-0.3.4 → fastlib_py-0.3.5}/fastlib/contextvars.py +2 -2
  12. {fastlib_py-0.3.4 → fastlib_py-0.3.5}/fastlib/exception/base.py +5 -5
  13. {fastlib_py-0.3.4 → fastlib_py-0.3.5}/fastlib/exception/exception_handler.py +2 -2
  14. {fastlib_py-0.3.4 → fastlib_py-0.3.5}/fastlib/i18n/manager.py +2 -2
  15. {fastlib_py-0.3.4 → fastlib_py-0.3.5}/fastlib/i18n/messages.py +2 -6
  16. {fastlib_py-0.3.4 → fastlib_py-0.3.5}/fastlib/i18n/types.py +0 -20
  17. {fastlib_py-0.3.4 → fastlib_py-0.3.5}/fastlib/i18n/utils.py +3 -5
  18. {fastlib_py-0.3.4 → fastlib_py-0.3.5}/fastlib/logging.py +2 -1
  19. {fastlib_py-0.3.4 → fastlib_py-0.3.5}/fastlib/mapper/base_mapper.py +15 -15
  20. {fastlib_py-0.3.4 → fastlib_py-0.3.5}/fastlib/mapper/impl/base_mapper_impl.py +46 -48
  21. {fastlib_py-0.3.4 → fastlib_py-0.3.5}/fastlib/middleware/db_session.py +4 -5
  22. {fastlib_py-0.3.4 → fastlib_py-0.3.5}/fastlib/migrate.py +3 -4
  23. {fastlib_py-0.3.4 → fastlib_py-0.3.5}/fastlib/request.py +1 -3
  24. {fastlib_py-0.3.4 → fastlib_py-0.3.5}/fastlib/response.py +6 -6
  25. {fastlib_py-0.3.4 → fastlib_py-0.3.5}/fastlib/security/security.py +5 -4
  26. {fastlib_py-0.3.4 → fastlib_py-0.3.5}/fastlib/security/utils.py +17 -22
  27. {fastlib_py-0.3.4 → fastlib_py-0.3.5}/fastlib/service/base_service.py +35 -34
  28. {fastlib_py-0.3.4 → fastlib_py-0.3.5}/fastlib/service/impl/base_service_impl.py +38 -36
  29. {fastlib_py-0.3.4 → fastlib_py-0.3.5}/fastlib/stream/event.py +9 -9
  30. {fastlib_py-0.3.4 → fastlib_py-0.3.5}/fastlib/stream/handler.py +3 -5
  31. {fastlib_py-0.3.4 → fastlib_py-0.3.5}/fastlib/stream/schema.py +5 -32
  32. {fastlib_py-0.3.4 → fastlib_py-0.3.5}/fastlib/stream/sse.py +27 -25
  33. {fastlib_py-0.3.4 → fastlib_py-0.3.5}/fastlib/utils/excel_util.py +3 -4
  34. {fastlib_py-0.3.4 → fastlib_py-0.3.5}/fastlib/utils/file_util.py +5 -9
  35. {fastlib_py-0.3.4 → fastlib_py-0.3.5}/fastlib/utils/http_util.py +8 -8
  36. {fastlib_py-0.3.4 → fastlib_py-0.3.5}/fastlib/utils/snowflake_util.py +1 -2
  37. {fastlib_py-0.3.4 → fastlib_py-0.3.5}/fastlib/utils/validate_util.py +7 -5
  38. {fastlib_py-0.3.4 → fastlib_py-0.3.5}/fastlib_py.egg-info/PKG-INFO +2 -3
  39. {fastlib_py-0.3.4 → fastlib_py-0.3.5}/pyproject.toml +126 -127
  40. {fastlib_py-0.3.4 → fastlib_py-0.3.5}/LICENSE +0 -0
  41. {fastlib_py-0.3.4 → fastlib_py-0.3.5}/README.md +0 -0
  42. {fastlib_py-0.3.4 → fastlib_py-0.3.5}/fastlib/__init__.py +0 -0
  43. {fastlib_py-0.3.4 → fastlib_py-0.3.5}/fastlib/_logging/__init__.py +0 -0
  44. {fastlib_py-0.3.4 → fastlib_py-0.3.5}/fastlib/cache/__init__.py +0 -0
  45. {fastlib_py-0.3.4 → fastlib_py-0.3.5}/fastlib/cache/manager.py +0 -0
  46. {fastlib_py-0.3.4 → fastlib_py-0.3.5}/fastlib/config/__init__.py +0 -0
  47. {fastlib_py-0.3.4 → fastlib_py-0.3.5}/fastlib/config/_database_config.py +0 -0
  48. {fastlib_py-0.3.4 → fastlib_py-0.3.5}/fastlib/config/_security_config.py +0 -0
  49. {fastlib_py-0.3.4 → fastlib_py-0.3.5}/fastlib/config/_server_config.py +0 -0
  50. {fastlib_py-0.3.4 → fastlib_py-0.3.5}/fastlib/config/base.py +0 -0
  51. {fastlib_py-0.3.4 → fastlib_py-0.3.5}/fastlib/constants.py +0 -0
  52. {fastlib_py-0.3.4 → fastlib_py-0.3.5}/fastlib/db_engine.py +0 -0
  53. {fastlib_py-0.3.4 → fastlib_py-0.3.5}/fastlib/enums.py +0 -0
  54. {fastlib_py-0.3.4 → fastlib_py-0.3.5}/fastlib/exception/__init__.py +0 -0
  55. {fastlib_py-0.3.4 → fastlib_py-0.3.5}/fastlib/exception/exception_manager.py +0 -0
  56. {fastlib_py-0.3.4 → fastlib_py-0.3.5}/fastlib/i18n/__init__.py +0 -0
  57. {fastlib_py-0.3.4 → fastlib_py-0.3.5}/fastlib/mapper/__init__.py +0 -0
  58. {fastlib_py-0.3.4 → fastlib_py-0.3.5}/fastlib/mapper/impl/__init__.py +0 -0
  59. {fastlib_py-0.3.4 → fastlib_py-0.3.5}/fastlib/middleware/__init__.py +0 -0
  60. {fastlib_py-0.3.4 → fastlib_py-0.3.5}/fastlib/middleware/i18n.py +0 -0
  61. {fastlib_py-0.3.4 → fastlib_py-0.3.5}/fastlib/middleware/jwt.py +0 -0
  62. {fastlib_py-0.3.4 → fastlib_py-0.3.5}/fastlib/openapi.py +0 -0
  63. {fastlib_py-0.3.4 → fastlib_py-0.3.5}/fastlib/py.typed +0 -0
  64. {fastlib_py-0.3.4 → fastlib_py-0.3.5}/fastlib/router.py +0 -0
  65. {fastlib_py-0.3.4 → fastlib_py-0.3.5}/fastlib/schema.py +0 -0
  66. {fastlib_py-0.3.4 → fastlib_py-0.3.5}/fastlib/security/__init__.py +0 -0
  67. {fastlib_py-0.3.4 → fastlib_py-0.3.5}/fastlib/service/__init__.py +0 -0
  68. {fastlib_py-0.3.4 → fastlib_py-0.3.5}/fastlib/service/impl/__init__.py +0 -0
  69. {fastlib_py-0.3.4 → fastlib_py-0.3.5}/fastlib/stream/__init__.py +0 -0
  70. {fastlib_py-0.3.4 → fastlib_py-0.3.5}/fastlib/stream/enums.py +0 -0
  71. {fastlib_py-0.3.4 → fastlib_py-0.3.5}/fastlib/utils/__init__.py +0 -0
  72. {fastlib_py-0.3.4 → fastlib_py-0.3.5}/fastlib/utils/ip_util.py +0 -0
  73. {fastlib_py-0.3.4 → fastlib_py-0.3.5}/fastlib/utils/str_util.py +0 -0
  74. {fastlib_py-0.3.4 → fastlib_py-0.3.5}/fastlib_py.egg-info/SOURCES.txt +0 -0
  75. {fastlib_py-0.3.4 → fastlib_py-0.3.5}/fastlib_py.egg-info/dependency_links.txt +0 -0
  76. {fastlib_py-0.3.4 → fastlib_py-0.3.5}/fastlib_py.egg-info/requires.txt +0 -0
  77. {fastlib_py-0.3.4 → fastlib_py-0.3.5}/fastlib_py.egg-info/top_level.txt +0 -0
  78. {fastlib_py-0.3.4 → fastlib_py-0.3.5}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fastlib-py
3
- Version: 0.3.4
3
+ Version: 0.3.5
4
4
  Summary: Fastlib, high performance, easy to use, fast to code, ready for production
5
5
  Author-email: tyvekZhang <tyvekzhang@gmail.com>
6
6
  Maintainer-email: tyvekZhang <tyvekzhang@gmail.com>
@@ -10,14 +10,13 @@ Keywords: fastapi,library,sqlmodel,web
10
10
  Classifier: Development Status :: 4 - Beta
11
11
  Classifier: Programming Language :: Python
12
12
  Classifier: Programming Language :: Python :: 3 :: Only
13
- Classifier: Programming Language :: Python :: 3.9
14
13
  Classifier: Programming Language :: Python :: 3.10
15
14
  Classifier: Programming Language :: Python :: 3.11
16
15
  Classifier: Programming Language :: Python :: 3.12
17
16
  Classifier: Programming Language :: Python :: 3.13
18
17
  Classifier: Programming Language :: Python :: Implementation :: CPython
19
18
  Classifier: Programming Language :: Python :: Implementation :: PyPy
20
- Requires-Python: >=3.9
19
+ Requires-Python: >=3.10
21
20
  Description-Content-Type: text/markdown
22
21
  License-File: LICENSE
23
22
  Requires-Dist: aiosqlite>=0.21
@@ -4,7 +4,7 @@ Log configuration and logging utility for the application.
4
4
  """
5
5
 
6
6
  from pathlib import Path
7
- from typing import Literal, Optional
7
+ from typing import Literal
8
8
 
9
9
  from fastlib.config.base import BaseConfig
10
10
  from fastlib.config.manager import config_class
@@ -29,7 +29,7 @@ class LogConfig(BaseConfig):
29
29
  error_log_rotation: str = "1 day",
30
30
  error_log_retention: str = "90 days",
31
31
  enable_async: bool = True,
32
- max_file_size: Optional[str] = "10 MB",
32
+ max_file_size: str | None = "10 MB",
33
33
  time_format: str = "YYYY-MM-DD",
34
34
  **kwargs,
35
35
  ):
@@ -5,12 +5,11 @@ A comprehensive logging tool for the application.
5
5
 
6
6
  import sys
7
7
  from pathlib import Path
8
- from typing import Optional
9
8
 
10
9
  from loguru import logger
11
10
 
12
- from fastlib.config.manager import ConfigManager
13
11
  from fastlib._logging.config import LogConfig
12
+ from fastlib.config.manager import ConfigManager
14
13
 
15
14
 
16
15
  class Logger:
@@ -19,7 +18,7 @@ class Logger:
19
18
  """
20
19
 
21
20
  _instances: dict[str, "Logger"] = {}
22
- _config: Optional[LogConfig] = None
21
+ _config: LogConfig | None = None
23
22
  _is_configured: bool = False
24
23
 
25
24
  @classmethod
@@ -49,7 +48,7 @@ class Logger:
49
48
  @classmethod
50
49
  def get_instance(
51
50
  cls,
52
- name: Optional[str] = None,
51
+ name: str | None = None,
53
52
  ) -> "Logger":
54
53
  """
55
54
  Get or create a named logger instance.
@@ -5,7 +5,7 @@ import json
5
5
  import threading
6
6
  import time
7
7
  from contextlib import asynccontextmanager
8
- from typing import Any, Optional
8
+ from typing import Any
9
9
 
10
10
  import diskcache
11
11
 
@@ -28,7 +28,7 @@ class PageCache(Cache):
28
28
  self,
29
29
  key: str,
30
30
  value: Any,
31
- ex: Optional[int] = None,
31
+ ex: int | None = None,
32
32
  nx: bool = False, # only set if not exists
33
33
  xx: bool = False, # only set if exists
34
34
  ) -> bool:
@@ -38,7 +38,7 @@ class PageCache(Cache):
38
38
  return False
39
39
  return self.cache.set(key, value, expire=ex)
40
40
 
41
- async def get(self, key: str) -> Optional[Any]:
41
+ async def get(self, key: str) -> Any | None:
42
42
  return self.cache.get(key, None)
43
43
 
44
44
  async def delete(self, *keys: str) -> int:
@@ -86,7 +86,7 @@ class PageCache(Cache):
86
86
  self.cache.set(name, data)
87
87
  return 1
88
88
 
89
- async def hget(self, name: str, key: str) -> Optional[Any]:
89
+ async def hget(self, name: str, key: str) -> Any | None:
90
90
  data = self.cache.get(name, {})
91
91
  return data.get(key) if isinstance(data, dict) else None
92
92
 
@@ -136,7 +136,7 @@ class PageCache(Cache):
136
136
  self._set_list(name, lst)
137
137
  return len(lst)
138
138
 
139
- async def lpop(self, name: str) -> Optional[Any]:
139
+ async def lpop(self, name: str) -> Any | None:
140
140
  lst = self._get_list(name)
141
141
  if not lst:
142
142
  return None
@@ -144,7 +144,7 @@ class PageCache(Cache):
144
144
  self._set_list(name, lst)
145
145
  return val
146
146
 
147
- async def rpop(self, name: str) -> Optional[Any]:
147
+ async def rpop(self, name: str) -> Any | None:
148
148
  lst = self._get_list(name)
149
149
  if not lst:
150
150
  return None
@@ -47,7 +47,7 @@ class RedisCache(Cache):
47
47
  self,
48
48
  key: str,
49
49
  value: Any,
50
- ex: Optional[int] = None,
50
+ ex: int | None = None,
51
51
  nx: bool = False,
52
52
  xx: bool = False,
53
53
  ) -> bool:
@@ -65,7 +65,7 @@ class RedisCache(Cache):
65
65
  except RedisError as e:
66
66
  raise CacheError(f"Failed to set key {key}", e) from e
67
67
 
68
- async def get(self, key: str) -> Optional[Any]:
68
+ async def get(self, key: str) -> Any | None:
69
69
  """Get a value from cache."""
70
70
  try:
71
71
  return await self.redis_client.get(key)
@@ -127,7 +127,7 @@ class RedisCache(Cache):
127
127
  except RedisError as e:
128
128
  raise CacheError(f"Failed to set hash field {key} in {name}", e) from e
129
129
 
130
- async def hget(self, name: str, key: str) -> Optional[Any]:
130
+ async def hget(self, name: str, key: str) -> Any | None:
131
131
  """Get a field from a hash."""
132
132
  try:
133
133
  return await self.redis_client.hget(name, key)
@@ -164,14 +164,14 @@ class RedisCache(Cache):
164
164
  except RedisError as e:
165
165
  raise CacheError(f"Failed to rpush values to list {name}", e) from e
166
166
 
167
- async def lpop(self, name: str) -> Optional[Any]:
167
+ async def lpop(self, name: str) -> Any | None:
168
168
  """Pop a value from the left of a list."""
169
169
  try:
170
170
  return await self.redis_client.lpop(name)
171
171
  except RedisError as e:
172
172
  raise CacheError(f"Failed to lpop from list {name}", e) from e
173
173
 
174
- async def rpop(self, name: str) -> Optional[Any]:
174
+ async def rpop(self, name: str) -> Any | None:
175
175
  """Pop a value from the right of a list."""
176
176
  try:
177
177
  return await self.redis_client.rpop(name)
@@ -7,13 +7,13 @@ for different caching implementations like Redis, memory cache, etc.
7
7
 
8
8
  from abc import ABC, abstractmethod
9
9
  from contextlib import asynccontextmanager
10
- from typing import Any, Optional
10
+ from typing import Any
11
11
 
12
12
 
13
13
  class CacheError(Exception):
14
14
  """Custom exception for cache-related errors."""
15
15
 
16
- def __init__(self, message: str, original_error: Optional[Exception] = None):
16
+ def __init__(self, message: str, original_error: Exception | None = None):
17
17
  self.message = message
18
18
  self.original_error = original_error
19
19
  super().__init__(f"Cache Error: {message}")
@@ -37,7 +37,7 @@ class Cache(ABC):
37
37
  self,
38
38
  key: str,
39
39
  value: Any,
40
- ex: Optional[int] = None,
40
+ ex: int | None = None,
41
41
  nx: bool = False,
42
42
  xx: bool = False,
43
43
  ) -> bool:
@@ -45,7 +45,7 @@ class Cache(ABC):
45
45
  pass
46
46
 
47
47
  @abstractmethod
48
- async def get(self, key: str) -> Optional[Any]:
48
+ async def get(self, key: str) -> Any | None:
49
49
  """Get a value from cache."""
50
50
  pass
51
51
 
@@ -85,7 +85,7 @@ class Cache(ABC):
85
85
  pass
86
86
 
87
87
  @abstractmethod
88
- async def hget(self, name: str, key: str) -> Optional[Any]:
88
+ async def hget(self, name: str, key: str) -> Any | None:
89
89
  """Get a field from a hash."""
90
90
  pass
91
91
 
@@ -110,12 +110,12 @@ class Cache(ABC):
110
110
  pass
111
111
 
112
112
  @abstractmethod
113
- async def lpop(self, name: str) -> Optional[Any]:
113
+ async def lpop(self, name: str) -> Any | None:
114
114
  """Pop a value from the left of a list."""
115
115
  pass
116
116
 
117
117
  @abstractmethod
118
- async def rpop(self, name: str) -> Optional[Any]:
118
+ async def rpop(self, name: str) -> Any | None:
119
119
  """Pop a value from the right of a list."""
120
120
  pass
121
121
 
@@ -2,7 +2,7 @@
2
2
  """ConfigLoader class for loading and managing application configurations from YAML files."""
3
3
 
4
4
  import os
5
- from typing import Any, Optional
5
+ from typing import Any
6
6
 
7
7
  import yaml
8
8
  from loguru import logger
@@ -12,7 +12,7 @@ from fastlib.config import utils as config_util
12
12
 
13
13
 
14
14
  class ConfigLoader:
15
- def __init__(self, env: str, base_config_file: Optional[str] = None) -> None:
15
+ def __init__(self, env: str, base_config_file: str | None = None) -> None:
16
16
  """
17
17
  Initializes a new instance of the ConfigLoader class
18
18
 
@@ -59,7 +59,7 @@ class ConfigLoader:
59
59
  except yaml.YAMLError as e:
60
60
  raise yaml.YAMLError(f"Error parsing YAML file {file_path}: {e}") from e
61
61
 
62
- def load_config(self, environment: Optional[str] = None) -> dict[str, Any]:
62
+ def load_config(self, environment: str | None = None) -> dict[str, Any]:
63
63
  """
64
64
  Load the base configuration and merge with environment-specific settings.
65
65
  """
@@ -2,7 +2,7 @@
2
2
  """Configuration loading and management with dynamic registry support."""
3
3
 
4
4
  import os
5
- from typing import Any, Optional
5
+ from typing import Any
6
6
 
7
7
  from fastlib import constants as constant
8
8
  from fastlib.config import utils as config_util
@@ -38,7 +38,7 @@ def config_class(name: str):
38
38
  class ConfigManager:
39
39
  """Global configuration manager with static methods and dynamic registry support."""
40
40
 
41
- _global_config_dict: Optional[dict[str, Any]] = None
41
+ _global_config_dict: dict[str, Any] | None = None
42
42
  _config_instances: dict[str, BaseConfig] = {}
43
43
  _initialized: bool = False
44
44
 
@@ -63,9 +63,9 @@ class ConfigManager:
63
63
 
64
64
  @staticmethod
65
65
  def initialize_global_config(
66
- env: Optional[str] = None,
67
- config_file: Optional[str] = None,
68
- custom_configs: Optional[dict[str, Any]] = None,
66
+ env: str | None = None,
67
+ config_file: str | None = None,
68
+ custom_configs: dict[str, Any] | None = None,
69
69
  ) -> None:
70
70
  """
71
71
  Initialize global configuration.
@@ -136,7 +136,7 @@ class ConfigManager:
136
136
  ) from e
137
137
 
138
138
  @staticmethod
139
- def get_config_instance(config_name: str) -> Optional[BaseConfig]:
139
+ def get_config_instance(config_name: str) -> BaseConfig | None:
140
140
  """
141
141
  Get a specific configuration instance.
142
142
 
@@ -205,7 +205,7 @@ class ConfigManager:
205
205
  return ConfigManager._initialized
206
206
 
207
207
  @staticmethod
208
- def get_config_dict() -> Optional[dict[str, Any]]:
208
+ def get_config_dict() -> dict[str, Any] | None:
209
209
  """
210
210
  Get the raw configuration dictionary.
211
211
 
@@ -2,7 +2,7 @@
2
2
  """Configuration registry for dynamic configuration class management."""
3
3
 
4
4
  # Import BaseConfig from config module to avoid circular imports
5
- from typing import Any, Optional
5
+ from typing import Any
6
6
 
7
7
 
8
8
  class ConfigRegistry:
@@ -36,7 +36,7 @@ class ConfigRegistry:
36
36
  cls._registry[name] = config_class
37
37
 
38
38
  @classmethod
39
- def get_config_class(cls, name: str) -> Optional[type]:
39
+ def get_config_class(cls, name: str) -> type | None:
40
40
  """
41
41
  Get a registered configuration class.
42
42
 
@@ -49,7 +49,7 @@ class ConfigRegistry:
49
49
  return cls._registry.get(name)
50
50
 
51
51
  @classmethod
52
- def create_instance(cls, name: str, config_dict: dict[str, Any]) -> Optional[Any]:
52
+ def create_instance(cls, name: str, config_dict: dict[str, Any]) -> Any | None:
53
53
  """
54
54
  Create an instance of a registered configuration class.
55
55
 
@@ -3,7 +3,7 @@
3
3
 
4
4
  import configparser
5
5
  from pathlib import Path
6
- from typing import Any, NamedTuple, Optional
6
+ from typing import Any, NamedTuple
7
7
  from urllib.parse import urlparse
8
8
 
9
9
  from loguru import logger
@@ -36,8 +36,8 @@ class ProjectInfo:
36
36
  self,
37
37
  name: str,
38
38
  version: str,
39
- description: Optional[str] = None,
40
- authors: Optional[list[str]] = None,
39
+ description: str | None = None,
40
+ authors: list[str] | None = None,
41
41
  ):
42
42
  self.name = name
43
43
  self.version = version
@@ -6,12 +6,12 @@ the current authenticated user's ID throughout the request lifecycle.
6
6
  """
7
7
 
8
8
  from contextvars import ContextVar
9
- from typing import Any, Optional
9
+ from typing import Any
10
10
 
11
11
  from loguru import logger
12
12
 
13
13
  # Type aliases for better readability
14
- UserID = Optional[int]
14
+ UserID = int | None
15
15
 
16
16
  # Context variable declaration
17
17
  _current_user_id: ContextVar[UserID] = ContextVar("current_user_id", default=None)
@@ -2,7 +2,7 @@
2
2
  """Base exception class for the application."""
3
3
 
4
4
  from http import HTTPStatus
5
- from typing import Any, Optional
5
+ from typing import Any
6
6
 
7
7
  from pydantic import BaseModel
8
8
 
@@ -27,8 +27,8 @@ class BaseException(Exception):
27
27
  def __init__(
28
28
  self,
29
29
  code: ErrorDetail,
30
- message: Optional[str] = None,
31
- details: Optional[Any] = None,
30
+ message: str | None = None,
31
+ details: Any | None = None,
32
32
  ):
33
33
  """
34
34
  Initialize the HTTPException.
@@ -58,5 +58,5 @@ class SystemErrorCode:
58
58
 
59
59
  class SystemException(BaseException):
60
60
  code: SystemErrorCode
61
- message: Optional[str] = None
62
- details: Optional[Any] = None
61
+ message: str | None = None
62
+ details: Any | None = None
@@ -4,7 +4,7 @@
4
4
  import textwrap
5
5
  import traceback
6
6
  from http import HTTPStatus
7
- from typing import Any, Optional
7
+ from typing import Any
8
8
 
9
9
  from fastapi import Request
10
10
  from fastapi.exception_handlers import http_exception_handler
@@ -95,7 +95,7 @@ def build_error_response(
95
95
  exc: Exception,
96
96
  request: Request,
97
97
  status_code: int,
98
- headers: Optional[dict[str, str]] = None,
98
+ headers: dict[str, str] | None = None,
99
99
  ) -> Response:
100
100
  """
101
101
  Build standardized error response.
@@ -5,8 +5,8 @@ Internationalization context manager
5
5
 
6
6
  import contextvars
7
7
  import functools
8
- from collections.abc import Awaitable
9
- from typing import Any, Callable, TypeVar
8
+ from collections.abc import Awaitable, Callable
9
+ from typing import Any, TypeVar
10
10
 
11
11
  from fastlib.i18n.types import Language
12
12
 
@@ -3,7 +3,6 @@
3
3
 
4
4
  import json
5
5
  from pathlib import Path
6
- from typing import Optional, Union
7
6
 
8
7
  from fastlib.constants import RESOURCE_DIR
9
8
  from fastlib.i18n.types import Language
@@ -17,7 +16,7 @@ TRANSLATIONS = {
17
16
  }
18
17
 
19
18
 
20
- def load_translations(base_dirs: Union[Path, list[Path], None] = None):
19
+ def load_translations(base_dirs: Path | list[Path] | None = None):
21
20
  """Load translation files from specified directories.
22
21
 
23
22
  Args:
@@ -61,9 +60,7 @@ def load_translations(base_dirs: Union[Path, list[Path], None] = None):
61
60
  TRANSLATIONS[lang.value][namespace] = translations_data
62
61
 
63
62
 
64
- def get_message(
65
- message_type: str, key: str, language: Optional[Language] = None
66
- ) -> str:
63
+ def get_message(message_type: str, key: str, language: Language | None = None) -> str:
67
64
  """Get translated message for given type, key and language.
68
65
 
69
66
  Args:
@@ -80,7 +77,6 @@ def get_message(
80
77
  # Try to get message from requested language
81
78
  lang_dict = TRANSLATIONS.get(language.value, {})
82
79
  msg = lang_dict.get(message_type, {}).get(key)
83
- print(f"lang_dict: {lang_dict}")
84
80
  if msg:
85
81
  return msg
86
82
 
@@ -84,23 +84,3 @@ class Language(Enum):
84
84
  def is_supported(cls, code: str) -> bool:
85
85
  """Check if language code is supported"""
86
86
  return code in cls.supported_codes()
87
-
88
-
89
- # if __name__ == "__main__":
90
- # # Register new languages dynamically
91
- # Language.register("es", "Spanish", "Español")
92
- # Language.register("ja", "Japanese", "日本語")
93
- # Language.register("ar", "Arabic", "العربية", "rtl")
94
-
95
- # # Access new languages
96
- # spanish = Language.ES
97
- # print(f"Spanish code: {spanish.value}") # es
98
- # print(f"Spanish native: {spanish.native_name}") # Español
99
-
100
- # # Check support
101
- # print(Language.is_supported("fr")) # False
102
- # print(Language.is_supported("ja")) # True
103
-
104
- # # Get from code
105
- # japanese = Language.from_code("ja")
106
- # print(japanese.display_name) # Japanese
@@ -3,8 +3,6 @@
3
3
  Internationalization utilities
4
4
  """
5
5
 
6
- from typing import Optional
7
-
8
6
  from .manager import I18nContext
9
7
  from .messages import get_message
10
8
  from .types import Language
@@ -21,12 +19,12 @@ LANGUAGE_MAPPING = {
21
19
  }
22
20
 
23
21
 
24
- def _resolve_language(language: Optional[Language]) -> Language:
22
+ def _resolve_language(language: Language | None) -> Language:
25
23
  """Return given language or current context default"""
26
24
  return language or I18nContext.get_language()
27
25
 
28
26
 
29
- def parse_language(language_str: Optional[str]) -> Language:
27
+ def parse_language(language_str: str | None) -> Language:
30
28
  """Parse string like 'zh-CN', 'en-US' to Language enum"""
31
29
  if not language_str:
32
30
  return DEFAULT_LANGUAGE
@@ -36,7 +34,7 @@ def parse_language(language_str: Optional[str]) -> Language:
36
34
 
37
35
 
38
36
  def get_localized_message(
39
- category: str, key: str, language: Optional[Language] = None
37
+ category: str, key: str, language: Language | None = None
40
38
  ) -> str:
41
39
  """Get localized message by category ('error', 'success', 'business')"""
42
40
  lang = _resolve_language(language)
@@ -2,6 +2,7 @@
2
2
  """
3
3
  Logging module
4
4
  """
5
+
5
6
  from ._logging.handlers import Logger
6
7
 
7
- logger = Logger.initialize()
8
+ logger = Logger.initialize()
@@ -3,7 +3,7 @@
3
3
 
4
4
  from abc import ABC, abstractmethod
5
5
  from collections.abc import Sequence
6
- from typing import Any, Generic, Optional, TypeVar
6
+ from typing import Any, Generic, TypeVar
7
7
 
8
8
  from pydantic import BaseModel
9
9
  from sqlmodel import SQLModel
@@ -19,7 +19,7 @@ IDType = TypeVar("IDType", int, str)
19
19
  class BaseMapper(ABC, Generic[ModelType]):
20
20
  @abstractmethod
21
21
  async def insert(
22
- self, *, data: ModelType, db_session: Optional[AsyncSession] = None
22
+ self, *, data: ModelType, db_session: AsyncSession | None = None
23
23
  ) -> ModelType:
24
24
  """Insert a single data into the database.
25
25
 
@@ -37,7 +37,7 @@ class BaseMapper(ABC, Generic[ModelType]):
37
37
  self,
38
38
  *,
39
39
  data_list: list[ModelType],
40
- db_session: Optional[AsyncSession] = None,
40
+ db_session: AsyncSession | None = None,
41
41
  ) -> int:
42
42
  """Insert data list into the database in a single operation.
43
43
 
@@ -52,8 +52,8 @@ class BaseMapper(ABC, Generic[ModelType]):
52
52
 
53
53
  @abstractmethod
54
54
  async def select_by_id(
55
- self, *, id: IDType, db_session: Optional[AsyncSession] = None
56
- ) -> Optional[ModelType]:
55
+ self, *, id: IDType, db_session: AsyncSession | None = None
56
+ ) -> ModelType | None:
57
57
  """Select a single record by its ID.
58
58
 
59
59
  Args:
@@ -67,7 +67,7 @@ class BaseMapper(ABC, Generic[ModelType]):
67
67
 
68
68
  @abstractmethod
69
69
  async def select_by_ids(
70
- self, *, ids: list[IDType], db_session: Optional[AsyncSession] = None
70
+ self, *, ids: list[IDType], db_session: AsyncSession | None = None
71
71
  ) -> list[ModelType]:
72
72
  """Select record list by their IDs.
73
73
 
@@ -86,7 +86,7 @@ class BaseMapper(ABC, Generic[ModelType]):
86
86
  *,
87
87
  current: IDType,
88
88
  page_size: int,
89
- db_session: Optional[AsyncSession] = None,
89
+ db_session: AsyncSession | None = None,
90
90
  **kwargs,
91
91
  ) -> tuple[list[ModelType], int]:
92
92
  """Select record list with pagination.
@@ -109,7 +109,7 @@ class BaseMapper(ABC, Generic[ModelType]):
109
109
  current: IDType,
110
110
  page_size: int,
111
111
  sort: list[SortItem] = None,
112
- db_session: Optional[AsyncSession] = None,
112
+ db_session: AsyncSession | None = None,
113
113
  **kwargs,
114
114
  ) -> tuple[list[ModelType], int]:
115
115
  """Select record list with pagination and sorting.
@@ -133,7 +133,7 @@ class BaseMapper(ABC, Generic[ModelType]):
133
133
  current: IDType,
134
134
  page_size: int,
135
135
  sort: list[SortItem] = None,
136
- db_session: Optional[AsyncSession] = None,
136
+ db_session: AsyncSession | None = None,
137
137
  **kwargs,
138
138
  ) -> tuple[list[ModelType], int]:
139
139
  """Select record list with pagination and sorting by parent ID.
@@ -152,7 +152,7 @@ class BaseMapper(ABC, Generic[ModelType]):
152
152
 
153
153
  @abstractmethod
154
154
  async def update_by_id(
155
- self, *, data: ModelType, db_session: Optional[AsyncSession] = None
155
+ self, *, data: ModelType, db_session: AsyncSession | None = None
156
156
  ) -> int:
157
157
  """Update a record by its ID.
158
158
 
@@ -170,7 +170,7 @@ class BaseMapper(ABC, Generic[ModelType]):
170
170
  self,
171
171
  *,
172
172
  data: Sequence[dict[str, Any]],
173
- db_session: Optional[AsyncSession] = None,
173
+ db_session: AsyncSession | None = None,
174
174
  ) -> int:
175
175
  """
176
176
  Update multiple records.
@@ -190,7 +190,7 @@ class BaseMapper(ABC, Generic[ModelType]):
190
190
  *,
191
191
  ids: list[IDType],
192
192
  data: dict[str, Any],
193
- db_session: Optional[AsyncSession] = None,
193
+ db_session: AsyncSession | None = None,
194
194
  ) -> int:
195
195
  """Update record list by their IDs with the same values.
196
196
 
@@ -206,7 +206,7 @@ class BaseMapper(ABC, Generic[ModelType]):
206
206
 
207
207
  @abstractmethod
208
208
  async def delete_by_id(
209
- self, *, id: IDType, db_session: Optional[AsyncSession] = None
209
+ self, *, id: IDType, db_session: AsyncSession | None = None
210
210
  ) -> int:
211
211
  """Delete a data by its ID.
212
212
 
@@ -221,7 +221,7 @@ class BaseMapper(ABC, Generic[ModelType]):
221
221
 
222
222
  @abstractmethod
223
223
  async def batch_delete_by_ids(
224
- self, *, ids: list[IDType], db_session: Optional[AsyncSession] = None
224
+ self, *, ids: list[IDType], db_session: AsyncSession | None = None
225
225
  ) -> int:
226
226
  """Delete multiple data_list by their IDs.
227
227
 
@@ -242,7 +242,7 @@ class BaseMapper(ABC, Generic[ModelType]):
242
242
  schema_class: SchemaType,
243
243
  level: int = 1,
244
244
  max_level: int = 5,
245
- db_session: Optional[AsyncSession] = None,
245
+ db_session: AsyncSession | None = None,
246
246
  ) -> list[SchemaType]:
247
247
  """
248
248
  Recursively fetch children of given parent items up to 5 levels.