Rotary Logger
1.0.2
The middleware rotary logger
Loading...
Searching...
No Matches
test_rotary_integration.py
Go to the documentation of this file.
1
"""
2
# +==== BEGIN rotary_logger =================+
3
# LOGO:
4
# ..........####...####..........
5
# ......###.....#.#########......
6
# ....##........#.###########....
7
# ...#..........#.############...
8
# ...#..........#.#####.######...
9
# ..#.....##....#.###..#...####..
10
# .#.....#.##...#.##..##########.
11
# #.....##########....##...######
12
# #.....#...##..#.##..####.######
13
# .#...##....##.#.##..###..#####.
14
# ..#.##......#.#.####...######..
15
# ..#...........#.#############..
16
# ..#...........#.#############..
17
# ...##.........#.############...
18
# ......#.......#.#########......
19
# .......#......#.########.......
20
# .........#####...#####.........
21
# /STOP
22
# PROJECT: rotary_logger
23
# FILE: test_rotary_integration.py
24
# CREATION DATE: 01-11-2025
25
# LAST Modified: 3:44:19 04-03-2026
26
# DESCRIPTION:
27
# A module that provides a universal python light on iops way of logging to files your program execution.
28
# /STOP
29
# COPYRIGHT: (c) Asperguide
30
# PURPOSE: This is the file in charge of making sure that the Rotary logger class works and does what is expected of it.
31
# // AR
32
# +==== END rotary_logger =================+
33
"""
34
import
sys
35
import
shutil
36
from
pathlib
import
Path
37
38
from
rotary_logger.rotary_logger_cls
import
RotaryLogger
39
40
41
def
test_start_logging_wires_and_writes
(tmp_path: Path) ->
None
:
42
parent = tmp_path
43
# Construct a FileInstance-backed TeeStream and write to it to verify
44
# that the wiring results in log files being created.
45
from
rotary_logger.file_instance
import
FileInstance
46
from
rotary_logger.tee_stream
import
TeeStream
47
48
orig = sys.stdout
49
try
:
50
fi = FileInstance(parent /
'logs.log'
, max_size_mb=1)
51
ts = TeeStream(fi, orig)
52
ts.write(
'integration test line\n'
)
53
ts.flush()
54
logs = list(parent.rglob(
'*.log'
))
55
assert
logs,
'No logs created by TeeStream/FileInstance'
56
content = logs[0].read_text(
57
encoding=fi.get_encoding(), errors=
'ignore'
)
58
assert
'integration test line'
in
content
59
finally
:
60
try
:
61
shutil.rmtree(parent)
62
except
Exception:
63
pass
64
65
66
def
test_destructor_safe_on_closed_files
(tmp_path: Path) ->
None
:
67
root = tmp_path /
'logs'
68
# Create and immediately close underlying streams to simulate shutdown
69
import
io
70
import
gc
71
orig = io.StringIO()
72
# create a TeeStream directly to test destructor
73
from
rotary_logger.tee_stream
import
TeeStream
74
ts = TeeStream(root, orig, max_size_mb=1)
75
# close underlying file descriptor (best-effort) and original stream
76
try
:
77
fi = getattr(ts,
"file_instance"
,
None
)
78
if
fi
and
fi.file
and
getattr(fi.file,
"descriptor"
,
None
):
79
try
:
80
fi.file.descriptor.close()
81
except
Exception:
82
pass
83
except
Exception:
84
pass
85
orig.close()
86
# deleting ts should not raise; collect to trigger __del__
87
del ts
88
gc.collect()
89
90
91
def
test_log_to_file_false_writes_no_content
(tmp_path: Path) ->
None
:
92
"""With log_to_file=False, no content should be written to any log file."""
93
SENTINEL =
"SENTINEL_MUST_NOT_APPEAR_IN_LOG_XYZ"
94
rl =
RotaryLogger
()
95
orig_out = sys.stdout
96
orig_err = sys.stderr
97
try
:
98
rl.start_logging(log_folder=tmp_path, merged=
True
, log_to_file=
False
)
99
sys.stdout.write(f
"{SENTINEL}\n"
)
100
try
:
101
sys.stdout.flush()
102
except
Exception:
103
pass
104
finally
:
105
sys.stdout = orig_out
106
sys.stderr = orig_err
107
108
for
log_file
in
tmp_path.rglob(
"*.log"
):
109
content = log_file.read_text(encoding=
"utf-8"
, errors=
"ignore"
)
110
assert
SENTINEL
not
in
content, (
111
f
"Sentinel unexpectedly logged to {log_file} when log_to_file=False"
112
)
113
114
115
def
test_stdout_prefix_appears_in_log
(tmp_path: Path) ->
None
:
116
"""When prefix_out_stream=True the [STDOUT] prefix should appear in the log."""
117
from
rotary_logger
import
constants
as
CONST
118
119
rl =
RotaryLogger
(prefix_out_stream=
True
)
120
orig_out = sys.stdout
121
orig_err = sys.stderr
122
try
:
123
rl.start_logging(log_folder=tmp_path, merged=
True
, log_to_file=
True
)
124
sys.stdout.write(
"prefixed line\n"
)
125
try
:
126
sys.stdout.flush()
127
except
Exception:
128
pass
129
finally
:
130
sys.stdout = orig_out
131
sys.stderr = orig_err
132
133
log_files = list(tmp_path.rglob(
"*.log"
))
134
assert
log_files,
"No log file was created"
135
content = log_files[0].read_text(encoding=
"utf-8"
)
136
assert
CONST.PREFIX_STDOUT
in
content, (
137
f
"Expected {CONST.PREFIX_STDOUT!r} in log, got: {content!r}"
138
)
rotary_logger.rotary_logger_cls.RotaryLogger
Definition
rotary_logger_cls.py:56
rotary_logger.file_instance
Definition
file_instance.py:1
rotary_logger.rotary_logger_cls
Definition
rotary_logger_cls.py:1
rotary_logger.tee_stream
Definition
tee_stream.py:1
tests.test_rotary_integration.test_start_logging_wires_and_writes
None test_start_logging_wires_and_writes(Path tmp_path)
Definition
test_rotary_integration.py:41
tests.test_rotary_integration.test_destructor_safe_on_closed_files
None test_destructor_safe_on_closed_files(Path tmp_path)
Definition
test_rotary_integration.py:66
tests.test_rotary_integration.test_log_to_file_false_writes_no_content
None test_log_to_file_false_writes_no_content(Path tmp_path)
Definition
test_rotary_integration.py:91
tests.test_rotary_integration.test_stdout_prefix_appears_in_log
None test_stdout_prefix_appears_in_log(Path tmp_path)
Definition
test_rotary_integration.py:115
tests
test_rotary_integration.py
Generated on Fri Mar 27 2026 11:28:32 for Rotary Logger by
1.12.0