1
+ import os
2
+ import unittest
3
+ import clr
4
+
5
+ # Import required .NET namespaces
6
+ clr .AddReference ("System" )
7
+ clr .AddReference ("System.IO" )
8
+ from System import IDisposable
9
+ from System .IO import MemoryStream , FileStream , FileMode , File , Path , StreamWriter
10
+
11
+ class DisposableContextManagerTests (unittest .TestCase ):
12
+ """Tests for Python's context manager protocol with .NET IDisposable objects"""
13
+
14
+ def test_memory_stream_context_manager (self ):
15
+ """Test that MemoryStream can be used as a context manager"""
16
+ data = bytes ([1 , 2 , 3 , 4 , 5 ])
17
+
18
+ # Using with statement with MemoryStream
19
+ with MemoryStream () as stream :
20
+ # Convert Python bytes to .NET byte array for proper writing
21
+ from System import Array , Byte
22
+ dotnet_bytes = Array [Byte ](data )
23
+ stream .Write (dotnet_bytes , 0 , len (dotnet_bytes ))
24
+
25
+ self .assertEqual (5 , stream .Length )
26
+ stream .Position = 0
27
+
28
+ # Create a .NET byte array to read into
29
+ buffer = Array [Byte ](5 )
30
+ stream .Read (buffer , 0 , 5 )
31
+
32
+ # Convert back to Python bytes for comparison
33
+ result = bytes (buffer )
34
+ self .assertEqual (data , result )
35
+
36
+ # The stream should be disposed (closed) after the with block
37
+ with self .assertRaises (Exception ):
38
+ stream .Position = 0 # This should fail because the stream is closed
39
+
40
+ def test_file_stream_context_manager (self ):
41
+ """Test that FileStream can be used as a context manager"""
42
+ # Create a temporary file path
43
+ temp_path = Path .Combine (Path .GetTempPath (), Path .GetRandomFileName ())
44
+
45
+ try :
46
+ # Write data to the file using with statement
47
+ data = "Hello, context manager!"
48
+ with FileStream (temp_path , FileMode .Create ) as fs :
49
+ writer = StreamWriter (fs )
50
+ writer .Write (data )
51
+ writer .Flush ()
52
+
53
+ # Verify the file was written and stream was closed
54
+ self .assertTrue (File .Exists (temp_path ))
55
+ content = File .ReadAllText (temp_path )
56
+ self .assertEqual (data , content )
57
+
58
+ # The stream should be disposed after the with block
59
+ with self .assertRaises (Exception ):
60
+ fs .Position = 0 # This should fail because the stream is closed
61
+ finally :
62
+ # Clean up
63
+ if File .Exists (temp_path ):
64
+ File .Delete (temp_path )
65
+
66
+ def test_disposable_in_multiple_contexts (self ):
67
+ """Test that using .NET IDisposable objects in multiple contexts works correctly"""
68
+ # Create multiple streams and check that they're all properly disposed
69
+
70
+ # Create a list to track if streams were properly disposed
71
+ # (we'll check this by trying to access the stream after disposal)
72
+ streams_disposed = [False , False ]
73
+
74
+ # Use nested context managers with .NET IDisposable objects
75
+ with MemoryStream () as outer_stream :
76
+ # Write some data to the outer stream
77
+ from System import Array , Byte
78
+ outer_data = Array [Byte ]([10 , 20 , 30 ])
79
+ outer_stream .Write (outer_data , 0 , len (outer_data ))
80
+
81
+ # Check that the outer stream is usable
82
+ self .assertEqual (3 , outer_stream .Length )
83
+
84
+ with MemoryStream () as inner_stream :
85
+ # Write different data to the inner stream
86
+ inner_data = Array [Byte ]([40 , 50 , 60 , 70 ])
87
+ inner_stream .Write (inner_data , 0 , len (inner_data ))
88
+
89
+ # Check that the inner stream is usable
90
+ self .assertEqual (4 , inner_stream .Length )
91
+
92
+ # Try to use the inner stream - should fail because it's disposed
93
+ try :
94
+ inner_stream .Position = 0
95
+ except Exception :
96
+ streams_disposed [1 ] = True
97
+
98
+ # Try to use the outer stream - should fail because it's disposed
99
+ try :
100
+ outer_stream .Position = 0
101
+ except Exception :
102
+ streams_disposed [0 ] = True
103
+
104
+ # Verify both streams were properly disposed
105
+ self .assertTrue (all (streams_disposed ))
106
+
107
+ def test_exception_handling (self ):
108
+ """Test that exceptions propagate correctly through the context manager"""
109
+ with self .assertRaises (ValueError ):
110
+ with MemoryStream () as stream :
111
+ raise ValueError ("Test exception" )
112
+
113
+ # Stream should be disposed despite the exception
114
+ with self .assertRaises (Exception ):
115
+ stream .Position = 0
116
+
117
+ if __name__ == "__main__" :
118
+ unittest .main ()
0 commit comments