python-wrap 0.1.0__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.

Potentially problematic release.


This version of python-wrap might be problematic. Click here for more details.

@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 PythonWrap Contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,189 @@
1
+ Metadata-Version: 2.1
2
+ Name: python-wrap
3
+ Version: 0.1.0
4
+ Summary: A comprehensive collection of Python decorators and utility functions for enhanced development workflows
5
+ Home-page: https://github.com/Pythondeveloper6/PythonWrap
6
+ License: MIT
7
+ Keywords: decorators,utilities,python,development,tools,python
8
+ Author: Mahmoud Ahmed
9
+ Author-email: contact.mahmoudahmed@gmail.com
10
+ Maintainer: Mahmoud Ahmed
11
+ Maintainer-email: contact.mahmoudahmed@gmail.com
12
+ Requires-Python: >=3.8,<4.0
13
+ Classifier: Development Status :: 4 - Beta
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: License :: OSI Approved :: MIT License
16
+ Classifier: Operating System :: OS Independent
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Programming Language :: Python :: 3.8
19
+ Classifier: Programming Language :: Python :: 3.9
20
+ Classifier: Programming Language :: Python :: 3.10
21
+ Classifier: Programming Language :: Python :: 3.11
22
+ Classifier: Programming Language :: Python :: 3.12
23
+ Classifier: Programming Language :: Python :: 3.13
24
+ Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
25
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
26
+ Classifier: Typing :: Typed
27
+ Requires-Dist: typing-extensions (>=4.7.1,<5.0.0)
28
+ Requires-Dist: wrapt (>=1.15.0,<2.0.0)
29
+ Project-URL: Bug Tracker, https://github.com/Pythondeveloper6/PythonWrap/issues
30
+ Project-URL: Changelog, https://github.com/Pythondeveloper6/PythonWrap/blob/main/CHANGELOG.md
31
+ Project-URL: Documentation, https://python-wrap.readthedocs.io
32
+ Project-URL: Repository, https://github.com/Pythondeveloper6/PythonWrap
33
+ Description-Content-Type: text/markdown
34
+
35
+ # PythonWrap
36
+
37
+ A comprehensive collection of Python decorators and utility functions to enhance your development workflow.
38
+
39
+ ## Installation
40
+
41
+ ```bash
42
+ pip install python-wrap
43
+ ```
44
+
45
+ ## Features
46
+
47
+ PythonWrap provides a rich set of decorators that can be used either as decorators or as standalone functions:
48
+
49
+ ### Performance & Profiling
50
+ - `@timing`: Measure function execution time
51
+ - `@profile`: Profile function performance
52
+ - `@benchmark`: Compare execution times
53
+ - `@measure_memory`: Track memory usage
54
+
55
+ ### Error Handling & Reliability
56
+ - `@retry`: Retry failed operations
57
+ - `@retry_on_exception`: Retry on specific exceptions
58
+ - `@timeout`: Set execution time limits
59
+ - `@revert_on_failure`: Automatic state rollback on failure
60
+
61
+ ### Caching & Optimization
62
+ - `@memoize`: Cache function results
63
+ - `@cache`: Time-based result caching
64
+ - `@once`: Single execution guarantee
65
+
66
+ ### Debugging & Logging
67
+ - `@log_args`: Log function arguments
68
+ - `@log_return`: Log return values
69
+ - `@trace`: Log call stack traces
70
+ - `@audit`: Comprehensive function call auditing
71
+
72
+ ### Type Safety & Validation
73
+ - `@check_type`: Runtime type checking
74
+ - `@validate_args`: Custom argument validation
75
+
76
+ ### Development Tools
77
+ - `@deprecate`: Mark deprecated functions
78
+ - `@no_debug`: Disable debug output
79
+ - `@mock_data`: Easy data mocking
80
+ - `@rate_limit`: Control execution frequency
81
+
82
+ ### Concurrency
83
+ - `@run_in_thread`: Asynchronous execution
84
+ - `@transactional`: Atomic operations
85
+
86
+ ## Usage Examples
87
+
88
+ ### Using as Decorators
89
+
90
+ ```python
91
+ from python_wrap import timing, retry, memoize
92
+
93
+ # As a decorator
94
+ @timing
95
+ def slow_operation():
96
+ time.sleep(1)
97
+ return "Done"
98
+
99
+ # As a decorator with parameters
100
+ @retry(max_attempts=3, delay=1.0)
101
+ def unreliable_operation():
102
+ return api_call()
103
+
104
+ # Simple decorator
105
+ @memoize
106
+ def fibonacci(n):
107
+ if n < 2:
108
+ return n
109
+ return fibonacci(n-1) + fibonacci(n-2)
110
+ ```
111
+
112
+ ### Using as Functions
113
+
114
+ ```python
115
+ from python_wrap import timing, retry, memoize
116
+
117
+ # Using timing as a function
118
+ def slow_operation():
119
+ time.sleep(1)
120
+ return "Done"
121
+
122
+ result = timing(slow_operation)()
123
+
124
+ # Using retry as a function
125
+ def unreliable_operation():
126
+ return api_call()
127
+
128
+ result = retry(unreliable_operation, max_attempts=3, delay=1.0)()
129
+
130
+ # Using memoize as a function
131
+ def fibonacci(n):
132
+ if n < 2:
133
+ return n
134
+ return fibonacci(n-1) + fibonacci(n-2)
135
+
136
+ memoized_fib = memoize(fibonacci)
137
+ result = memoized_fib(10)
138
+ ```
139
+
140
+ ### Advanced Usage
141
+
142
+ ```python
143
+ from python_wrap import validate_args, check_type, timeout
144
+
145
+ # As decorators
146
+ @validate_args(x=lambda x: x > 0, y=lambda y: y < 100)
147
+ def process_numbers(x, y):
148
+ return x + y
149
+
150
+ @check_type(name=str, age=int)
151
+ def create_user(name, age):
152
+ return {"name": name, "age": age}
153
+
154
+ # As functions
155
+ def long_running_task():
156
+ process_large_dataset()
157
+
158
+ timed_task = timeout(5)(long_running_task)
159
+ result = timed_task()
160
+ ```
161
+
162
+ ### Combining Multiple Functions
163
+
164
+ ```python
165
+ from python_wrap import timing, retry, log_args
166
+
167
+ # As decorators
168
+ @timing
169
+ @retry(max_attempts=3)
170
+ @log_args
171
+ def complex_operation(x, y):
172
+ return expensive_calculation(x, y)
173
+
174
+ # As functions
175
+ def complex_operation(x, y):
176
+ return expensive_calculation(x, y)
177
+
178
+ # Compose functions
179
+ monitored_op = timing(retry(log_args(complex_operation), max_attempts=3))
180
+ result = monitored_op(1, 2)
181
+ ```
182
+
183
+ ## Contributing
184
+
185
+ Contributions are welcome! Please feel free to submit a Pull Request.
186
+
187
+ ## License
188
+
189
+ This project is licensed under the MIT License - see the LICENSE file for details.
@@ -0,0 +1,155 @@
1
+ # PythonWrap
2
+
3
+ A comprehensive collection of Python decorators and utility functions to enhance your development workflow.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ pip install python-wrap
9
+ ```
10
+
11
+ ## Features
12
+
13
+ PythonWrap provides a rich set of decorators that can be used either as decorators or as standalone functions:
14
+
15
+ ### Performance & Profiling
16
+ - `@timing`: Measure function execution time
17
+ - `@profile`: Profile function performance
18
+ - `@benchmark`: Compare execution times
19
+ - `@measure_memory`: Track memory usage
20
+
21
+ ### Error Handling & Reliability
22
+ - `@retry`: Retry failed operations
23
+ - `@retry_on_exception`: Retry on specific exceptions
24
+ - `@timeout`: Set execution time limits
25
+ - `@revert_on_failure`: Automatic state rollback on failure
26
+
27
+ ### Caching & Optimization
28
+ - `@memoize`: Cache function results
29
+ - `@cache`: Time-based result caching
30
+ - `@once`: Single execution guarantee
31
+
32
+ ### Debugging & Logging
33
+ - `@log_args`: Log function arguments
34
+ - `@log_return`: Log return values
35
+ - `@trace`: Log call stack traces
36
+ - `@audit`: Comprehensive function call auditing
37
+
38
+ ### Type Safety & Validation
39
+ - `@check_type`: Runtime type checking
40
+ - `@validate_args`: Custom argument validation
41
+
42
+ ### Development Tools
43
+ - `@deprecate`: Mark deprecated functions
44
+ - `@no_debug`: Disable debug output
45
+ - `@mock_data`: Easy data mocking
46
+ - `@rate_limit`: Control execution frequency
47
+
48
+ ### Concurrency
49
+ - `@run_in_thread`: Asynchronous execution
50
+ - `@transactional`: Atomic operations
51
+
52
+ ## Usage Examples
53
+
54
+ ### Using as Decorators
55
+
56
+ ```python
57
+ from python_wrap import timing, retry, memoize
58
+
59
+ # As a decorator
60
+ @timing
61
+ def slow_operation():
62
+ time.sleep(1)
63
+ return "Done"
64
+
65
+ # As a decorator with parameters
66
+ @retry(max_attempts=3, delay=1.0)
67
+ def unreliable_operation():
68
+ return api_call()
69
+
70
+ # Simple decorator
71
+ @memoize
72
+ def fibonacci(n):
73
+ if n < 2:
74
+ return n
75
+ return fibonacci(n-1) + fibonacci(n-2)
76
+ ```
77
+
78
+ ### Using as Functions
79
+
80
+ ```python
81
+ from python_wrap import timing, retry, memoize
82
+
83
+ # Using timing as a function
84
+ def slow_operation():
85
+ time.sleep(1)
86
+ return "Done"
87
+
88
+ result = timing(slow_operation)()
89
+
90
+ # Using retry as a function
91
+ def unreliable_operation():
92
+ return api_call()
93
+
94
+ result = retry(unreliable_operation, max_attempts=3, delay=1.0)()
95
+
96
+ # Using memoize as a function
97
+ def fibonacci(n):
98
+ if n < 2:
99
+ return n
100
+ return fibonacci(n-1) + fibonacci(n-2)
101
+
102
+ memoized_fib = memoize(fibonacci)
103
+ result = memoized_fib(10)
104
+ ```
105
+
106
+ ### Advanced Usage
107
+
108
+ ```python
109
+ from python_wrap import validate_args, check_type, timeout
110
+
111
+ # As decorators
112
+ @validate_args(x=lambda x: x > 0, y=lambda y: y < 100)
113
+ def process_numbers(x, y):
114
+ return x + y
115
+
116
+ @check_type(name=str, age=int)
117
+ def create_user(name, age):
118
+ return {"name": name, "age": age}
119
+
120
+ # As functions
121
+ def long_running_task():
122
+ process_large_dataset()
123
+
124
+ timed_task = timeout(5)(long_running_task)
125
+ result = timed_task()
126
+ ```
127
+
128
+ ### Combining Multiple Functions
129
+
130
+ ```python
131
+ from python_wrap import timing, retry, log_args
132
+
133
+ # As decorators
134
+ @timing
135
+ @retry(max_attempts=3)
136
+ @log_args
137
+ def complex_operation(x, y):
138
+ return expensive_calculation(x, y)
139
+
140
+ # As functions
141
+ def complex_operation(x, y):
142
+ return expensive_calculation(x, y)
143
+
144
+ # Compose functions
145
+ monitored_op = timing(retry(log_args(complex_operation), max_attempts=3))
146
+ result = monitored_op(1, 2)
147
+ ```
148
+
149
+ ## Contributing
150
+
151
+ Contributions are welcome! Please feel free to submit a Pull Request.
152
+
153
+ ## License
154
+
155
+ This project is licensed under the MIT License - see the LICENSE file for details.
@@ -0,0 +1,90 @@
1
+ [tool.poetry]
2
+ name = "python-wrap"
3
+ version = "0.1.0"
4
+ description = "A comprehensive collection of Python decorators and utility functions for enhanced development workflows"
5
+ authors = ["Mahmoud Ahmed <contact.mahmoudahmed@gmail.com>"]
6
+ maintainers = ["Mahmoud Ahmed <contact.mahmoudahmed@gmail.com>"]
7
+ license = "MIT"
8
+ readme = "README.md"
9
+ homepage = "https://github.com/Pythondeveloper6/PythonWrap"
10
+ repository = "https://github.com/Pythondeveloper6/PythonWrap"
11
+ documentation = "https://python-wrap.readthedocs.io"
12
+ keywords = ["decorators", "utilities", "python", "development", "tools","python"]
13
+ classifiers = [
14
+ "Development Status :: 4 - Beta",
15
+ "Intended Audience :: Developers",
16
+ "License :: OSI Approved :: MIT License",
17
+ "Operating System :: OS Independent",
18
+ "Programming Language :: Python :: 3",
19
+ "Programming Language :: Python :: 3.8",
20
+ "Programming Language :: Python :: 3.9",
21
+ "Programming Language :: Python :: 3.10",
22
+ "Programming Language :: Python :: 3.11",
23
+ "Topic :: Software Development :: Libraries :: Python Modules",
24
+ "Topic :: Software Development :: Libraries :: Application Frameworks",
25
+ "Typing :: Typed"
26
+ ]
27
+ packages = [{include = "python_wrap"}]
28
+
29
+ [tool.poetry.dependencies]
30
+ python = "^3.8"
31
+ wrapt = "^1.15.0"
32
+ typing-extensions = "^4.7.1" # For better type hints support
33
+
34
+ [tool.poetry.group.dev.dependencies]
35
+ pytest = "^7.4.0"
36
+ pytest-cov = "^4.1.0"
37
+ black = "^23.7.0" # Code formatting
38
+ isort = "^5.12.0" # Import sorting
39
+ mypy = "^1.4.1" # Type checking
40
+ pylint = "^2.17.5" # Code linting
41
+ pre-commit = "^3.3.3" # Git hooks
42
+ sphinx = "^7.1.1" # Documentation
43
+ sphinx-rtd-theme = "^1.2.2" # Documentation theme
44
+
45
+ [tool.poetry.urls]
46
+ "Bug Tracker" = "https://github.com/Pythondeveloper6/PythonWrap/issues"
47
+ "Changelog" = "https://github.com/Pythondeveloper6/PythonWrap/blob/main/CHANGELOG.md"
48
+
49
+ [build-system]
50
+ requires = ["poetry-core"]
51
+ build-backend = "poetry.core.masonry.api"
52
+
53
+ [tool.black]
54
+ line-length = 88
55
+ target-version = ["py38"]
56
+ include = '\.pyi?$'
57
+
58
+ [tool.isort]
59
+ profile = "black"
60
+ multi_line_output = 3
61
+ line_length = 88
62
+
63
+ [tool.mypy]
64
+ python_version = "3.8"
65
+ warn_return_any = true
66
+ warn_unused_configs = true
67
+ disallow_untyped_defs = true
68
+ check_untyped_defs = true
69
+
70
+ [tool.pytest.ini_options]
71
+ minversion = "7.0"
72
+ addopts = "-ra -q --cov=python_wrap --cov-report=term-missing"
73
+ testpaths = ["tests"]
74
+
75
+ [tool.coverage.run]
76
+ source = ["python_wrap"]
77
+ branch = true
78
+
79
+ [tool.coverage.report]
80
+ exclude_lines = [
81
+ "pragma: no cover",
82
+ "def __repr__",
83
+ "if self.debug:",
84
+ "raise NotImplementedError",
85
+ "if __name__ == .__main__.:",
86
+ "pass",
87
+ "raise ImportError"
88
+ ]
89
+ ignore_errors = true
90
+ omit = ["tests/*", "setup.py"]
@@ -0,0 +1,56 @@
1
+ """
2
+ PythonWrap - A comprehensive collection of Python decorators and utility functions.
3
+ """
4
+
5
+ from .decorators import (
6
+ timing,
7
+ retry,
8
+ memoize,
9
+ log_args,
10
+ log_return,
11
+ validate_args,
12
+ cache,
13
+ once,
14
+ deprecate,
15
+ check_type,
16
+ retry_on_exception,
17
+ measure_memory,
18
+ profile,
19
+ rate_limit,
20
+ mock_data,
21
+ benchmark,
22
+ run_in_thread,
23
+ no_debug,
24
+ transactional,
25
+ revert_on_failure,
26
+ audit,
27
+ trace,
28
+ timeout,
29
+ )
30
+
31
+ __version__ = "0.1.0"
32
+ __all__ = [
33
+ "timing",
34
+ "retry",
35
+ "memoize",
36
+ "log_args",
37
+ "log_return",
38
+ "validate_args",
39
+ "cache",
40
+ "once",
41
+ "deprecate",
42
+ "check_type",
43
+ "retry_on_exception",
44
+ "measure_memory",
45
+ "profile",
46
+ "rate_limit",
47
+ "mock_data",
48
+ "benchmark",
49
+ "run_in_thread",
50
+ "no_debug",
51
+ "transactional",
52
+ "revert_on_failure",
53
+ "audit",
54
+ "trace",
55
+ "timeout",
56
+ ]
@@ -0,0 +1,702 @@
1
+ """
2
+ Core decorators module containing all decorator implementations.
3
+ """
4
+
5
+ import time
6
+ import logging
7
+ import functools
8
+ import threading
9
+ import warnings
10
+ import inspect
11
+ import traceback
12
+ from typing import Any, Callable, Dict, List, Type, Union
13
+ from datetime import datetime, timedelta
14
+ import threading
15
+ import queue
16
+ import signal
17
+ import resource
18
+ import cProfile
19
+ import pstats
20
+ import io
21
+ from contextlib import contextmanager
22
+
23
+ # Configure logging
24
+ logging.basicConfig(level=logging.INFO)
25
+ logger = logging.getLogger(__name__)
26
+
27
+ def _timing_impl(func, *args, **kwargs):
28
+ """Implementation of timing functionality."""
29
+ start_time = time.time()
30
+ result = func(*args, **kwargs)
31
+ end_time = time.time()
32
+ logger.info(f"{func.__name__} took {end_time - start_time:.4f} seconds to execute")
33
+ return result
34
+
35
+ def timing(func: Union[Callable, None] = None) -> Callable:
36
+ """
37
+ Measures and logs the execution time of a function.
38
+ Can be used as a decorator or function:
39
+
40
+ @timing
41
+ def func(): pass
42
+
43
+ # or
44
+ result = timing(func)()
45
+ """
46
+ if func is None:
47
+ return timing
48
+
49
+ @functools.wraps(func)
50
+ def wrapper(*args, **kwargs):
51
+ return _timing_impl(func, *args, **kwargs)
52
+ return wrapper
53
+
54
+ def _retry_impl(func, max_attempts, delay, *args, **kwargs):
55
+ """Implementation of retry functionality."""
56
+ attempts = 0
57
+ while attempts < max_attempts:
58
+ try:
59
+ return func(*args, **kwargs)
60
+ except Exception as e:
61
+ attempts += 1
62
+ if attempts == max_attempts:
63
+ raise
64
+ logger.warning(f"Attempt {attempts} failed, retrying in {delay} seconds...")
65
+ time.sleep(delay)
66
+ return None
67
+
68
+ def retry(func: Union[Callable, None] = None, *, max_attempts: int = 3, delay: float = 1.0) -> Callable:
69
+ """
70
+ Retries a function in case of failure.
71
+ Can be used as a decorator or function:
72
+
73
+ @retry(max_attempts=3)
74
+ def func(): pass
75
+
76
+ # or
77
+ result = retry(func, max_attempts=3)()
78
+ """
79
+ if func is None:
80
+ return lambda f: retry(f, max_attempts=max_attempts, delay=delay)
81
+
82
+ @functools.wraps(func)
83
+ def wrapper(*args, **kwargs):
84
+ return _retry_impl(func, max_attempts, delay, *args, **kwargs)
85
+ return wrapper
86
+
87
+ def _memoize_impl(func, cache, *args, **kwargs):
88
+ """Implementation of memoize functionality."""
89
+ key = str(args) + str(kwargs)
90
+ if key not in cache:
91
+ cache[key] = func(*args, **kwargs)
92
+ return cache[key]
93
+
94
+ def memoize(func: Union[Callable, None] = None) -> Callable:
95
+ """
96
+ Caches the result of a function to prevent redundant calculations.
97
+ Can be used as a decorator or function:
98
+
99
+ @memoize
100
+ def func(): pass
101
+
102
+ # or
103
+ result = memoize(func)()
104
+ """
105
+ if func is None:
106
+ return memoize
107
+
108
+ cache = {}
109
+
110
+ @functools.wraps(func)
111
+ def wrapper(*args, **kwargs):
112
+ return _memoize_impl(func, cache, *args, **kwargs)
113
+ return wrapper
114
+
115
+ def _log_args_impl(func, *args, **kwargs):
116
+ """Implementation of log_args functionality."""
117
+ logger.info(f"Calling {func.__name__} with args: {args}, kwargs: {kwargs}")
118
+ return func(*args, **kwargs)
119
+
120
+ def log_args(func: Union[Callable, None] = None) -> Callable:
121
+ """
122
+ Logs the arguments passed to a function.
123
+ Can be used as a decorator or function:
124
+
125
+ @log_args
126
+ def func(): pass
127
+
128
+ # or
129
+ result = log_args(func)()
130
+ """
131
+ if func is None:
132
+ return log_args
133
+
134
+ @functools.wraps(func)
135
+ def wrapper(*args, **kwargs):
136
+ return _log_args_impl(func, *args, **kwargs)
137
+ return wrapper
138
+
139
+ def _log_return_impl(func, *args, **kwargs):
140
+ """Implementation of log_return functionality."""
141
+ result = func(*args, **kwargs)
142
+ logger.info(f"{func.__name__} returned: {result}")
143
+ return result
144
+
145
+ def log_return(func: Union[Callable, None] = None) -> Callable:
146
+ """
147
+ Logs the return value of a function after execution.
148
+ Can be used as a decorator or function:
149
+
150
+ @log_return
151
+ def func(): pass
152
+
153
+ # or
154
+ result = log_return(func)()
155
+ """
156
+ if func is None:
157
+ return log_return
158
+
159
+ @functools.wraps(func)
160
+ def wrapper(*args, **kwargs):
161
+ return _log_return_impl(func, *args, **kwargs)
162
+ return wrapper
163
+
164
+ def _validate_args_impl(func, validators, *args, **kwargs):
165
+ """Implementation of validate_args functionality."""
166
+ sig = inspect.signature(func)
167
+ bound_args = sig.bind(*args, **kwargs)
168
+ for param_name, validator in validators.items():
169
+ if param_name in bound_args.arguments:
170
+ value = bound_args.arguments[param_name]
171
+ if not validator(value):
172
+ raise ValueError(f"Invalid value for {param_name}: {value}")
173
+ return func(*args, **kwargs)
174
+
175
+ def validate_args(**validators):
176
+ """
177
+ Validates the arguments passed to a function based on custom rules.
178
+ Can be used as a decorator or function:
179
+
180
+ @validate_args(x=lambda x: x > 0)
181
+ def func(): pass
182
+
183
+ # or
184
+ result = validate_args(x=lambda x: x > 0)(func)()
185
+ """
186
+ def decorator(func):
187
+ @functools.wraps(func)
188
+ def wrapper(*args, **kwargs):
189
+ return _validate_args_impl(func, validators, *args, **kwargs)
190
+ return wrapper
191
+ return decorator
192
+
193
+ def _cache_impl(func, duration, cache_data, *args, **kwargs):
194
+ """Implementation of cache functionality."""
195
+ key = str(args) + str(kwargs)
196
+ now = datetime.now()
197
+ if key in cache_data:
198
+ result, timestamp = cache_data[key]
199
+ if now - timestamp < duration:
200
+ return result
201
+ result = func(*args, **kwargs)
202
+ cache_data[key] = (result, now)
203
+ return result
204
+
205
+ def cache(duration: timedelta):
206
+ """
207
+ Caches the result of a function call for a specified duration.
208
+ Can be used as a decorator or function:
209
+
210
+ @cache(duration=timedelta(minutes=5))
211
+ def func(): pass
212
+
213
+ # or
214
+ result = cache(duration=timedelta(minutes=5))(func)()
215
+ """
216
+ cache_data = {}
217
+
218
+ def decorator(func):
219
+ @functools.wraps(func)
220
+ def wrapper(*args, **kwargs):
221
+ return _cache_impl(func, duration, cache_data, *args, **kwargs)
222
+ return wrapper
223
+ return decorator
224
+
225
+ def once(func: Union[Callable, None] = None) -> Callable:
226
+ """
227
+ Ensures the function runs only once, even across multiple calls.
228
+ Can be used as a decorator or function:
229
+
230
+ @once
231
+ def func(): pass
232
+
233
+ # or
234
+ result = once(func)()
235
+ """
236
+ if func is None:
237
+ return once
238
+
239
+ # Store state in a dictionary to maintain closure state
240
+ state = {'has_run': False, 'result': None}
241
+
242
+ @functools.wraps(func)
243
+ def wrapper(*args, **kwargs):
244
+ if not state['has_run']:
245
+ state['result'] = func(*args, **kwargs)
246
+ state['has_run'] = True
247
+ return state['result']
248
+
249
+ return wrapper
250
+
251
+ def _deprecate_impl(func, message, *args, **kwargs):
252
+ """Implementation of deprecate functionality."""
253
+ warn_msg = message or f"{func.__name__} is deprecated and will be removed in a future version."
254
+ warnings.warn(warn_msg, DeprecationWarning, stacklevel=2)
255
+ return func(*args, **kwargs)
256
+
257
+ def deprecate(message: str = None):
258
+ """
259
+ Marks a function as deprecated and provides a warning when used.
260
+ Can be used as a decorator or function:
261
+
262
+ @deprecate("Use new_func instead")
263
+ def func(): pass
264
+
265
+ # or
266
+ result = deprecate("Use new_func instead")(func)()
267
+ """
268
+ def decorator(func):
269
+ @functools.wraps(func)
270
+ def wrapper(*args, **kwargs):
271
+ return _deprecate_impl(func, message, *args, **kwargs)
272
+ return wrapper
273
+ return decorator
274
+
275
+ def _check_type_impl(func, type_hints, *args, **kwargs):
276
+ """Implementation of check_type functionality."""
277
+ sig = inspect.signature(func)
278
+ bound_args = sig.bind(*args, **kwargs)
279
+ for param_name, expected_type in type_hints.items():
280
+ if param_name in bound_args.arguments:
281
+ value = bound_args.arguments[param_name]
282
+ if not isinstance(value, expected_type):
283
+ raise TypeError(f"Parameter {param_name} must be of type {expected_type}")
284
+ return func(*args, **kwargs)
285
+
286
+ def check_type(**type_hints):
287
+ """
288
+ Verifies that function arguments are of the correct type.
289
+ Can be used as a decorator or function:
290
+
291
+ @check_type(x=int, y=str)
292
+ def func(): pass
293
+
294
+ # or
295
+ result = check_type(x=int, y=str)(func)()
296
+ """
297
+ def decorator(func):
298
+ @functools.wraps(func)
299
+ def wrapper(*args, **kwargs):
300
+ return _check_type_impl(func, type_hints, *args, **kwargs)
301
+ return wrapper
302
+ return decorator
303
+
304
+ def _retry_on_exception_impl(func, exceptions, *args, **kwargs):
305
+ """Implementation of retry_on_exception functionality."""
306
+ while True:
307
+ try:
308
+ return func(*args, **kwargs)
309
+ except exceptions as e:
310
+ logger.warning(f"Caught exception {type(e).__name__}, retrying...")
311
+ continue
312
+ except Exception as e:
313
+ raise
314
+
315
+ def retry_on_exception(*exceptions):
316
+ """
317
+ Retries the function when specific exceptions are raised.
318
+ Can be used as a decorator or function:
319
+
320
+ @retry_on_exception(ValueError, KeyError)
321
+ def func(): pass
322
+
323
+ # or
324
+ result = retry_on_exception(ValueError, KeyError)(func)()
325
+ """
326
+ if not exceptions:
327
+ exceptions = (Exception,)
328
+
329
+ def decorator(func):
330
+ @functools.wraps(func)
331
+ def wrapper(*args, **kwargs):
332
+ return _retry_on_exception_impl(func, exceptions, *args, **kwargs)
333
+ return wrapper
334
+ return decorator
335
+
336
+ def _measure_memory_impl(func, *args, **kwargs):
337
+ """Implementation of measure_memory functionality."""
338
+ initial_memory = resource.getrusage(resource.RUSAGE_SELF).ru_maxrss
339
+ result = func(*args, **kwargs)
340
+ final_memory = resource.getrusage(resource.RUSAGE_SELF).ru_maxrss
341
+ memory_used = final_memory - initial_memory
342
+ logger.info(f"{func.__name__} used {memory_used} KB of memory")
343
+ return result
344
+
345
+ def measure_memory(func: Union[Callable, None] = None) -> Callable:
346
+ """
347
+ Measures the memory usage of a function while it runs.
348
+ Can be used as a decorator or function:
349
+
350
+ @measure_memory
351
+ def func(): pass
352
+
353
+ # or
354
+ result = measure_memory(func)()
355
+ """
356
+ if func is None:
357
+ return measure_memory
358
+
359
+ @functools.wraps(func)
360
+ def wrapper(*args, **kwargs):
361
+ return _measure_memory_impl(func, *args, **kwargs)
362
+ return wrapper
363
+
364
+ def _profile_impl(func, *args, **kwargs):
365
+ """Implementation of profile functionality."""
366
+ profiler = cProfile.Profile()
367
+ try:
368
+ return profiler.runcall(func, *args, **kwargs)
369
+ finally:
370
+ s = io.StringIO()
371
+ stats = pstats.Stats(profiler, stream=s).sort_stats('cumulative')
372
+ stats.print_stats()
373
+ logger.info(f"Profile for {func.__name__}:\n{s.getvalue()}")
374
+
375
+ def profile(func: Union[Callable, None] = None) -> Callable:
376
+ """
377
+ Profiles the performance of a function to aid in optimization.
378
+ Can be used as a decorator or function:
379
+
380
+ @profile
381
+ def func(): pass
382
+
383
+ # or
384
+ result = profile(func)()
385
+ """
386
+ if func is None:
387
+ return profile
388
+
389
+ @functools.wraps(func)
390
+ def wrapper(*args, **kwargs):
391
+ return _profile_impl(func, *args, **kwargs)
392
+ return wrapper
393
+
394
+ def _rate_limit_impl(func, calls, period, call_times, *args, **kwargs):
395
+ """Implementation of rate_limit functionality."""
396
+ now = time.time()
397
+ call_times[:] = [t for t in call_times if now - t < period]
398
+ if len(call_times) >= calls:
399
+ raise Exception(f"Rate limit exceeded: {calls} calls per {period} seconds")
400
+ call_times.append(now)
401
+ return func(*args, **kwargs)
402
+
403
+ def rate_limit(calls: int, period: float):
404
+ """
405
+ Limits the frequency of function calls to avoid overload.
406
+ Can be used as a decorator or function:
407
+
408
+ @rate_limit(calls=100, period=60)
409
+ def func(): pass
410
+
411
+ # or
412
+ result = rate_limit(calls=100, period=60)(func)()
413
+ """
414
+ call_times = []
415
+
416
+ def decorator(func):
417
+ @functools.wraps(func)
418
+ def wrapper(*args, **kwargs):
419
+ return _rate_limit_impl(func, calls, period, call_times, *args, **kwargs)
420
+ return wrapper
421
+ return decorator
422
+
423
+ def _mock_data_impl(func, data, *args, **kwargs):
424
+ """Implementation of mock_data functionality."""
425
+ return data() if callable(data) else data
426
+
427
+ def mock_data(data: Any):
428
+ """
429
+ Replaces a function's output with mock data, useful for testing.
430
+ Can be used as a decorator or function:
431
+
432
+ @mock_data(42)
433
+ def func(): pass
434
+
435
+ # or
436
+ result = mock_data(42)(func)()
437
+ """
438
+ def decorator(func):
439
+ @functools.wraps(func)
440
+ def wrapper(*args, **kwargs):
441
+ return _mock_data_impl(func, data, *args, **kwargs)
442
+ return wrapper
443
+ return decorator
444
+
445
+ def _benchmark_impl(func, *args, **kwargs):
446
+ """Implementation of benchmark functionality."""
447
+ times = []
448
+ for _ in range(3): # Run 3 times for averaging
449
+ start_time = time.time()
450
+ result = func(*args, **kwargs)
451
+ end_time = time.time()
452
+ times.append(end_time - start_time)
453
+ avg_time = sum(times) / len(times)
454
+ logger.info(f"Benchmark {func.__name__}: avg={avg_time:.4f}s over {len(times)} runs")
455
+ return result
456
+
457
+ def benchmark(func: Union[Callable, None] = None) -> Callable:
458
+ """
459
+ Compares the execution times of different functions.
460
+ Can be used as a decorator or function:
461
+
462
+ @benchmark
463
+ def func(): pass
464
+
465
+ # or
466
+ result = benchmark(func)()
467
+ """
468
+ if func is None:
469
+ return benchmark
470
+
471
+ @functools.wraps(func)
472
+ def wrapper(*args, **kwargs):
473
+ return _benchmark_impl(func, *args, **kwargs)
474
+ return wrapper
475
+
476
+ def _run_in_thread_impl(func, *args, **kwargs):
477
+ """Implementation of run_in_thread functionality."""
478
+ thread = threading.Thread(target=func, args=args, kwargs=kwargs)
479
+ thread.start()
480
+ return thread
481
+
482
+ def run_in_thread(func: Union[Callable, None] = None) -> Callable:
483
+ """
484
+ Executes a function asynchronously in a separate thread.
485
+ Can be used as a decorator or function:
486
+
487
+ @run_in_thread
488
+ def func(): pass
489
+
490
+ # or
491
+ result = run_in_thread(func)()
492
+ """
493
+ if func is None:
494
+ return run_in_thread
495
+
496
+ @functools.wraps(func)
497
+ def wrapper(*args, **kwargs):
498
+ return _run_in_thread_impl(func, *args, **kwargs)
499
+ return wrapper
500
+
501
+ def _no_debug_impl(func, *args, **kwargs):
502
+ """Implementation of no_debug functionality."""
503
+ current_level = logger.getEffectiveLevel()
504
+ logger.setLevel(logging.INFO)
505
+ try:
506
+ return func(*args, **kwargs)
507
+ finally:
508
+ logger.setLevel(current_level)
509
+
510
+ def no_debug(func: Union[Callable, None] = None) -> Callable:
511
+ """
512
+ Disables debug output in production environments.
513
+ Can be used as a decorator or function:
514
+
515
+ @no_debug
516
+ def func(): pass
517
+
518
+ # or
519
+ result = no_debug(func)()
520
+ """
521
+ if func is None:
522
+ return no_debug
523
+
524
+ @functools.wraps(func)
525
+ def wrapper(*args, **kwargs):
526
+ return _no_debug_impl(func, *args, **kwargs)
527
+ return wrapper
528
+
529
+ def _transactional_impl(func, changes, *args, **kwargs):
530
+ """Implementation of transactional functionality."""
531
+ try:
532
+ result = func(*args, **kwargs)
533
+ return result
534
+ except Exception:
535
+ for change in reversed(changes):
536
+ change.rollback()
537
+ raise
538
+
539
+ def transactional(func: Union[Callable, None] = None) -> Callable:
540
+ """
541
+ Ensures that function changes are committed or rolled back atomically.
542
+ Can be used as a decorator or function:
543
+
544
+ @transactional
545
+ def func(): pass
546
+
547
+ # or
548
+ result = transactional(func)()
549
+ """
550
+ if func is None:
551
+ return transactional
552
+
553
+ @functools.wraps(func)
554
+ def wrapper(*args, **kwargs):
555
+ changes = []
556
+ return _transactional_impl(func, changes, *args, **kwargs)
557
+ return wrapper
558
+
559
+ def _revert_on_failure_impl(func, state, *args, **kwargs):
560
+ """Implementation of revert_on_failure functionality."""
561
+ try:
562
+ return func(*args, **kwargs)
563
+ except Exception:
564
+ # Restore initial state
565
+ for key, value in state.items():
566
+ setattr(args[0], key, value)
567
+ raise
568
+
569
+ def revert_on_failure(func: Union[Callable, None] = None) -> Callable:
570
+ """
571
+ Reverts all changes made by the function if an exception occurs.
572
+ Can be used as a decorator or function:
573
+
574
+ @revert_on_failure
575
+ def func(): pass
576
+
577
+ # or
578
+ result = revert_on_failure(func)()
579
+ """
580
+ if func is None:
581
+ return revert_on_failure
582
+
583
+ @functools.wraps(func)
584
+ def wrapper(*args, **kwargs):
585
+ state = {} # Store initial state
586
+ return _revert_on_failure_impl(func, state, *args, **kwargs)
587
+ return wrapper
588
+
589
+ def _audit_impl(func, *args, **kwargs):
590
+ """Implementation of audit functionality."""
591
+ timestamp = datetime.now()
592
+ caller_frame = inspect.currentframe().f_back
593
+ caller_info = f"{caller_frame.f_code.co_filename}:{caller_frame.f_lineno}"
594
+
595
+ audit_data = {
596
+ "function": func.__name__,
597
+ "timestamp": timestamp,
598
+ "caller": caller_info,
599
+ "args": args,
600
+ "kwargs": kwargs
601
+ }
602
+
603
+ try:
604
+ result = func(*args, **kwargs)
605
+ audit_data["status"] = "success"
606
+ audit_data["result"] = result
607
+ return result
608
+ except Exception as e:
609
+ audit_data["status"] = "error"
610
+ audit_data["error"] = str(e)
611
+ raise
612
+ finally:
613
+ logger.info(f"Audit log: {audit_data}")
614
+
615
+ def audit(func: Union[Callable, None] = None) -> Callable:
616
+ """
617
+ Audits and logs function calls with metadata.
618
+ Can be used as a decorator or function:
619
+
620
+ @audit
621
+ def func(): pass
622
+
623
+ # or
624
+ result = audit(func)()
625
+ """
626
+ if func is None:
627
+ return audit
628
+
629
+ @functools.wraps(func)
630
+ def wrapper(*args, **kwargs):
631
+ return _audit_impl(func, *args, **kwargs)
632
+ return wrapper
633
+
634
+ def _trace_impl(func, *args, **kwargs):
635
+ """Implementation of trace functionality."""
636
+ stack = traceback.extract_stack()[:-1] # Exclude current frame
637
+ logger.debug(f"Call trace for {func.__name__}:")
638
+ for filename, lineno, name, line in stack:
639
+ logger.debug(f" File {filename}, line {lineno}, in {name}")
640
+ if line:
641
+ logger.debug(f" {line.strip()}")
642
+ return func(*args, **kwargs)
643
+
644
+ def trace(func: Union[Callable, None] = None) -> Callable:
645
+ """
646
+ Logs function calls, including call stack traces for debugging.
647
+ Can be used as a decorator or function:
648
+
649
+ @trace
650
+ def func(): pass
651
+
652
+ # or
653
+ result = trace(func)()
654
+ """
655
+ if func is None:
656
+ return trace
657
+
658
+ @functools.wraps(func)
659
+ def wrapper(*args, **kwargs):
660
+ return _trace_impl(func, *args, **kwargs)
661
+ return wrapper
662
+
663
+ def _timeout_impl(func, seconds, *args, **kwargs):
664
+ """Implementation of timeout functionality."""
665
+ result = queue.Queue()
666
+
667
+ def target():
668
+ try:
669
+ result.put(func(*args, **kwargs))
670
+ except Exception as e:
671
+ result.put(e)
672
+
673
+ thread = threading.Thread(target=target)
674
+ thread.daemon = True
675
+ thread.start()
676
+ thread.join(seconds)
677
+
678
+ if thread.is_alive():
679
+ raise TimeoutError(f"Function {func.__name__} timed out after {seconds} seconds")
680
+
681
+ value = result.get()
682
+ if isinstance(value, Exception):
683
+ raise value
684
+ return value
685
+
686
+ def timeout(seconds: int):
687
+ """
688
+ Sets a timeout limit on function execution.
689
+ Can be used as a decorator or function:
690
+
691
+ @timeout(5)
692
+ def func(): pass
693
+
694
+ # or
695
+ result = timeout(5)(func)()
696
+ """
697
+ def decorator(func):
698
+ @functools.wraps(func)
699
+ def wrapper(*args, **kwargs):
700
+ return _timeout_impl(func, seconds, *args, **kwargs)
701
+ return wrapper
702
+ return decorator