@@ -65,42 +65,6 @@ def test_project_logger_with_filepath():
6565 assert isinstance (logger , logging .Logger )
6666
6767
68- def test_project_logger_with_complex_filepath ():
69- # Arrange
70- filepath = '/very/long/path/to/some/complex_module_name.py'
71-
72- # Act
73- logger = project_logger (filepath )
74-
75- # Assert
76- assert logger .name == 'ibind.complex_module_name'
77- assert isinstance (logger , logging .Logger )
78-
79-
80- def test_project_logger_with_pathlib_path ():
81- # Arrange
82- filepath = Path ('/path/to/module.py' )
83-
84- # Act
85- logger = project_logger (str (filepath ))
86-
87- # Assert
88- assert logger .name == 'ibind.module'
89- assert isinstance (logger , logging .Logger )
90-
91-
92- def test_project_logger_with_no_extension ():
93- # Arrange
94- filepath = '/path/to/module'
95-
96- # Act
97- logger = project_logger (filepath )
98-
99- # Assert
100- assert logger .name == 'ibind.module'
101- assert isinstance (logger , logging .Logger )
102-
103-
10468@patch ('ibind.support.logs.var.LOG_TO_CONSOLE' , True )
10569@patch ('ibind.support.logs.var.LOG_TO_FILE' , False )
10670@patch ('ibind.support.logs.var.LOG_LEVEL' , 'DEBUG' )
@@ -211,27 +175,28 @@ def test_ibind_logs_initialize_disables_file_logging(reset_logging_state):
211175 assert not fh_logger .filters [0 ](test_record )
212176
213177
214- @patch ('ibind.support.logs._LOGGER' )
215- def test_new_daily_rotating_file_handler_with_file_logging (mock_logger , reset_logging_state ):
178+ def test_new_daily_rotating_file_handler_with_file_logging (reset_logging_state ):
216179 # Arrange
217180 import ibind .support .logs
218181 ibind .support .logs ._log_to_file = True
219182 logger_name = 'test_logger'
220183 filepath = '/tmp/test.log' # noqa: S108
221184
222- # Act
223- with patch ('ibind.support.logs.DailyRotatingFileHandler' ) as mock_handler_class :
224- mock_handler = MagicMock ()
225- mock_handler_class .return_value = mock_handler
185+ # Mock only file operations, not the handler itself
186+ with patch ('builtins.open' , mock_open ()), \
187+ patch ( 'ibind.support.logs.Path' ) as mock_path :
188+ mock_path .return_value . parent . mkdir = MagicMock ()
226189
190+ # Act - Test real DailyRotatingFileHandler behavior
227191 logger = new_daily_rotating_file_handler (logger_name , filepath )
228192
229193 # Assert
230194 assert logger .name == 'ibind_fh.test_logger'
231195 assert logger .level == logging .DEBUG
232- mock_logger .info .assert_called_once ()
233- assert 'test_logger' in mock_logger .info .call_args [0 ][0 ]
234- assert filepath in mock_logger .info .call_args [0 ][0 ]
196+ # Verify logger has real DailyRotatingFileHandler
197+ assert len (logger .handlers ) == 1
198+ assert isinstance (logger .handlers [0 ], DailyRotatingFileHandler )
199+ assert logger .handlers [0 ].baseFilename == filepath
235200
236201
237202def test_new_daily_rotating_file_handler_without_file_logging (reset_logging_state ):
@@ -286,140 +251,66 @@ def test_daily_rotating_file_handler_initialization():
286251 assert handler .date_format == '%Y-%m-%d'
287252
288253
289- def test_daily_rotating_file_handler_custom_date_format ():
254+ def test_daily_rotating_file_handler_open ():
290255 # Arrange
291256 base_filename = '/tmp/test.log' # noqa: S108
292- custom_format = '%Y%m%d'
293-
294- # Act
295- handler = DailyRotatingFileHandler (base_filename , date_format = custom_format )
296-
297- # Assert
298- assert handler .date_format == custom_format
299-
300-
301- @patch ('ibind.support.logs.datetime' )
302- def test_daily_rotating_file_handler_get_timestamp (mock_datetime ):
303- # Arrange
304- mock_now = MagicMock ()
305- mock_now .strftime .return_value = '2024-01-15'
306- mock_datetime .datetime .now .return_value = mock_now
307- mock_datetime .timezone .utc = datetime .timezone .utc
308-
309- with patch ('builtins.open' , mock_open ()):
310- handler = DailyRotatingFileHandler ('/tmp/test.log' ) # noqa: S108 # noqa: S108
311-
312- # Act
313- timestamp = handler .get_timestamp ()
314257
315- # Assert
316- assert timestamp == '2024-01-15'
317- # Note: datetime.now gets called during initialization too, so we check if it was called
318- assert mock_datetime .datetime .now .call_count >= 1
319- mock_now .strftime .assert_called_with ('%Y-%m-%d' )
320-
321-
322- def test_daily_rotating_file_handler_get_filename ():
323- # Arrange
324- handler = DailyRotatingFileHandler ('/tmp/test.log' ) # noqa: S108
325- timestamp = '2024-01-15'
326-
327- # Act
328- filename = handler .get_filename (timestamp )
329-
330- # Assert
331- assert filename == '/tmp/test.log__2024-01-15.txt' # noqa: S108
332-
333-
334- @patch ('ibind.support.logs.Path' )
335- @patch ('builtins.open' , new_callable = mock_open )
336- def test_daily_rotating_file_handler_open (mock_file_open , mock_path ):
337- # Arrange
338- mock_path .return_value .parent .mkdir = MagicMock ()
339-
340- with patch ('builtins.open' , mock_open ()):
341- handler = DailyRotatingFileHandler ('/tmp/test.log' ) # noqa: S108 # noqa: S108
342-
343- with patch .object (handler , 'get_timestamp' , return_value = '2024-01-15' ):
344- # Act
345- handler ._open ()
258+ # Mock only file operations and Path.mkdir, not the entire Path class
259+ with patch ('builtins.open' , mock_open ()) as mock_file_open , \
260+ patch ('pathlib.Path.mkdir' ) as mock_mkdir :
261+
262+ handler = DailyRotatingFileHandler (base_filename )
263+
264+ # Test real get_timestamp behavior by using a fixed date
265+ with patch .object (handler , 'get_timestamp' , return_value = '2024-01-15' ):
266+ # Act - Test real _open behavior
267+ file_obj = handler ._open ()
346268
347269 # Assert
348270 assert handler .timestamp == '2024-01-15'
349- # Path gets called during initialization and during _open
350271 expected_path = '/tmp/test.log__2024-01-15.txt' # noqa: S108
351- assert any (call [0 ][0 ] == expected_path for call in mock_path .call_args_list )
352- mock_path .return_value .parent .mkdir .assert_called_with (parents = True , exist_ok = True )
272+
273+ # Verify real get_filename behavior was used
274+ assert handler .get_filename ('2024-01-15' ) == expected_path
275+
276+ # Verify directory creation and file opening
277+ mock_mkdir .assert_called_with (parents = True , exist_ok = True )
353278 mock_file_open .assert_called_with (expected_path , 'a' , encoding = 'utf-8' )
354279
355280
356- @patch ('ibind.support.logs.Path' )
357- @patch ('builtins.open' , new_callable = mock_open )
358- def test_daily_rotating_file_handler_emit_same_day (mock_file_open , mock_path ):
281+ def test_daily_rotating_file_handler_emit_rotation ():
359282 # Arrange
360- handler = DailyRotatingFileHandler ('/tmp/test.log' ) # noqa: S108
361- handler .timestamp = '2024-01-15'
362- mock_stream = MagicMock ()
363- handler .stream = mock_stream
364-
365- record = logging .LogRecord ('test' , logging .INFO , 'path' , 1 , 'Test message' , (), None )
366-
367- with patch .object (handler , 'get_timestamp' , return_value = '2024-01-15' ):
368- with patch ('logging.FileHandler.emit' ) as mock_super_emit :
369- # Act
283+ base_filename = '/tmp/test.log' # noqa: S108
284+
285+ with patch ('builtins.open' , mock_open ()) as mock_file_open , \
286+ patch ('pathlib.Path.mkdir' ) as mock_mkdir :
287+
288+ handler = DailyRotatingFileHandler (base_filename )
289+ handler .timestamp = '2024-01-15' # Set initial timestamp
290+
291+ # Create a mock stream to simulate file being open
292+ mock_stream = MagicMock ()
293+ handler .stream = mock_stream
294+
295+ # Create test log record
296+ record = logging .LogRecord ('test' , logging .INFO , 'path' , 1 , 'test message' , (), None )
297+
298+ # Test case 1: Same timestamp - no rotation
299+ with patch .object (handler , 'get_timestamp' , return_value = '2024-01-15' ):
370300 handler .emit (record )
371-
372- # Assert
373- # Should not reopen file on same day
374- assert handler .stream is mock_stream
375- mock_super_emit .assert_called_once_with (record )
376-
377-
378- @patch ('ibind.support.logs.Path' )
379- @patch ('builtins.open' , new_callable = mock_open )
380- def test_daily_rotating_file_handler_emit_new_day (mock_file_open , mock_path ):
381- # Arrange
382- mock_path .return_value .parent .mkdir = MagicMock ()
383-
384- with patch ('builtins.open' , mock_open ()):
385- handler = DailyRotatingFileHandler ('/tmp/test.log' ) # noqa: S108 # noqa: S108
386-
387- handler .timestamp = '2024-01-15'
388- old_stream = MagicMock ()
389- handler .stream = old_stream
390-
391- record = logging .LogRecord ('test' , logging .INFO , 'path' , 1 , 'Test message' , (), None )
392-
393- with patch .object (handler , 'get_timestamp' , return_value = '2024-01-16' ):
394- with patch .object (handler , 'close' ) as mock_close :
395- with patch ('logging.FileHandler.emit' ) as mock_super_emit :
396- # Act
397- handler .emit (record )
398-
399- # Assert
400- # Should close old stream and open new one for new day
401- assert mock_close .call_count >= 1 # May be called during init and emit
402- assert handler .timestamp == '2024-01-16'
403- expected_path = '/tmp/test.log__2024-01-16.txt' # noqa: S108
404- mock_file_open .assert_called_with (expected_path , 'a' , encoding = 'utf-8' )
405- mock_super_emit .assert_called_once_with (record )
406-
407-
408- def test_daily_rotating_file_handler_emit_no_existing_stream ():
409- # Arrange
410- handler = DailyRotatingFileHandler ('/tmp/test.log' ) # noqa: S108
411- handler .stream = None
412- record = logging .LogRecord ('test' , logging .INFO , 'path' , 1 , 'Test message' , (), None )
413-
414- with patch .object (handler , 'get_timestamp' , return_value = '2024-01-15' ):
415- with patch .object (handler , '_open' , return_value = MagicMock ()) as mock_open_method :
416- with patch ('logging.FileHandler.emit' ) as mock_super_emit :
417- # Act
418- handler .emit (record )
419-
420- # Assert
421- mock_open_method .assert_called_once ()
422- mock_super_emit .assert_called_once_with (record )
301+
302+ # Should not have called close or _open
303+ mock_stream .close .assert_not_called ()
304+
305+ # Test case 2: Different timestamp - should rotate
306+ with patch .object (handler , 'get_timestamp' , return_value = '2024-01-16' ), \
307+ patch .object (handler , '_open' , return_value = MagicMock ()) as mock_open_method :
308+
309+ handler .emit (record )
310+
311+ # Should have closed old file and opened new one
312+ mock_stream .close .assert_called_once ()
313+ mock_open_method .assert_called_once ()
423314
424315
425316def test_default_format_constant ():
0 commit comments