fastlib-py 0.2.3__tar.gz → 0.2.4__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 (77) hide show
  1. {fastlib_py-0.2.3 → fastlib_py-0.2.4}/PKG-INFO +1 -1
  2. {fastlib_py-0.2.3 → fastlib_py-0.2.4}/fastlib/cache/__init__.py +1 -1
  3. {fastlib_py-0.2.3 → fastlib_py-0.2.4}/fastlib/enums/__init__.py +0 -2
  4. {fastlib_py-0.2.3 → fastlib_py-0.2.4}/fastlib/middleware/__init__.py +1 -2
  5. {fastlib_py-0.2.3 → fastlib_py-0.2.4}/fastlib_py.egg-info/PKG-INFO +1 -1
  6. {fastlib_py-0.2.3 → fastlib_py-0.2.4}/fastlib_py.egg-info/SOURCES.txt +0 -2
  7. {fastlib_py-0.2.3 → fastlib_py-0.2.4}/pyproject.toml +1 -1
  8. fastlib_py-0.2.3/fastlib/decorator/base.py +0 -237
  9. fastlib_py-0.2.3/fastlib/service/impl/__init__.py +0 -0
  10. {fastlib_py-0.2.3 → fastlib_py-0.2.4}/LICENSE +0 -0
  11. {fastlib_py-0.2.3 → fastlib_py-0.2.4}/README.md +0 -0
  12. {fastlib_py-0.2.3 → fastlib_py-0.2.4}/fastlib/__init__.py +0 -0
  13. {fastlib_py-0.2.3 → fastlib_py-0.2.4}/fastlib/cache/base.py +0 -0
  14. {fastlib_py-0.2.3 → fastlib_py-0.2.4}/fastlib/cache/disk_cache.py +0 -0
  15. {fastlib_py-0.2.3 → fastlib_py-0.2.4}/fastlib/cache/manager.py +0 -0
  16. {fastlib_py-0.2.3 → fastlib_py-0.2.4}/fastlib/cache/redis_cache.py +0 -0
  17. {fastlib_py-0.2.3 → fastlib_py-0.2.4}/fastlib/config/__init__.py +0 -0
  18. {fastlib_py-0.2.3 → fastlib_py-0.2.4}/fastlib/config/base.py +0 -0
  19. {fastlib_py-0.2.3 → fastlib_py-0.2.4}/fastlib/config/database_config.py +0 -0
  20. {fastlib_py-0.2.3 → fastlib_py-0.2.4}/fastlib/config/loader.py +0 -0
  21. {fastlib_py-0.2.3 → fastlib_py-0.2.4}/fastlib/config/manager.py +0 -0
  22. {fastlib_py-0.2.3 → fastlib_py-0.2.4}/fastlib/config/registry.py +0 -0
  23. {fastlib_py-0.2.3 → fastlib_py-0.2.4}/fastlib/config/security_config.py +0 -0
  24. {fastlib_py-0.2.3 → fastlib_py-0.2.4}/fastlib/config/server_config.py +0 -0
  25. {fastlib_py-0.2.3 → fastlib_py-0.2.4}/fastlib/config/utils.py +0 -0
  26. {fastlib_py-0.2.3 → fastlib_py-0.2.4}/fastlib/constant/__init__.py +0 -0
  27. {fastlib_py-0.2.3 → fastlib_py-0.2.4}/fastlib/constant/constant.py +0 -0
  28. {fastlib_py-0.2.3 → fastlib_py-0.2.4}/fastlib/context/__init__.py +0 -0
  29. {fastlib_py-0.2.3 → fastlib_py-0.2.4}/fastlib/context/contextvars.py +0 -0
  30. {fastlib_py-0.2.3 → fastlib_py-0.2.4}/fastlib/enums/base.py +0 -0
  31. {fastlib_py-0.2.3 → fastlib_py-0.2.4}/fastlib/exception/__init__.py +0 -0
  32. {fastlib_py-0.2.3 → fastlib_py-0.2.4}/fastlib/exception/base.py +0 -0
  33. {fastlib_py-0.2.3 → fastlib_py-0.2.4}/fastlib/exception/exception_handler.py +0 -0
  34. {fastlib_py-0.2.3 → fastlib_py-0.2.4}/fastlib/exception/exception_manager.py +0 -0
  35. {fastlib_py-0.2.3 → fastlib_py-0.2.4}/fastlib/i18n/manager.py +0 -0
  36. {fastlib_py-0.2.3 → fastlib_py-0.2.4}/fastlib/i18n/messages.py +0 -0
  37. {fastlib_py-0.2.3 → fastlib_py-0.2.4}/fastlib/i18n/types.py +0 -0
  38. {fastlib_py-0.2.3 → fastlib_py-0.2.4}/fastlib/i18n/utils.py +0 -0
  39. {fastlib_py-0.2.3 → fastlib_py-0.2.4}/fastlib/logging/__init__.py +0 -0
  40. {fastlib_py-0.2.3 → fastlib_py-0.2.4}/fastlib/logging/config.py +0 -0
  41. {fastlib_py-0.2.3 → fastlib_py-0.2.4}/fastlib/logging/handlers.py +0 -0
  42. {fastlib_py-0.2.3/fastlib/decorator → fastlib_py-0.2.4/fastlib/mapper}/__init__.py +0 -0
  43. {fastlib_py-0.2.3 → fastlib_py-0.2.4}/fastlib/mapper/base_mapper.py +0 -0
  44. {fastlib_py-0.2.3/fastlib/mapper → fastlib_py-0.2.4/fastlib/mapper/impl}/__init__.py +0 -0
  45. {fastlib_py-0.2.3 → fastlib_py-0.2.4}/fastlib/mapper/impl/base_mapper_impl.py +0 -0
  46. {fastlib_py-0.2.3 → fastlib_py-0.2.4}/fastlib/middleware/db_session.py +0 -0
  47. {fastlib_py-0.2.3 → fastlib_py-0.2.4}/fastlib/middleware/i18n.py +0 -0
  48. {fastlib_py-0.2.3 → fastlib_py-0.2.4}/fastlib/middleware/jwt.py +0 -0
  49. {fastlib_py-0.2.3 → fastlib_py-0.2.4}/fastlib/migrate/migrate.py +0 -0
  50. {fastlib_py-0.2.3 → fastlib_py-0.2.4}/fastlib/openapi/__init__.py +0 -0
  51. {fastlib_py-0.2.3 → fastlib_py-0.2.4}/fastlib/openapi/offline.py +0 -0
  52. {fastlib_py-0.2.3 → fastlib_py-0.2.4}/fastlib/router/__init__.py +0 -0
  53. {fastlib_py-0.2.3 → fastlib_py-0.2.4}/fastlib/router/base.py +0 -0
  54. {fastlib_py-0.2.3 → fastlib_py-0.2.4}/fastlib/schema/__init__.py +0 -0
  55. {fastlib_py-0.2.3 → fastlib_py-0.2.4}/fastlib/schema/base.py +0 -0
  56. {fastlib_py-0.2.3 → fastlib_py-0.2.4}/fastlib/schema/response.py +0 -0
  57. {fastlib_py-0.2.3 → fastlib_py-0.2.4}/fastlib/security/__init__.py +0 -0
  58. {fastlib_py-0.2.3 → fastlib_py-0.2.4}/fastlib/security/security.py +0 -0
  59. {fastlib_py-0.2.3 → fastlib_py-0.2.4}/fastlib/security/utils.py +0 -0
  60. {fastlib_py-0.2.3/fastlib/mapper/impl → fastlib_py-0.2.4/fastlib/service}/__init__.py +0 -0
  61. {fastlib_py-0.2.3 → fastlib_py-0.2.4}/fastlib/service/base_service.py +0 -0
  62. {fastlib_py-0.2.3/fastlib/service → fastlib_py-0.2.4/fastlib/service/impl}/__init__.py +0 -0
  63. {fastlib_py-0.2.3 → fastlib_py-0.2.4}/fastlib/service/impl/base_service_impl.py +0 -0
  64. {fastlib_py-0.2.3 → fastlib_py-0.2.4}/fastlib/session/__init__.py +0 -0
  65. {fastlib_py-0.2.3 → fastlib_py-0.2.4}/fastlib/session/db_engine.py +0 -0
  66. {fastlib_py-0.2.3 → fastlib_py-0.2.4}/fastlib/session/db_session.py +0 -0
  67. {fastlib_py-0.2.3 → fastlib_py-0.2.4}/fastlib/utils/__init__.py +0 -0
  68. {fastlib_py-0.2.3 → fastlib_py-0.2.4}/fastlib/utils/excel_util.py +0 -0
  69. {fastlib_py-0.2.3 → fastlib_py-0.2.4}/fastlib/utils/file_util.py +0 -0
  70. {fastlib_py-0.2.3 → fastlib_py-0.2.4}/fastlib/utils/http_util.py +0 -0
  71. {fastlib_py-0.2.3 → fastlib_py-0.2.4}/fastlib/utils/ip_util.py +0 -0
  72. {fastlib_py-0.2.3 → fastlib_py-0.2.4}/fastlib/utils/snowflake_util.py +0 -0
  73. {fastlib_py-0.2.3 → fastlib_py-0.2.4}/fastlib/utils/str_util.py +0 -0
  74. {fastlib_py-0.2.3 → fastlib_py-0.2.4}/fastlib_py.egg-info/dependency_links.txt +0 -0
  75. {fastlib_py-0.2.3 → fastlib_py-0.2.4}/fastlib_py.egg-info/requires.txt +0 -0
  76. {fastlib_py-0.2.3 → fastlib_py-0.2.4}/fastlib_py.egg-info/top_level.txt +0 -0
  77. {fastlib_py-0.2.3 → fastlib_py-0.2.4}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fastlib-py
3
- Version: 0.2.3
3
+ Version: 0.2.4
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>
@@ -3,5 +3,5 @@
3
3
  from .manager import get_cache_client
4
4
 
5
5
  __all__ = [
6
- get_cache_client,
6
+ "get_cache_client",
7
7
  ]
@@ -1,10 +1,8 @@
1
1
  """Enum for the application"""
2
2
 
3
3
  from .base import DBTypeEnum, MediaTypeEnum, SortEnum
4
- from .base_error_code import ExceptionCode
5
4
 
6
5
  __all__ = [
7
- ExceptionCode,
8
6
  SortEnum,
9
7
  DBTypeEnum,
10
8
  MediaTypeEnum,
@@ -2,6 +2,5 @@
2
2
 
3
3
  from .db_session import SQLAlchemyMiddleware, db
4
4
  from .jwt import jwt_middleware
5
- from .log import log_requests
6
5
 
7
- __all__ = [SQLAlchemyMiddleware, jwt_middleware, log_requests, db]
6
+ __all__ = [SQLAlchemyMiddleware, jwt_middleware, db]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fastlib-py
3
- Version: 0.2.3
3
+ Version: 0.2.4
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>
@@ -20,8 +20,6 @@ fastlib/constant/__init__.py
20
20
  fastlib/constant/constant.py
21
21
  fastlib/context/__init__.py
22
22
  fastlib/context/contextvars.py
23
- fastlib/decorator/__init__.py
24
- fastlib/decorator/base.py
25
23
  fastlib/enums/__init__.py
26
24
  fastlib/enums/base.py
27
25
  fastlib/exception/__init__.py
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "fastlib-py"
3
- version = "0.2.3"
3
+ version = "0.2.4"
4
4
  description = "Fastlib, high performance, easy to use, fast to code, ready for production"
5
5
  readme = "README.md"
6
6
  keywords = [
@@ -1,237 +0,0 @@
1
- # SPDX-License-Identifier: MIT
2
- """Commonly used decorator modules"""
3
- import asyncio
4
- from functools import wraps
5
- import functools
6
- import hashlib
7
- import json
8
- import time
9
- from typing import Any, Callable, Optional
10
- from loguru import Logger
11
-
12
- from fastlib.cache.manager import get_cache_client
13
-
14
-
15
- def log_request_time(logger_name: Optional[str] = None):
16
- """
17
- Decorator to log API request execution time.
18
-
19
- Args:
20
- logger_name: Name of the logger instance to use. If None, uses default logger.
21
-
22
- Returns:
23
- Decorator function
24
- """
25
-
26
- def decorator(func: Callable):
27
- @wraps(func)
28
- async def async_wrapper(*args, **kwargs):
29
- return await _time_request_async(func, logger_name, *args, **kwargs)
30
-
31
- @wraps(func)
32
- def sync_wrapper(*args, **kwargs):
33
- return _time_request_sync(func, logger_name, *args, **kwargs)
34
-
35
- # Return appropriate wrapper based on function type
36
- if asyncio.iscoroutinefunction(func):
37
- return async_wrapper
38
- return sync_wrapper
39
-
40
- return decorator
41
-
42
-
43
- async def _time_request_async(func: Callable, logger_name: str, *args, **kwargs) -> Any:
44
- """
45
- Internal function to time and log async request execution.
46
-
47
- Args:
48
- func: The decorated function
49
- logger_name: Logger instance name
50
- *args: Function arguments
51
- **kwargs: Function keyword arguments
52
-
53
- Returns:
54
- Result of the function execution
55
- """
56
- # Get logger instance
57
- logger_instance = Logger.get_instance(logger_name)
58
-
59
- # Record start time
60
- start_time = time.time()
61
-
62
- try:
63
- # Execute the function
64
- result = await func(*args, **kwargs)
65
-
66
- # Calculate execution time
67
- execution_time = time.time() - start_time
68
-
69
- # Log success
70
- logger_instance.info(
71
- f"API endpoint {func.__name__} executed successfully",
72
- execution_time_ms=round(execution_time * 1000, 2),
73
- status="success",
74
- endpoint=func.__name__,
75
- )
76
-
77
- return result
78
-
79
- except Exception as e:
80
- # Calculate execution time (even if error occurred)
81
- execution_time = time.time() - start_time
82
-
83
- # Log error
84
- logger_instance.error(
85
- f"API endpoint {func.__name__} execution failed: {str(e)}",
86
- execution_time_ms=round(execution_time * 1000, 2),
87
- status="error",
88
- endpoint=func.__name__,
89
- exc_info=e,
90
- )
91
-
92
- # Re-raise the exception
93
- raise
94
-
95
-
96
- def _time_request_sync(func: Callable, logger_name: str, *args, **kwargs) -> Any:
97
- """
98
- Internal function to time and log synchronous request execution.
99
-
100
- Args:
101
- func: The decorated function
102
- logger_name: Logger instance name
103
- *args: Function arguments
104
- **kwargs: Function keyword arguments
105
-
106
- Returns:
107
- Result of the function execution
108
- """
109
- # Get logger instance
110
- logger_instance = Logger.get_instance(logger_name)
111
-
112
- # Record start time
113
- start_time = time.time()
114
-
115
- try:
116
- # Execute the function
117
- result = func(*args, **kwargs)
118
-
119
- # Calculate execution time
120
- execution_time = time.time() - start_time
121
-
122
- # Log success
123
- logger_instance.info(
124
- f"API endpoint {func.__name__} executed successfully",
125
- execution_time_ms=round(execution_time * 1000, 2),
126
- status="success",
127
- endpoint=func.__name__,
128
- )
129
-
130
- return result
131
-
132
- except Exception as e:
133
- # Calculate execution time (even if error occurred)
134
- execution_time = time.time() - start_time
135
-
136
- # Log error
137
- logger_instance.error(
138
- f"API endpoint {func.__name__} execution failed: {str(e)}",
139
- execution_time_ms=round(execution_time * 1000, 2),
140
- status="error",
141
- endpoint=func.__name__,
142
- exc_info=e,
143
- )
144
-
145
- # Re-raise the exception
146
- raise
147
-
148
-
149
- def prevent_duplicate_submission(
150
- key_prefix: str = "duplicate_submission",
151
- ttl: int = 60,
152
- include_args: bool = True,
153
- include_kwargs: bool = True,
154
- custom_key_func: Optional[Callable] = None,
155
- ):
156
- """Decorator to prevent duplicate submissions within a specified time window.
157
-
158
- Args:
159
- key_prefix: Prefix for the cache key
160
- ttl: Time to live in seconds for the duplicate check
161
- include_args: Whether to include function args in the cache key
162
- include_kwargs: Whether to include function kwargs in the cache key
163
- custom_key_func: Optional custom function to generate cache key
164
-
165
- Returns:
166
- Decorated function that prevents duplicate submissions
167
- """
168
-
169
- def decorator(func: Callable) -> Callable:
170
- @functools.wraps(func)
171
- async def async_wrapper(*args, **kwargs):
172
- # Generate cache key
173
- if custom_key_func:
174
- cache_key = custom_key_func(*args, **kwargs)
175
- else:
176
- key_parts = [key_prefix, func.__name__]
177
-
178
- if include_args and args:
179
- # Skip 'self' for instance methods
180
- args_to_hash = (
181
- args[1:] if args and hasattr(args[0], "__class__") else args
182
- )
183
- key_parts.append(str(args_to_hash))
184
-
185
- if include_kwargs and kwargs:
186
- # Sort kwargs for consistent key generation
187
- sorted_kwargs = json.dumps(kwargs, sort_keys=True)
188
- key_parts.append(sorted_kwargs)
189
-
190
- # Create hash of the key parts for a shorter key
191
- key_content = ":".join(key_parts)
192
- cache_key = (
193
- f"{key_prefix}:{hashlib.md5(key_content.encode()).hexdigest()}"
194
- )
195
-
196
- # Get cache client
197
- cache = await get_cache_client()
198
-
199
- # Check if request is duplicate
200
- existing = await cache.get(cache_key)
201
- if existing is not None:
202
- raise DuplicateSubmissionError(
203
- f"Duplicate submission detected. Please wait {ttl} seconds before retrying."
204
- )
205
-
206
- # Set lock in cache
207
- await cache.set(cache_key, "locked", ttl=ttl)
208
-
209
- try:
210
- # Execute the original function
211
- result = await func(*args, **kwargs)
212
- return result
213
- except Exception as e:
214
- # On error, remove the lock to allow retry
215
- await cache.delete(cache_key)
216
- raise e
217
-
218
- @functools.wraps(func)
219
- def sync_wrapper(*args, **kwargs):
220
- raise NotImplementedError(
221
- "Synchronous functions are not supported. "
222
- "Please use async functions with prevent_duplicate_submission decorator."
223
- )
224
-
225
- # Return appropriate wrapper based on function type
226
- if asyncio.iscoroutinefunction(func):
227
- return async_wrapper
228
- else:
229
- return sync_wrapper
230
-
231
- return decorator
232
-
233
-
234
- class DuplicateSubmissionError(Exception):
235
- """Exception raised when a duplicate submission is detected."""
236
-
237
- pass
File without changes
File without changes
File without changes
File without changes