Skip to content

Commit 54ffdcd

Browse files
committed
move async_logger, AsyncQueueListener, LogHelper, RotatingFileWriter, and SizedTimedRotatingFileHandler from morebuiltins.funcs to morebuiltins.logs
1 parent d0e8242 commit 54ffdcd

File tree

8 files changed

+850
-914
lines changed

8 files changed

+850
-914
lines changed

CHANGELOG.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
1+
## Changelog
2+
13
### 1.3.2 (2025-08-02)
24
1. fix typing-hint for `morebuiltins.funcs.threads` decorator, now it returns `Callable[..., Future]`.
35
2. add force kill methods to `morebuiltins.shared_memory.PLock`:
46
1. add `force_signum` to `morebuiltins.shared_memory.PLock`, to specify the signal number to force kill the process if it exists.
57
2. add `is_free` to `morebuiltins.shared_memory.PLock`, to check if the lock is free.
68
3. add `kill_with_name` to `morebuiltins.shared_memory.PLock`, to kill the process with the given name and signal number.
7-
3. add `morebuiltins.funcs.LogHelper` to quickly bind a logging handler to a logger, with a StreamHandler or SizedTimedRotatingFileHandler.
9+
3. add `morebuiltins.logs.LogHelper` to quickly bind a logging handler to a logger, with a StreamHandler or SizedTimedRotatingFileHandler.
10+
4. **Compatibility Warnings**:
11+
1. move `async_logger`, `AsyncQueueListener`, `LogHelper`, `RotatingFileWriter`, and `SizedTimedRotatingFileHandler` from `morebuiltins.funcs` to `morebuiltins.logs`.
812

913
### 1.3.1 (2025-06-19)
1014
1. add `check_recursion` to `morebuiltins.funcs`, to check if a function is recursive.

README.md

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,12 @@ This project enhances Python’s built-ins with extra functionality, prioritizin
1616
- Minimal Dependencies: Designed to avoid third-party libraries for seamless integration, conflict prevention, and easy packaging via zipapp for pyz distribution.
1717
ibution.
1818

19+
## Compatibility Break Warnings
20+
1. **1.3.2 (2025-08-02)**
21+
1. move `async_logger`, `AsyncQueueListener`, `LogHelper`, `RotatingFileWriter`, and `SizedTimedRotatingFileHandler` from `morebuiltins.funcs` to `morebuiltins.logs`.
22+
2. **1.3.0 (2025-03-08)**
23+
1. rename `morebuiltins.functools` to `morebuiltins.funcs` to avoid conflict with `functools` in python standard library.
24+
1925
## Install
2026

2127
- From [pypi.org](https://pypi.org/project/morebuiltins/)
@@ -157,23 +163,17 @@ print(morebuiltins.__file__)
157163

158164
3.6 `InlinePB` - Inline progress bar.
159165

160-
3.7 `SizedTimedRotatingFileHandler` - TimedRotatingFileHandler with maxSize, to avoid files that are too large.
161-
162-
3.8 `get_type_default` - Get the default value for a type. {int: 0, float: 0.0, bytes: b"", str: "", list: [], tuple: (), set: set(), dict: {}}
163-
164-
3.9 `func_cmd` - Handle function with argparse, typing-hint is nessessary.
165-
166-
3.10 `file_import` - Import function from file path.
166+
3.7 `get_type_default` - Get the default value for a type. {int: 0, float: 0.0, bytes: b"", str: "", list: [], tuple: (), set: set(), dict: {}}
167167

168-
3.11 `RotatingFileWriter` - RotatingFileWriter class for writing to a file with rotation support.
168+
3.8 `func_cmd` - Handle function with argparse, typing-hint is nessessary.
169169

170-
3.12 `get_function` - Get the function object from entrypoint.
170+
3.9 `file_import` - Import function from file path.
171171

172-
3.13 `to_thread` - Asynchronously run function *func* in a separate thread, same as `asyncio.to_thread` in python 3.9+.
172+
3.10 `get_function` - Get the function object from entrypoint.
173173

174-
3.14 `check_recursion` - Check if a function is recursive by inspecting its AST.
174+
3.11 `to_thread` - Asynchronously run function *func* in a separate thread, same as `asyncio.to_thread` in python 3.9+.
175175

176-
3.15 `LogHelper` - Quickly bind a logging handler to a logger, with a StreamHandler or SizedTimedRotatingFileHandler.
176+
3.12 `check_recursion` - Check if a function is recursive by inspecting its AST.
177177

178178

179179
## 4. morebuiltins.ipc

doc.md

Lines changed: 9 additions & 147 deletions
Original file line numberDiff line numberDiff line change
@@ -625,7 +625,9 @@ True if the process is running; False otherwise.
625625
Examples:
626626
>>> is_running(os.getpid() * 10) # Assume process is not running
627627
False
628-
>>> is_running(os.getpid()) # Check if the current process is running
628+
>>> current_pid = os.getpid()
629+
>>> # sometimes may return False on Windows due to permission issues!
630+
>>> is_running(current_pid) or is_running(current_pid) # Check if the current process is running
629631
True
630632
>>> is_running("not_a_pid") # Invalid PID input should be handled and return False
631633
False
@@ -1637,56 +1639,7 @@ Demo::
16371639

16381640

16391641

1640-
3.7 `SizedTimedRotatingFileHandler` - TimedRotatingFileHandler with maxSize, to avoid files that are too large.
1641-
1642-
1643-
```python
1644-
1645-
1646-
Demo::
1647-
1648-
import logging
1649-
import time
1650-
from morebuiltins.funcs import SizedTimedRotatingFileHandler
1651-
1652-
logger = logging.getLogger("test1")
1653-
h = SizedTimedRotatingFileHandler(
1654-
"logs/test1.log", "d", 1, 3, maxBytes=1, ensure_dir=True
1655-
)
1656-
h.setFormatter(logging.Formatter("%(asctime)s %(levelname)s %(message)s"))
1657-
logger.addHandler(h)
1658-
1659-
for i in range(5):
1660-
logger.warning(str(i) * 102400)
1661-
time.sleep(1)
1662-
# 102434 test1.log
1663-
# 102434 test1.log.20241113_231000
1664-
# 102434 test1.log.20241113_231001
1665-
# 102434 test1.log.20241113_231002
1666-
logger = logging.getLogger("test2")
1667-
h = SizedTimedRotatingFileHandler(
1668-
"logs/test2.log", "d", 1, 3, maxBytes=1, compress=True
1669-
)
1670-
h.setFormatter(logging.Formatter("%(asctime)s %(levelname)s %(message)s"))
1671-
logger.addHandler(h)
1672-
1673-
for i in range(5):
1674-
logger.warning(str(i) * 102400)
1675-
time.sleep(1)
1676-
# 102434 test2.log
1677-
# 186 test2.log.20241113_231005.gz
1678-
# 186 test2.log.20241113_231006.gz
1679-
# 186 test2.log.20241113_231007.gz
1680-
1681-
1682-
```
1683-
1684-
1685-
---
1686-
1687-
1688-
1689-
3.8 `get_type_default` - Get the default value for a type. {int: 0, float: 0.0, bytes: b"", str: "", list: [], tuple: (), set: set(), dict: {}}
1642+
3.7 `get_type_default` - Get the default value for a type. {int: 0, float: 0.0, bytes: b"", str: "", list: [], tuple: (), set: set(), dict: {}}
16901643

16911644

16921645

@@ -1696,7 +1649,7 @@ Demo::
16961649

16971650

16981651

1699-
3.9 `func_cmd` - Handle function with argparse, typing-hint is nessessary.
1652+
3.8 `func_cmd` - Handle function with argparse, typing-hint is nessessary.
17001653

17011654

17021655
```python
@@ -1766,7 +1719,7 @@ Demo::
17661719

17671720

17681721

1769-
3.10 `file_import` - Import function from file path.
1722+
3.9 `file_import` - Import function from file path.
17701723

17711724

17721725
```python
@@ -1784,70 +1737,7 @@ Demo::
17841737

17851738

17861739

1787-
3.11 `RotatingFileWriter` - RotatingFileWriter class for writing to a file with rotation support.
1788-
1789-
1790-
```python
1791-
1792-
Demo::
1793-
1794-
>>> # test normal usage
1795-
>>> writer = RotatingFileWriter("test.log", max_size=10 * 1024, max_backups=1)
1796-
>>> writer.write("1" * 10)
1797-
>>> writer.path.stat().st_size
1798-
0
1799-
>>> writer.flush()
1800-
>>> writer.path.stat().st_size
1801-
10
1802-
>>> writer.clean_backups(writer.max_backups)
1803-
>>> writer.unlink_file()
1804-
>>> # test rotating
1805-
>>> writer = RotatingFileWriter("test.log", max_size=20, max_backups=2)
1806-
>>> writer.write("1" * 15)
1807-
>>> writer.write("1" * 15)
1808-
>>> writer.write("1" * 15, flush=True)
1809-
>>> writer.path.stat().st_size
1810-
15
1811-
>>> len(writer.backup_path_list())
1812-
2
1813-
>>> writer.clean_backups(writer.max_backups)
1814-
>>> writer.unlink_file()
1815-
>>> # test no backups
1816-
>>> writer = RotatingFileWriter("test.log", max_size=20, max_backups=0)
1817-
>>> writer.write("1" * 15)
1818-
>>> writer.write("1" * 15)
1819-
>>> writer.write("1" * 15, flush=True)
1820-
>>> writer.path.stat().st_size
1821-
15
1822-
>>> len(writer.backup_path_list())
1823-
0
1824-
>>> writer.clean_backups(writer.max_backups)
1825-
>>> len(writer.backup_path_list())
1826-
0
1827-
>>> writer = RotatingFileWriter("test.log", max_size=20, max_backups=3)
1828-
>>> writer.print("1" * 100)
1829-
>>> writer.unlink(rotate=False)
1830-
>>> len(writer.backup_path_list())
1831-
1
1832-
>>> writer.unlink(rotate=True)
1833-
>>> len(writer.backup_path_list())
1834-
0
1835-
>>> writer = RotatingFileWriter("test.log", max_size=20, max_backups=3, compress=True)
1836-
>>> writer.print("1" * 100)
1837-
>>> len(writer.backup_path_list())
1838-
1
1839-
>>> writer.unlink(rotate=True)
1840-
>>> len(writer.backup_path_list())
1841-
0
1842-
1843-
```
1844-
1845-
1846-
---
1847-
1848-
1849-
1850-
3.12 `get_function` - Get the function object from entrypoint.
1740+
3.10 `get_function` - Get the function object from entrypoint.
18511741

18521742

18531743
```python
@@ -1864,7 +1754,7 @@ Demo::
18641754

18651755

18661756

1867-
3.13 `to_thread` - Asynchronously run function *func* in a separate thread, same as `asyncio.to_thread` in python 3.9+.
1757+
3.11 `to_thread` - Asynchronously run function *func* in a separate thread, same as `asyncio.to_thread` in python 3.9+.
18681758

18691759

18701760

@@ -1874,7 +1764,7 @@ Demo::
18741764

18751765

18761766

1877-
3.14 `check_recursion` - Check if a function is recursive by inspecting its AST.
1767+
3.12 `check_recursion` - Check if a function is recursive by inspecting its AST.
18781768

18791769

18801770
```python
@@ -1900,34 +1790,6 @@ Demo::
19001790
---
19011791

19021792

1903-
1904-
3.15 `LogHelper` - Quickly bind a logging handler to a logger, with a StreamHandler or SizedTimedRotatingFileHandler.
1905-
1906-
1907-
```python
1908-
1909-
The default handler is a StreamHandler to sys.stderr.
1910-
The default file handler is a SizedTimedRotatingFileHandler, which can rotate logs by both time and size.
1911-
1912-
Examples::
1913-
1914-
import logging
1915-
from morebuiltins.log import LogHelper
1916-
1917-
LogHelper.shorten_level()
1918-
logger = LogHelper.bind_handler(name="mylogger", filename=sys.stdout, maxBytes=100 * 1024**2, backupCount=7)
1919-
# use logging.getLogger to get the same logger instance
1920-
logger2 = logging.getLogger("mylogger")
1921-
assert logger is logger2
1922-
logger.info("This is an info message")
1923-
logger.fatal("This is a critical message")
1924-
1925-
```
1926-
1927-
1928-
---
1929-
1930-
19311793
## 4. morebuiltins.ipc
19321794

19331795

morebuiltins/cmd/log_server.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
from pathlib import Path
1212
from queue import Empty, Queue
1313

14-
from ..funcs import RotatingFileWriter
14+
from ..logs import RotatingFileWriter
1515
from ..ipc import SocketLogHandlerEncoder, SocketServer
1616
from ..utils import format_error, read_size, ttime
1717

@@ -310,7 +310,8 @@ def handle_signal(self, sig, frame):
310310
self.send_log(msg)
311311
self.shutdown()
312312
self._write_queue.put(self.STOP_SIG)
313-
self.loop.call_soon_threadsafe(self._shutdown_ev.set)
313+
if self._shutdown_ev:
314+
self.loop.call_soon_threadsafe(self._shutdown_ev.set)
314315

315316
def __del__(self):
316317
for f in self._opened_files.values():

0 commit comments

Comments
 (0)