Skip to content

Commit 4d1d661

Browse files
Merge pull request #9 from hmohammad2520-org/HMohammad2520/1-add-readme
2 parents 91f5b7c + 5bd36d5 commit 4d1d661

3 files changed

Lines changed: 155 additions & 2 deletions

File tree

README.md

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
# classmods
2+
3+
`classmods` is a lightweight Python package designed to enhance class behavior with minimal effort. It provides modular decorators and descriptors to automate and simplify class-related tasks like environment variable management, creating example env files, monitoring, logging, and more.
4+
5+
# Documentation
6+
7+
All features are well documented and use a high level of `type_hints` for easy understanding and usage.
8+
9+
## Features
10+
11+
* `ConstantAttrib`: A descriptor that acts like a constant. Once set, the value cannot be changed. Raises `AttributeError` on change detection.
12+
* `RemoteAttrib`: A descriptor that acts as a remote attribute. You can modify the mapped value on-the-fly.
13+
* `ENVMod`: The main API class for managing `.env` variables. Supports manual and decorator-based registration of environment items, type-safe value loading, and `.env_example` generation.
14+
* `MethodMonitor`: A class to monitor method calls of a target class, triggering a handler function after the method is called.
15+
* `logwrap`: A dynamic decorator to log function calls. Uses the `logging` module with your current project configurations.
16+
* `suppress_errors`: A decorator that suppresses exceptions raised by the wrapped function and returns a fallback value instead.
17+
18+
## Installation
19+
20+
1. Easy install with pip
21+
22+
```bash
23+
pip install classmods
24+
```
25+
26+
2. Install with git+pip
27+
28+
```bash
29+
pip install git+https://github.com/hmohammad2520-org/classmods
30+
```
31+
32+
## Examples
33+
34+
### Constant Attribute
35+
36+
```python
37+
from classmods import ConstantAttrib
38+
39+
class Config:
40+
app_name = ConstantAttrib[str]()
41+
42+
def __init__(self, app_name):
43+
self.app_name = app_name
44+
45+
config = Config('new app')
46+
config.app_name = 'my app' # This will raise AttributeError
47+
```
48+
49+
### Remote Attribute
50+
51+
```python
52+
import requests
53+
from classmods import RemoteAttrib
54+
55+
class Config:
56+
token = RemoteAttrib[str](
57+
get=lambda: requests.get("https://api.example.com/auth").json()["token"],
58+
cache_timeout=10, # keeps result for 10 seconds
59+
)
60+
61+
config = Config()
62+
token = config.token # This will send a request and return the result
63+
```
64+
65+
### ENVMod
66+
67+
```python
68+
from os import PathLike
69+
from requests import Session
70+
from classmods import ENVMod
71+
72+
class Config:
73+
ENVMod.register(exclude=['session'], cast={'log_path': str})
74+
def __init__(
75+
self,
76+
app_name: str,
77+
session: Session, # Excluded non-parsable object
78+
log_path: PathLike,
79+
log_level: Optional[str] = None,
80+
port: int = 10,
81+
):
82+
'''
83+
Args:
84+
app_name (str): Application name.
85+
session (Session): Requests session.
86+
log_path (PathLike): Path of log file.
87+
log_level (Optional[str]): Log level, e.g., info.
88+
port (int): Session port, defaults to 10.
89+
'''
90+
91+
ENVMod.save_example('.my_example_path')
92+
ENVMod.load_dotenv('.my_env')
93+
ENVMod.sync_env_file('.my_env')
94+
config = Config(**ENVMod.load_args(Config.__init__), session=Session())
95+
```
96+
97+
### Method Monitor
98+
99+
```python
100+
from classmods import MethodMonitor
101+
102+
class MyClass:
103+
def my_method(self):
104+
pass
105+
106+
def my_handler(instance):
107+
print(f"Monitor triggered on {instance}")
108+
109+
monitor = MethodMonitor(MyClass, my_handler, target_method='my_method')
110+
obj = MyClass()
111+
obj.my_method()
112+
```
113+
114+
### logwrap
115+
116+
```python
117+
from classmods import logwrap
118+
119+
@logwrap(before=('INFO', '{func} starting, args={args} kwargs={kwargs}'), after=('INFO', '{func} ended'))
120+
def my_func(my_arg, my_kwarg=None):
121+
...
122+
123+
my_func('hello', my_kwarg=123) # Check logs to see the output
124+
```
125+
126+
### Suppress Errors
127+
128+
```python
129+
from classmods import suppress_errors
130+
131+
@suppress_errors(Exception)
132+
def risky_op() -> int:
133+
return 1 / 0
134+
135+
result = risky_op() # result = ZeroDivisionError
136+
137+
@suppress_errors(False)
138+
def safe_op() -> bool:
139+
raise ValueError("error")
140+
141+
result = safe_op() # result = False
142+
```
143+
144+
## License
145+
146+
MIT License
147+
148+
---
149+
150+
Made with ❤️ by [hmohammad2520](https://github.com/hmohammad2520-org)

classmods/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@
99
'get_version',
1010
'ConstantAttrib',
1111
'RemoteAttrib',
12-
'logwrap',
13-
'suppress_errors',
1412
'ENVMod',
1513
'MethodMonitor',
14+
'logwrap',
15+
'suppress_errors',
1616
]

classmods/_env_mod.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,9 @@ def load_args(cls, func: Callable) -> Dict[str, Any]:
303303
def save_example(cls, path: str = ".env_example") -> None:
304304
"""
305305
Save an example .env file based on all registered items.
306+
307+
WARNING: Do not store your values in the example file,
308+
it gets overwritten on secound execution.
306309
"""
307310
cls._envfile._save_as_file(path)
308311

0 commit comments

Comments
 (0)