|
11 | 11 | # See the License for the specific language governing permissions and
|
12 | 12 | # limitations under the License.
|
13 | 13 | # ========= Copyright 2023-2024 @ CAMEL-AI.org. All Rights Reserved. =========
|
| 14 | +import asyncio |
14 | 15 | import functools
|
15 | 16 | import importlib
|
| 17 | +import inspect |
16 | 18 | import logging
|
17 | 19 | import os
|
18 | 20 | import platform
|
@@ -978,36 +980,54 @@ def with_timeout(timeout=None):
|
978 | 980 | """
|
979 | 981 |
|
980 | 982 | def decorator(func):
|
981 |
| - @functools.wraps(func) |
982 |
| - def wrapper(*args, **kwargs): |
983 |
| - # Determine the effective timeout value |
984 |
| - effective_timeout = timeout |
985 |
| - if effective_timeout is None and args: |
986 |
| - effective_timeout = getattr(args[0], 'timeout', None) |
987 |
| - |
988 |
| - # If no timeout value is provided, execute function normally |
989 |
| - if effective_timeout is None: |
990 |
| - return func(*args, **kwargs) |
991 |
| - |
992 |
| - # Container to hold the result of the function call |
993 |
| - result_container = [] |
994 |
| - |
995 |
| - def target(): |
996 |
| - result_container.append(func(*args, **kwargs)) |
997 |
| - |
998 |
| - # Start the function in a new thread |
999 |
| - thread = threading.Thread(target=target) |
1000 |
| - thread.start() |
1001 |
| - thread.join(effective_timeout) |
1002 |
| - |
1003 |
| - # Check if the thread is still alive after the timeout |
1004 |
| - if thread.is_alive(): |
1005 |
| - return ( |
1006 |
| - f"Function `{func.__name__}` execution timed out, " |
1007 |
| - f"exceeded {effective_timeout} seconds." |
| 983 | + if inspect.iscoroutinefunction(func): |
| 984 | + |
| 985 | + @functools.wraps(func) |
| 986 | + async def async_wrapper(*args, **kwargs): |
| 987 | + eff_timeout = timeout |
| 988 | + if eff_timeout is None and args: |
| 989 | + eff_timeout = getattr(args[0], 'timeout', None) |
| 990 | + |
| 991 | + if eff_timeout is None: |
| 992 | + return await func(*args, **kwargs) |
| 993 | + |
| 994 | + return await asyncio.wait_for( |
| 995 | + func(*args, **kwargs), timeout=eff_timeout |
1008 | 996 | )
|
1009 |
| - else: |
1010 |
| - return result_container[0] |
| 997 | + |
| 998 | + return async_wrapper |
| 999 | + else: |
| 1000 | + |
| 1001 | + @functools.wraps(func) |
| 1002 | + def wrapper(*args, **kwargs): |
| 1003 | + # Determine the effective timeout value |
| 1004 | + effective_timeout = timeout |
| 1005 | + if effective_timeout is None and args: |
| 1006 | + effective_timeout = getattr(args[0], 'timeout', None) |
| 1007 | + |
| 1008 | + # If no timeout value is provided, execute function normally |
| 1009 | + if effective_timeout is None: |
| 1010 | + return func(*args, **kwargs) |
| 1011 | + |
| 1012 | + # Container to hold the result of the function call |
| 1013 | + result_container = [] |
| 1014 | + |
| 1015 | + def target(): |
| 1016 | + result_container.append(func(*args, **kwargs)) |
| 1017 | + |
| 1018 | + # Start the function in a new thread |
| 1019 | + thread = threading.Thread(target=target) |
| 1020 | + thread.start() |
| 1021 | + thread.join(effective_timeout) |
| 1022 | + |
| 1023 | + # Check if the thread is still alive after the timeout |
| 1024 | + if thread.is_alive(): |
| 1025 | + return ( |
| 1026 | + f"Function `{func.__name__}` execution timed out, " |
| 1027 | + f"exceeded {effective_timeout} seconds." |
| 1028 | + ) |
| 1029 | + else: |
| 1030 | + return result_container[0] |
1011 | 1031 |
|
1012 | 1032 | return wrapper
|
1013 | 1033 |
|
|
0 commit comments