This library provides a robust set of decorators for enhancing Python code functionality. It includes:
Project description
🎯 Python Advanced Decorators Library
A comprehensive collection of flexible and reusable decorators for functions, methods, and classes.
📑 Table of Contents
🔍 Overview
This library provides a robust set of decorators for enhancing Python code functionality. It includes:
- 🔧 Base decorator classes for extensibility
- 📊 Monitoring and logging capabilities
- 🔒 Validation and security features
- 💾 Caching and performance optimization
- 🏭 Support for both functions and classes
🚀 Installation
pip install ornator
🛠 Function & Method Decorators
Base Decorators
BeforeDecorator
Executes logic before the function call
from ornator import BeforeDecorator
class LoggingDecorator(BeforeDecorator):
def __init__(self):
super().__init__()
self.pre = self.log_call
def log_call(self, *args, **kwargs):
print(f"[LOG] Function call with: {args}, {kwargs}")
return args
logger = LoggingDecorator().before
@logger()
def process_data(data, pre=None):
return f"Processing: {data}"
AfterDecorator
Modifies the function's return value
from ornator import AfterDecorator
class ResponseTransformer(AfterDecorator):
def __init__(self):
super().__init__()
self.pos = self.transform_response
def transform_response(self, result, format="json"):
if format == "json":
return json.dumps(result)
return result
transformer = ResponseTransformer().after
@transformer(format="json")
def get_data():
return {"key": "value"}
DualDecorator
Executes logic before and after the function call
from ornator import DualDecorator
class PerformanceMonitor(DualDecorator):
def __init__(self):
super().__init__()
self.pre = self.start_timer
self.pos = self.end_timer
self.times = []
def start_timer(self, *args, **kwargs):
return time.time()
def end_timer(self, result, *args, **kwargs):
execution_time = time.time() - kwargs['pre']
self.times.append(execution_time)
return result
monitor = PerformanceMonitor().dual
@monitor()
def expensive_operation(pre):
time.sleep(1)
return "Done"
EmptyDecorator
Provides complete flexibility for custom logic
from ornator import EmptyDecorator
class Validator(EmptyDecorator):
def validate(self, func, *args, **kwargs):
if not args:
raise ValueError("Arguments required")
return func(*args, **kwargs)
validator = Validator().empty
@validator(handler=Validator().validate)
def process_data(*args):
return sum(args)
🏗 Class Decorators
Base Class Decorators
BeforeClassDecorator
Executes logic during class instantiation
from ornator import BeforeClassDecorator
class LoggingClassDecorator(BeforeClassDecorator):
def __init__(self):
super().__init__()
self.pre = self.log_instantiation
self._log = []
def log_instantiation(self, cls, *args, **kwargs):
log_entry = {
"timestamp": datetime.now(),
"class": cls.__name__,
"args": args
}
self._log.append(log_entry)
return log_entry
logger = LoggingClassDecorator().before
@logger()
class User:
def __init__(self, name):
self.name = name
AfterClassDecorator
Modifies the class after its definition
from ornator import AfterClassDecorator
class ValidationDecorator(AfterClassDecorator):
def __init__(self):
super().__init__()
self.pos = self.add_validation
def add_validation(self, cls):
original_init = cls.__init__
def validated_init(instance, *args, **kwargs):
for key, value in kwargs.items():
if not isinstance(value, cls.__annotations__.get(key, object)):
raise TypeError(f"Invalid type for {key}")
original_init(instance, *args, **kwargs)
cls.__init__ = validated_init
return cls
validator = ValidationDecorator().after
@validator()
class Person:
name: str
age: int
🌟 Examples
Real-World Use Cases
1. API Rate Limiting
from ornator import BeforeDecorator
import time
class RateLimiter(BeforeDecorator):
def __init__(self, calls_per_second=1):
super().__init__()
self.pre = self.check_rate
self.calls = []
self.calls_per_second = calls_per_second
def check_rate(self, *args, **kwargs):
now = time.time()
self.calls = [call for call in self.calls if now - call < 1.0]
if len(self.calls) >= self.calls_per_second:
raise Exception("Rate limit exceeded")
self.calls.append(now)
return args
limiter = RateLimiter(calls_per_second=2).before
@limiter()
def api_call(pre):
return "API response"
2. Caching with Expiration
from ornator import DualDecorator
from datetime import datetime, timedelta
class CacheWithExpiration(DualDecorator):
def __init__(self, expiration_minutes=60):
super().__init__()
self.pre = self.check_cache
self.pos = self.update_cache
self.cache = {}
self.expiration = expiration_minutes
def check_cache(self, *args, **kwargs):
key = str(args) + str(kwargs)
if key in self.cache:
value, timestamp = self.cache[key]
if datetime.now() - timestamp < timedelta(minutes=self.expiration):
return value
return None
def update_cache(self, result, *args, **kwargs):
key = str(args) + str(kwargs)
self.cache[key] = (result, datetime.now())
return result
cache = CacheWithExpiration(expiration_minutes=30).dual
@cache()
def expensive_computation(pre, x, y):
if pre is not None:
return pre
return x + y
🤝 Contributing
Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.
📄 License
This project is licensed under the MIT License - see the LICENSE file for details.
📚 Advanced Usage
Creating Custom Decorators
You can easily extend the base decorators to create your own:
class MyCustomDecorator(DualDecorator):
def __init__(self):
super().__init__()
self.pre = self.my_pre_logic
self.pos = self.my_post_logic
def my_pre_logic(self, *args, **kwargs):
# Your custom pre-execution logic
return modified_args
def my_post_logic(self, result, *args, **kwargs):
# Your custom post-execution logic
return modified_result
Chaining Decorators
Decorators can be chained for combined functionality:
@cache()
@validator()
@logger()
def complex_operation(*args, **kwargs):
return result
🔧 Configuration
Each decorator can be configured through its constructor or decorator arguments:
# Configure through constructor
logger = LoggingDecorator(log_level='DEBUG').before
# Configure through decorator
@logger(format='json', timestamp=True)
def my_function():
pass
📊 Performance Considerations
- Use
EmptyDecoratorfor maximum performance when custom logic is needed - Consider using
BeforeDecoratorinstead ofDualDecoratorwhen post-processing isn't required - Cache decorator results when appropriate
🚨 Error Handling
All decorators include built-in error handling and will raise appropriate exceptions:
TypeError: When invalid types are providedValueError: When required values are missingRuntimeError: For execution-related errors
💡 Best Practices
- Always extend from the appropriate base decorator
- Document your custom decorators
- Use type hints for better code clarity
- Follow the Single Responsibility Principle
- Test your decorators thoroughly
🔍 Debugging
To debug decorated functions:
import logging
logging.basicConfig(level=logging.DEBUG)
class DebugDecorator(BeforeDecorator):
def __init__(self):
super().__init__()
self.pre = self.debug_call
def debug_call(self, *args, **kwargs):
logging.debug(f"Function call: args={args}, kwargs={kwargs}")
return args
debug = DebugDecorator().before
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file ornator-0.0.4.tar.gz.
File metadata
- Download URL: ornator-0.0.4.tar.gz
- Upload date:
- Size: 6.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.11.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c96a076f275ceb6206ee63b1a9d350b377e32e49e3bc2b9ce0e24a27fc7e5642
|
|
| MD5 |
9e28e4a9b12b60842970bdc38b0257d3
|
|
| BLAKE2b-256 |
6ab79e9fd00d565a715181a42130fe1ab9a66cc0d554f76079710904a0e5ee34
|
File details
Details for the file ornator-0.0.4-py3-none-any.whl.
File metadata
- Download URL: ornator-0.0.4-py3-none-any.whl
- Upload date:
- Size: 7.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.11.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
83d1abf436372a9e4587b03bbcde65809117b8051e780e367aa7ade2712854dc
|
|
| MD5 |
2039bebbb30c575a3466ba1b6b021ea2
|
|
| BLAKE2b-256 |
da95cfe1875ba52e76dbdba225ac960eecf117a3ba0d9dfa2ec4df9d4f6967a9
|