Skip to content

Add support for async functions #766

Add support for async functions

Add support for async functions #766

GitHub Actions / .NET Test report ubuntu-latest-3.13 failed Nov 23, 2024 in 0s

798 passed, 6 failed and 34 skipped

Tests failed

Report Passed Failed Skipped Time
Conda.Tests-ubuntu-latest-3.13-net8.0.trx 1❌ 9s
Conda.Tests-ubuntu-latest-3.13-net9.0.trx 1❌ 4s
CSnakes.Runtime.Tests-ubuntu-latest-3.13-net8.0.trx 120✔️ 17✖️ 13s
CSnakes.Runtime.Tests-ubuntu-latest-3.13-net9.0.trx 120✔️ 17✖️ 9s
CSnakes.Tests-ubuntu-latest-3.13-net8.0.trx 184✔️ 2❌ 18s
CSnakes.Tests-ubuntu-latest-3.13-net9.0.trx 184✔️ 2❌ 16s
Integration.Tests-ubuntu-latest-3.13-net8.0.trx 90✔️ 31s
Integration.Tests-ubuntu-latest-3.13-net9.0.trx 100✔️ 20s

❌ Conda.Tests-ubuntu-latest-3.13-net8.0.trx

1 tests were completed in 9s with 0 passed, 1 failed and 0 skipped.

Test suite Passed Failed Skipped Time
Conda.Tests.BasicTests 1❌ 3s

❌ Conda.Tests.BasicTests

❌ TestSimpleImport
	CSnakes.Runtime.PythonInvocationException : The Python runtime raised a ModuleNotFoundError exception, see InnerException for details.
	---- CSnakes.Runtime.PythonRuntimeException : No module named 'httpx'

❌ Conda.Tests-ubuntu-latest-3.13-net9.0.trx

1 tests were completed in 4s with 0 passed, 1 failed and 0 skipped.

Test suite Passed Failed Skipped Time
Conda.Tests.BasicTests 1❌ 1s

❌ Conda.Tests.BasicTests

❌ TestSimpleImport
	CSnakes.Runtime.PythonInvocationException : The Python runtime raised a ModuleNotFoundError exception, see InnerException for details.
	---- CSnakes.Runtime.PythonRuntimeException : No module named 'httpx'

✔️ CSnakes.Runtime.Tests-ubuntu-latest-3.13-net8.0.trx

137 tests were completed in 13s with 120 passed, 0 failed and 17 skipped.

Test suite Passed Failed Skipped Time
CSnakes.Runtime.Tests.Converter.BigIntegerConverterTest 1✔️ 53ms
CSnakes.Runtime.Tests.Converter.BoolConverterTest 2✔️ 118ms
CSnakes.Runtime.Tests.Converter.BytesConverterTest 2✔️ 56ms
CSnakes.Runtime.Tests.Converter.DictionaryConverterTest 1✔️ 47ms
CSnakes.Runtime.Tests.Converter.DoubleConverterTest 10✔️ 425ms
CSnakes.Runtime.Tests.Converter.ListConverterTest 1✔️ 52ms
CSnakes.Runtime.Tests.Converter.LongConverterTest 7✔️ 270ms
CSnakes.Runtime.Tests.Converter.TupleConverterTests 5✔️ 239ms
CSnakes.Runtime.Tests.Converter.UnicodeConverterTest 6✔️ 365ms
CSnakes.Runtime.Tests.Locators.NuGetLocatorTests 1✔️ 7✖️ 21ms
CSnakes.Runtime.Tests.Locators.PythonLocatorTests 6✔️ 10✖️ 15ms
CSnakes.Runtime.Tests.Python.ImmortalTests 5✔️ 677ms
CSnakes.Runtime.Tests.Python.ImportTests 3✔️ 157ms
CSnakes.Runtime.Tests.Python.PyDictionaryTests 6✔️ 262ms
CSnakes.Runtime.Tests.Python.PyObjectTests 45✔️ 2s
CSnakes.Runtime.Tests.ServiceCollectionTests 19✔️ 340ms

✔️ CSnakes.Runtime.Tests-ubuntu-latest-3.13-net9.0.trx

137 tests were completed in 9s with 120 passed, 0 failed and 17 skipped.

Test suite Passed Failed Skipped Time
CSnakes.Runtime.Tests.Converter.BigIntegerConverterTest 1✔️ 39ms
CSnakes.Runtime.Tests.Converter.BoolConverterTest 2✔️ 54ms
CSnakes.Runtime.Tests.Converter.BytesConverterTest 2✔️ 56ms
CSnakes.Runtime.Tests.Converter.DictionaryConverterTest 1✔️ 54ms
CSnakes.Runtime.Tests.Converter.DoubleConverterTest 10✔️ 277ms
CSnakes.Runtime.Tests.Converter.ListConverterTest 1✔️ 52ms
CSnakes.Runtime.Tests.Converter.LongConverterTest 7✔️ 333ms
CSnakes.Runtime.Tests.Converter.TupleConverterTests 5✔️ 223ms
CSnakes.Runtime.Tests.Converter.UnicodeConverterTest 6✔️ 138ms
CSnakes.Runtime.Tests.Locators.NuGetLocatorTests 1✔️ 7✖️ 13ms
CSnakes.Runtime.Tests.Locators.PythonLocatorTests 6✔️ 10✖️ 12ms
CSnakes.Runtime.Tests.Python.ImmortalTests 5✔️ 554ms
CSnakes.Runtime.Tests.Python.ImportTests 3✔️ 130ms
CSnakes.Runtime.Tests.Python.PyDictionaryTests 6✔️ 270ms
CSnakes.Runtime.Tests.Python.PyObjectTests 45✔️ 2s
CSnakes.Runtime.Tests.ServiceCollectionTests 19✔️ 254ms

❌ CSnakes.Tests-ubuntu-latest-3.13-net8.0.trx

186 tests were completed in 18s with 184 passed, 2 failed and 0 skipped.

Test suite Passed Failed Skipped Time
CSnakes.Tests.CaseHelperTests 10✔️ 15ms
CSnakes.Tests.GeneratedSignatureTests 30✔️ 8s
CSnakes.Tests.PythonConstantTests+FloatTests 1✔️ 16ms
CSnakes.Tests.PythonStaticGeneratorTests 13✔️ 2❌ 2s
CSnakes.Tests.TokenizerTests 81✔️ 489ms
CSnakes.Tests.TypeReflectionTests 49✔️ 393ms

❌ CSnakes.Tests.PythonStaticGeneratorTests

❌ FormatClassFromMethods(resourceName: "CSnakes.Tests.python.test_coroutines.py")
	Shouldly.ShouldMatchApprovedException : To approve the changes run this command:
	cp "/home/runner/work/CSnakes/CSnakes/src/CSnakes.Tests/PythonStaticGeneratorTests/FormatClassFromMethods.test_coroutines.received.txt" "/home/runner/work/CSnakes/CSnakes/src/CSnakes.Tests/PythonStaticGeneratorTests/FormatClassFromMethods.test_coroutines.approved.txt"
	----------------------------
	
	Approval file /home/runner/work/CSnakes/CSnakes/src/CSnakes.Tests/PythonStaticGeneratorTests/FormatClassFromMethods.test_coroutines.approved.txt
	    does not exist
❌ FormatClassFromMethods(resourceName: "CSnakes.Tests.python.test_generators.py")
	Shouldly.ShouldMatchApprovedException : To approve the changes run this command:
	cp "/home/runner/work/CSnakes/CSnakes/src/CSnakes.Tests/PythonStaticGeneratorTests/FormatClassFromMethods.test_generators.received.txt" "/home/runner/work/CSnakes/CSnakes/src/CSnakes.Tests/PythonStaticGeneratorTests/FormatClassFromMethods.test_generators.approved.txt"
	----------------------------
	
	compiledCode
	    should match approved with options: Ignoring line endings
	"// <auto-generated/>
	#nullable enable
	
	using CSnakes.Runtime;
	using CSnakes.Runtime.Python;
	
	using System;
	using System.Collections.Generic;
	using System.Diagnostics;
	using System.Reflection.Metadata;
	
	using Microsoft.Extensions.Logging;
	
	[assembly: MetadataUpdateHandler(typeof(Python.Generated.Tests.TestClassExtensions))]
	
	namespace Python.Generated.Tests;
	
	public static class TestClassExtensions
	{
	    private static ITestClass? instance;
	
	    private static ReadOnlySpan<byte> HotReloadHash => "657bc350954200f5d7103a2587de60ae"u8;
	
	    public static ITestClass TestClass(this IPythonEnvironment env)
	    {
	        if (instance is null)
	        {
	            instance = new TestClassInternal(env.Logger);
	        }
	        Debug.Assert(!env.IsDisposed());
	        return instance;
	    }
	
	    public static void UpdateApplication(Type[]? updatedTypes)
	    {
	        instance?.ReloadModule();
	    }
	
	    private class TestClassInternal : ITestClass
	    {
	        private PyObject module;
	        private readonly ILogger<IPythonEnvironment> logger;
	
	        private PyObject __func_example_generator;
	        private PyObject __func_test_normal_generator;
	
	        internal TestClassInternal(ILogger<IPythonEnvironment> logger)
	        {
	            this.logger = logger;
	            using (GIL.Acquire())
	            {
	                logger.LogDebug("Importing module {ModuleName}", "test");
	                module = Import.ImportModule("test");
	                this.__func_example_generator = module.GetAttr("example_generator");
	                this.__func_test_normal_generator = module.GetAttr("test_normal_generator");
	            }
	        }
	
	        void IReloadableModuleImport.ReloadModule()
	        {
	            logger.LogDebug("Reloading module {ModuleName}", "test");
	            using (GIL.Acquire())
	            {
	                Import.ReloadModule(ref module);
	                // Dispose old functions
	                this.__func_example_generator.Dispose();
	                this.__func_test_normal_generator.Dispose();
	                // Bind to new functions
	                this.__func_example_generator = module.GetAttr("example_generator");
	                this.__func_test_normal_generator = module.GetAttr("test_normal_generator");
	            }
	        }
	
	        public void Dispose()
	        {
	            logger.LogDebug("Disposing module {ModuleName}", "test");
	            this.__func_example_generator.Dispose();
	            this.__func_test_normal_generator.Dispose();
	            module.Dispose();
	        }
	
	        public IGeneratorIterator<string, long, bool> ExampleGenerator(long length)
	        {
	            using (GIL.Acquire())
	            {
	                logger.LogDebug("Invoking Python function: {FunctionName}", "example_generator");
	                PyObject __underlyingPythonFunc = this.__func_example_generator;
	                using PyObject length_pyObject = PyObject.From(length)!;
	                using PyObject __result_pyObject = __underlyingPythonFunc.Call(length_pyObject);
	                return __result_pyObject.As<IGeneratorIterator<string, long, bool>>();
	            }
	        }
	
	        public IGeneratorIterator<string, PyObject, PyObject> TestNormalGenerator()
	        {
	            using (GIL.Acquire())
	            {
	                logger.LogDebug("Invoking Python function: {FunctionName}", "test_normal_generator");
	                PyObject __underlyingPythonFunc = this.__func_test_normal_generator;
	                using PyObject __result_pyObject = __underlyingPythonFunc.Call();
	                return __result_pyObject.As<IGeneratorIterator<string, PyObject, PyObject>>();
	            }
	        }
	    }
	}
	
	/// <summary>
	/// Represents functions of the Python module <c>test</c>.
	/// </summary>
	public interface ITestClass : IReloadableModuleImport
	{
	    /// <summary>
	    /// Invokes the Python function <c>example_generator</c>:
	    /// <code><![CDATA[
	    /// def example_generator(length: int) -> Generator[str, int, bool]: ...
	    /// ]]></code>
	    /// </summary>
	    IGeneratorIterator<string, long, bool> ExampleGenerator(long length);
	
	    /// <summary>
	    /// Invokes the Python function <c>test_normal_generator</c>:
	    /// <code><![CDATA[
	    /// def test_normal_generator() -> Generator[str, None, None]: ...
	    /// ]]></code>
	    /// </summary>
	    IGeneratorIterator<string, PyObject, PyObject> TestNormalGenerator();
	}
	"
	    but was
	"// <auto-generated/>
	#nullable enable
	
	using CSnakes.Runtime;
	using CSnakes.Runtime.Python;
	
	using System;
	using System.Collections.Generic;
	using System.Diagnostics;
	using System.Reflection.Metadata;
	
	using Microsoft.Extensions.Logging;
	
	[assembly: MetadataUpdateHandler(typeof(Python.Generated.Tests.TestClassExtensions))]
	
	namespace Python.Generated.Tests;
	
	public static class TestClassExtensions
	{
	    private static ITestClass? instance;
	
	    private static ReadOnlySpan<byte> HotReloadHash => "628447fb6935f7e3926b93b678146fc8"u8;
	
	    public static ITestClass TestClass(this IPythonEnvironment env)
	    {
	        if (instance is null)
	        {
	            instance = new TestClassInternal(env.Logger);
	        }
	        Debug.Assert(!env.IsDisposed());
	        return instance;
	    }
	
	    public static void UpdateApplication(Type[]? updatedTypes)
	    {
	        instance?.ReloadModule();
	    }
	
	    private class TestClassInternal : ITestClass
	    {
	        private PyObject module;
	        private readonly ILogger<IPythonEnvironment> logger;
	
	        private PyObject __func_example_generator;
	        private PyObject __func_test_normal_generator;
	        private PyObject __func_test_generator_sequence;
	
	        internal TestClassInternal(ILogger<IPythonEnvironment> logger)
	        {
	            this.logger = logger;
	            using (GIL.Acquire())
	            {
	                logger.LogDebug("Importing module {ModuleName}", "test");
	                module = Import.ImportModule("test");
	                this.__func_example_generator = module.GetAttr("example_generator");
	                this.__func_test_normal_generator = module.GetAttr("test_normal_generator");
	                this.__func_test_generator_sequence = module.GetAttr("test_generator_sequence");
	            }
	        }
	
	        void IReloadableModuleImport.ReloadModule()
	        {
	            logger.LogDebug("Reloading module {ModuleName}", "test");
	            using (GIL.Acquire())
	            {
	                Import.ReloadModule(ref module);
	                // Dispose old functions
	                this.__func_example_generator.Dispose();
	                this.__func_test_normal_generator.Dispose();
	                this.__func_test_generator_sequence.Dispose();
	                // Bind to new functions
	                this.__func_example_generator = module.GetAttr("example_generator");
	                this.__func_test_normal_generator = module.GetAttr("test_normal_generator");
	                this.__func_test_generator_sequence = module.GetAttr("test_generator_sequence");
	            }
	        }
	
	        public void Dispose()
	        {
	            logger.LogDebug("Disposing module {ModuleName}", "test");
	            this.__func_example_generator.Dispose();
	            this.__func_test_normal_generator.Dispose();
	            this.__func_test_generator_sequence.Dispose();
	            module.Dispose();
	        }
	
	        public IGeneratorIterator<string, long, bool> ExampleGenerator(long length)
	        {
	            using (GIL.Acquire())
	            {
	                logger.LogDebug("Invoking Python function: {FunctionName}", "example_generator");
	                PyObject __underlyingPythonFunc = this.__func_example_generator;
	                using PyObject length_pyObject = PyObject.From(length)!;
	                using PyObject __result_pyObject = __underlyingPythonFunc.Call(length_pyObject);
	                return __result_pyObject.As<IGeneratorIterator<string, long, bool>>();
	            }
	        }
	
	        public IGeneratorIterator<string, PyObject, PyObject> TestNormalGenerator()
	        {
	            using (GIL.Acquire())
	            {
	                logger.LogDebug("Invoking Python function: {FunctionName}", "test_normal_generator");
	                PyObject __underlyingPythonFunc = this.__func_test_normal_generator;
	                using PyObject __result_pyObject = __underlyingPythonFunc.Call();
	                return __result_pyObject.As<IGeneratorIterator<string, PyObject, PyObject>>();
	            }
	        }
	
	        public IGeneratorIterator<string, PyObject, PyObject> TestGeneratorSequence()
	        {
	            using (GIL.Acquire())
	            {
	                logger.LogDebug("Invoking Python function: {FunctionName}", "test_generator_sequence");
	                PyObject __underlyingPythonFunc = this.__func_test_generator_sequence;
	                using PyObject __result_pyObject = __underlyingPythonFunc.Call();
	                return __result_pyObject.As<IGeneratorIterator<string, PyObject, PyObject>>();
	            }
	        }
	    }
	}
	
	/// <summary>
	/// Represents functions of the Python module <c>test</c>.
	/// </summary>
	public interface ITestClass : IReloadableModuleImport
	{
	    /// <summary>
	    /// Invokes the Python function <c>example_generator</c>:
	    /// <code><![CDATA[
	    /// def example_generator(length: int) -> Generator[str, int, bool]: ...
	    /// ]]></code>
	    /// </summary>
	    IGeneratorIterator<string, long, "
	    difference
	Showing some of the 3577 differences
	Difference     |       |    |    |    |    |    |    |    |    |    |    |    |    |    |    |    |    |    |    |    |    |        
	               |      \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/       
	Index          | ...  502  503  504  505  506  507  508  509  510  511  512  513  514  515  516  517  518  519  520  521  522  ...  
	Expected Value | ...  5    7    b    c    3    5    0    9    5    4    2    0    0    f    5    d    7    1    0    3    a    ...  
	Actual Value   | ...  2    8    4    4    7    f    b    6    9    3    5    f    7    e    3    9    2    6    b    9    3    ...  
	Expected Code  | ...  53   55   98   99   51   53   48   57   53   52   50   48   48   102  53   100  55   49   48   51   97   ...  
	Actual Code    | ...  50   56   52   52   55   102  98   54   57   51   53   102  55   101  51   57   50   54   98   57   51   ...  
	
	Difference     |       |    |    |    |    |    |    |    |    |    |    |    |         |    |    |                                 
	               |      \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/       \|/  \|/  \|/                                
	Index          | ...  517  518  519  520  521  522  523  524  525  526  527  528  529  530  531  532  533  534  535  536  537  ...  
	Expected Value | ...  d    7    1    0    3    a    2    5    8    7    d    e    6    0    a    e    "    u    8    ;    \n   ...  
	Actual Value   | ...  9    2    6    b    9    3    b    6    7    8    1    4    6    f    c    8    "    u    8    ;    \n   ...  
	Expected Code  | ...  100  55   49   48   51   97   50   53   56   55   100  101  54   48   97   101  34   117  56   59   10   ...  
	Actual Code    | ...  57   50   54   98   57   51   98   54   55   56   49   52   54   102  99   56   34   117  56   59   10   ...  
	
	Difference     |                                |    |    |    |    |    |    |    |    |    |    |    |    |    |    |    |        
	               |                               \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/       
	Index          | ...  1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 ...  
	Expected Value | ...  \s   \s   \s   \s   \s   \s   i    n    t    e    r    n    a    l    \s   T    e    s    t    C    l    ...  
	Actual Value   | ...  \s   \s   \s   \s   \s   p    r    i    v    a    t    e    \s   P    y    O    b    j    e    c    t    ...  
	Expected Code  | ...  32   32   32   32   32   32   105  110  116  101  114  110  97   108  32   84   101  115  116  67   108  ...  
	Actual Code    | ...  32   32   32   32   32   112  114  105  118  97   116  101  32   80   121  79   98   106  101  99   116  ...  
	
	Difference     |       |    |    |    |    |    |    |    |    |    |    |    |    |    |    |    |    |    |    |    |    |        
	               |      \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/       
	Index          | ...  1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 ...  
	Expected Value | ...  t    C    l    a    s    s    I    n    t    e    r    n    a    l    (    I    L    o    g    g    e    ...  
	Actual Value   | ...  e    c    t    \s   _    _    f    u    n    c    _    t    e    s    t    _    g    e    n    e    r    ...  
	Expected Code  | ...  116  67   108  97   115  115  73   110  116  101  114  110  97   108  40   73   76   111  103  103  101  ...  
	Actual Code    | ...  101  99   116  32   95   95   102  117  110  99   95   116  101  115  116  95   103  101  110  101  114  ...  
	
	Difference     |       |    |    |    |    |    |    |    |    |    |         |    |    |    |    |    |    |    |    |    |        
	               |      \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/       \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/       
	Index          | ...  1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 ...  
	Expected Value | ...  r    <    I    P    y    t    h    o    n    E    n    v    i    r    o    n    m    e    n    t    >    ...  
	Actual Value   | ...  a    t    o    r    _    s    e    q    u    e    n    c    e    ;    \n   \n   \s   \s   \s   \s   \s   ...  
	Expected Code  | ...  114  60   73   80   121  116  104  111  110  69   110  118  105  114  111  110  109  101  110  116  62   ...  
	Actual Code    | ...  97   116  111  114  95   115  101  113  117  101  110  99   101  59   10   10   32   32   32   32   32   ...  
	
	Difference     |       |    |    |    |    |    |    |    |    |    |         |    |    |    |    |    |    |    |    |    |        
	               |      \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/       \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/       
	Index          | ...  1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 ...  
	Expected Value | ...  l    o    g    g    e    r    )    \n   \s   \s   \s   \s   \s   \s   \s   \s   {    \n   \s   \s   \s   ...  
	Actual Value   | ...  \s   \s   i    n    t    e    r    n    a    l    \s   T    e    s    t    C    l    a    s    s    I    ...  
	Expected Code  | ...  108  111  103  103  101  114  41   10   32   32   32   32   32   32   32   32   123  10   32   32   32   ...  
	Actual Code    | ...  32   32   105  110  116  101  114  110  97   108  32   84   101  115  116  67   108  97   115  115  73   ...  
	
	Difference     |       |    |    |    |    |    |    |    |    |    |    |    |    |    |    |    |    |    |    |    |    |        
	               |      \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/       
	Index          | ...  1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 ...  
	Expected Value | ...  \s   \s   \s   \s   \s   \s   \s   \s   \s   t    h    i    s    .    l    o    g    g    e    r    \s   ...  
	Actual Value   | ...  n    t    e    r    n    a    l    (    I    L    o    g    g    e    r    <    I    P    y    t    h    ...  
	Expected Code  | ...  32   32   32   32   32   32   32   32   32   116  104  105  115  46   108  111  103  103  101  114  32   ...  
	Actual Code    | ...  110  116  101  114  110  97   108  40   73   76   111  103  103  101  114  60   73   80   121  116  104  ...  
	
	Difference     |       |    |    |    |    |    |    |    |    |    |    |    |    |    |         |    |    |    |    |    |        
	               |      \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/       \|/  \|/  \|/  \|/  \|/  \|/       
	Index          | ...  1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 ...  
	Expected Value | ...  =    \s   l    o    g    g    e    r    ;    \n   \s   \s   \s   \s   \s   \s   \s   \s   \s   \s   \s   ...  
	Actual Value   | ...  o    n    E    n    v    i    r    o    n    m    e    n    t    >    \s   l    o    g    g    e    r    ...  
	Expected Code  | ...  61   32   108  111  103  103  101  114  59   10   32   32   32   32   32   32   32   32   32   32   32   ...  
	Actual Code    | ...  111  110  69   110  118  105  114  111  110  109  101  110  116  62   32   108  111  103  103  101  114  ...  
	
	Difference     |       |    |    |    |    |    |         |    |    |    |    |    |    |    |    |    |    |    |    |    |        
	               |      \|/  \|/  \|/  \|/  \|/  \|/       \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/       
	Index          | ...  1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 ...  
	Expected Value | ...  \s   u    s    i    n    g    \s   (    G    I    L    .    A    c    q    u    i    r    e    (    )    ...  
	Actual Value   | ...  )    \n   \s   \s   \s   \s   \s   \s   \s   \s   {    \n   \s   \s   \s   \s   \s   \s   \s   \s   \s   ...  
	Expected Code  | ...  32   117  115  105  110  103  32   40   71   73   76   46   65   99   113  117  105  114  101  40   41   ...  
	Actual Code    | ...  41   10   32   32   32   32   32   32   32   32   123  10   32   32   32   32   32   32   32   32   32   ...  
	
	Difference     |       |    |         |    |    |    |    |    |    |    |    |    |    |    |    |         |    |    |    |        
	               |      \|/  \|/       \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/       \|/  \|/  \|/  \|/       
	Index          | ...  1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 ...  
	Expected Value | ...  )    \n   \s   \s   \s   \s   \s   \s   \s   \s   \s   \s   \s   \s   {    \n   \s   \s   \s   \s   \s   ...  
	Actual Value   | ...  \s   \s   \s   t    h    i    s    .    l    o    g    g    e    r    \s   =    \s   l    o    g    g    ...  
	Expected Code  | ...  41   10   32   32   32   32   32   32   32   32   32   32   32   32   123  10   32   32   32   32   32   ...  
	Actual Code    | ...  32   32   32   116  104  105  115  46   108  111  103  103  101  114  32   61   32   108  111  103  103  ...  

❌ CSnakes.Tests-ubuntu-latest-3.13-net9.0.trx

186 tests were completed in 16s with 184 passed, 2 failed and 0 skipped.

Test suite Passed Failed Skipped Time
CSnakes.Tests.CaseHelperTests 10✔️ 1ms
CSnakes.Tests.GeneratedSignatureTests 30✔️ 7s
CSnakes.Tests.PythonConstantTests+FloatTests 1✔️ 43ms
CSnakes.Tests.PythonStaticGeneratorTests 13✔️ 2❌ 1s
CSnakes.Tests.TokenizerTests 81✔️ 326ms
CSnakes.Tests.TypeReflectionTests 49✔️ 407ms

❌ CSnakes.Tests.PythonStaticGeneratorTests

❌ FormatClassFromMethods(resourceName: "CSnakes.Tests.python.test_coroutines.py")
	Shouldly.ShouldMatchApprovedException : To approve the changes run this command:
	cp "/home/runner/work/CSnakes/CSnakes/src/CSnakes.Tests/PythonStaticGeneratorTests/FormatClassFromMethods.test_coroutines.received.txt" "/home/runner/work/CSnakes/CSnakes/src/CSnakes.Tests/PythonStaticGeneratorTests/FormatClassFromMethods.test_coroutines.approved.txt"
	----------------------------
	
	Approval file /home/runner/work/CSnakes/CSnakes/src/CSnakes.Tests/PythonStaticGeneratorTests/FormatClassFromMethods.test_coroutines.approved.txt
	    does not exist
❌ FormatClassFromMethods(resourceName: "CSnakes.Tests.python.test_generators.py")
	Shouldly.ShouldMatchApprovedException : To approve the changes run this command:
	cp "/home/runner/work/CSnakes/CSnakes/src/CSnakes.Tests/PythonStaticGeneratorTests/FormatClassFromMethods.test_generators.received.txt" "/home/runner/work/CSnakes/CSnakes/src/CSnakes.Tests/PythonStaticGeneratorTests/FormatClassFromMethods.test_generators.approved.txt"
	----------------------------
	
	compiledCode
	    should match approved with options: Ignoring line endings
	"// <auto-generated/>
	#nullable enable
	
	using CSnakes.Runtime;
	using CSnakes.Runtime.Python;
	
	using System;
	using System.Collections.Generic;
	using System.Diagnostics;
	using System.Reflection.Metadata;
	
	using Microsoft.Extensions.Logging;
	
	[assembly: MetadataUpdateHandler(typeof(Python.Generated.Tests.TestClassExtensions))]
	
	namespace Python.Generated.Tests;
	
	public static class TestClassExtensions
	{
	    private static ITestClass? instance;
	
	    private static ReadOnlySpan<byte> HotReloadHash => "657bc350954200f5d7103a2587de60ae"u8;
	
	    public static ITestClass TestClass(this IPythonEnvironment env)
	    {
	        if (instance is null)
	        {
	            instance = new TestClassInternal(env.Logger);
	        }
	        Debug.Assert(!env.IsDisposed());
	        return instance;
	    }
	
	    public static void UpdateApplication(Type[]? updatedTypes)
	    {
	        instance?.ReloadModule();
	    }
	
	    private class TestClassInternal : ITestClass
	    {
	        private PyObject module;
	        private readonly ILogger<IPythonEnvironment> logger;
	
	        private PyObject __func_example_generator;
	        private PyObject __func_test_normal_generator;
	
	        internal TestClassInternal(ILogger<IPythonEnvironment> logger)
	        {
	            this.logger = logger;
	            using (GIL.Acquire())
	            {
	                logger.LogDebug("Importing module {ModuleName}", "test");
	                module = Import.ImportModule("test");
	                this.__func_example_generator = module.GetAttr("example_generator");
	                this.__func_test_normal_generator = module.GetAttr("test_normal_generator");
	            }
	        }
	
	        void IReloadableModuleImport.ReloadModule()
	        {
	            logger.LogDebug("Reloading module {ModuleName}", "test");
	            using (GIL.Acquire())
	            {
	                Import.ReloadModule(ref module);
	                // Dispose old functions
	                this.__func_example_generator.Dispose();
	                this.__func_test_normal_generator.Dispose();
	                // Bind to new functions
	                this.__func_example_generator = module.GetAttr("example_generator");
	                this.__func_test_normal_generator = module.GetAttr("test_normal_generator");
	            }
	        }
	
	        public void Dispose()
	        {
	            logger.LogDebug("Disposing module {ModuleName}", "test");
	            this.__func_example_generator.Dispose();
	            this.__func_test_normal_generator.Dispose();
	            module.Dispose();
	        }
	
	        public IGeneratorIterator<string, long, bool> ExampleGenerator(long length)
	        {
	            using (GIL.Acquire())
	            {
	                logger.LogDebug("Invoking Python function: {FunctionName}", "example_generator");
	                PyObject __underlyingPythonFunc = this.__func_example_generator;
	                using PyObject length_pyObject = PyObject.From(length)!;
	                using PyObject __result_pyObject = __underlyingPythonFunc.Call(length_pyObject);
	                return __result_pyObject.As<IGeneratorIterator<string, long, bool>>();
	            }
	        }
	
	        public IGeneratorIterator<string, PyObject, PyObject> TestNormalGenerator()
	        {
	            using (GIL.Acquire())
	            {
	                logger.LogDebug("Invoking Python function: {FunctionName}", "test_normal_generator");
	                PyObject __underlyingPythonFunc = this.__func_test_normal_generator;
	                using PyObject __result_pyObject = __underlyingPythonFunc.Call();
	                return __result_pyObject.As<IGeneratorIterator<string, PyObject, PyObject>>();
	            }
	        }
	    }
	}
	
	/// <summary>
	/// Represents functions of the Python module <c>test</c>.
	/// </summary>
	public interface ITestClass : IReloadableModuleImport
	{
	    /// <summary>
	    /// Invokes the Python function <c>example_generator</c>:
	    /// <code><![CDATA[
	    /// def example_generator(length: int) -> Generator[str, int, bool]: ...
	    /// ]]></code>
	    /// </summary>
	    IGeneratorIterator<string, long, bool> ExampleGenerator(long length);
	
	    /// <summary>
	    /// Invokes the Python function <c>test_normal_generator</c>:
	    /// <code><![CDATA[
	    /// def test_normal_generator() -> Generator[str, None, None]: ...
	    /// ]]></code>
	    /// </summary>
	    IGeneratorIterator<string, PyObject, PyObject> TestNormalGenerator();
	}
	"
	    but was
	"// <auto-generated/>
	#nullable enable
	
	using CSnakes.Runtime;
	using CSnakes.Runtime.Python;
	
	using System;
	using System.Collections.Generic;
	using System.Diagnostics;
	using System.Reflection.Metadata;
	
	using Microsoft.Extensions.Logging;
	
	[assembly: MetadataUpdateHandler(typeof(Python.Generated.Tests.TestClassExtensions))]
	
	namespace Python.Generated.Tests;
	
	public static class TestClassExtensions
	{
	    private static ITestClass? instance;
	
	    private static ReadOnlySpan<byte> HotReloadHash => "628447fb6935f7e3926b93b678146fc8"u8;
	
	    public static ITestClass TestClass(this IPythonEnvironment env)
	    {
	        if (instance is null)
	        {
	            instance = new TestClassInternal(env.Logger);
	        }
	        Debug.Assert(!env.IsDisposed());
	        return instance;
	    }
	
	    public static void UpdateApplication(Type[]? updatedTypes)
	    {
	        instance?.ReloadModule();
	    }
	
	    private class TestClassInternal : ITestClass
	    {
	        private PyObject module;
	        private readonly ILogger<IPythonEnvironment> logger;
	
	        private PyObject __func_example_generator;
	        private PyObject __func_test_normal_generator;
	        private PyObject __func_test_generator_sequence;
	
	        internal TestClassInternal(ILogger<IPythonEnvironment> logger)
	        {
	            this.logger = logger;
	            using (GIL.Acquire())
	            {
	                logger.LogDebug("Importing module {ModuleName}", "test");
	                module = Import.ImportModule("test");
	                this.__func_example_generator = module.GetAttr("example_generator");
	                this.__func_test_normal_generator = module.GetAttr("test_normal_generator");
	                this.__func_test_generator_sequence = module.GetAttr("test_generator_sequence");
	            }
	        }
	
	        void IReloadableModuleImport.ReloadModule()
	        {
	            logger.LogDebug("Reloading module {ModuleName}", "test");
	            using (GIL.Acquire())
	            {
	                Import.ReloadModule(ref module);
	                // Dispose old functions
	                this.__func_example_generator.Dispose();
	                this.__func_test_normal_generator.Dispose();
	                this.__func_test_generator_sequence.Dispose();
	                // Bind to new functions
	                this.__func_example_generator = module.GetAttr("example_generator");
	                this.__func_test_normal_generator = module.GetAttr("test_normal_generator");
	                this.__func_test_generator_sequence = module.GetAttr("test_generator_sequence");
	            }
	        }
	
	        public void Dispose()
	        {
	            logger.LogDebug("Disposing module {ModuleName}", "test");
	            this.__func_example_generator.Dispose();
	            this.__func_test_normal_generator.Dispose();
	            this.__func_test_generator_sequence.Dispose();
	            module.Dispose();
	        }
	
	        public IGeneratorIterator<string, long, bool> ExampleGenerator(long length)
	        {
	            using (GIL.Acquire())
	            {
	                logger.LogDebug("Invoking Python function: {FunctionName}", "example_generator");
	                PyObject __underlyingPythonFunc = this.__func_example_generator;
	                using PyObject length_pyObject = PyObject.From(length)!;
	                using PyObject __result_pyObject = __underlyingPythonFunc.Call(length_pyObject);
	                return __result_pyObject.As<IGeneratorIterator<string, long, bool>>();
	            }
	        }
	
	        public IGeneratorIterator<string, PyObject, PyObject> TestNormalGenerator()
	        {
	            using (GIL.Acquire())
	            {
	                logger.LogDebug("Invoking Python function: {FunctionName}", "test_normal_generator");
	                PyObject __underlyingPythonFunc = this.__func_test_normal_generator;
	                using PyObject __result_pyObject = __underlyingPythonFunc.Call();
	                return __result_pyObject.As<IGeneratorIterator<string, PyObject, PyObject>>();
	            }
	        }
	
	        public IGeneratorIterator<string, PyObject, PyObject> TestGeneratorSequence()
	        {
	            using (GIL.Acquire())
	            {
	                logger.LogDebug("Invoking Python function: {FunctionName}", "test_generator_sequence");
	                PyObject __underlyingPythonFunc = this.__func_test_generator_sequence;
	                using PyObject __result_pyObject = __underlyingPythonFunc.Call();
	                return __result_pyObject.As<IGeneratorIterator<string, PyObject, PyObject>>();
	            }
	        }
	    }
	}
	
	/// <summary>
	/// Represents functions of the Python module <c>test</c>.
	/// </summary>
	public interface ITestClass : IReloadableModuleImport
	{
	    /// <summary>
	    /// Invokes the Python function <c>example_generator</c>:
	    /// <code><![CDATA[
	    /// def example_generator(length: int) -> Generator[str, int, bool]: ...
	    /// ]]></code>
	    /// </summary>
	    IGeneratorIterator<string, long, "
	    difference
	Showing some of the 3577 differences
	Difference     |       |    |    |    |    |    |    |    |    |    |    |    |    |    |    |    |    |    |    |    |    |        
	               |      \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/       
	Index          | ...  502  503  504  505  506  507  508  509  510  511  512  513  514  515  516  517  518  519  520  521  522  ...  
	Expected Value | ...  5    7    b    c    3    5    0    9    5    4    2    0    0    f    5    d    7    1    0    3    a    ...  
	Actual Value   | ...  2    8    4    4    7    f    b    6    9    3    5    f    7    e    3    9    2    6    b    9    3    ...  
	Expected Code  | ...  53   55   98   99   51   53   48   57   53   52   50   48   48   102  53   100  55   49   48   51   97   ...  
	Actual Code    | ...  50   56   52   52   55   102  98   54   57   51   53   102  55   101  51   57   50   54   98   57   51   ...  
	
	Difference     |       |    |    |    |    |    |    |    |    |    |    |    |         |    |    |                                 
	               |      \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/       \|/  \|/  \|/                                
	Index          | ...  517  518  519  520  521  522  523  524  525  526  527  528  529  530  531  532  533  534  535  536  537  ...  
	Expected Value | ...  d    7    1    0    3    a    2    5    8    7    d    e    6    0    a    e    "    u    8    ;    \n   ...  
	Actual Value   | ...  9    2    6    b    9    3    b    6    7    8    1    4    6    f    c    8    "    u    8    ;    \n   ...  
	Expected Code  | ...  100  55   49   48   51   97   50   53   56   55   100  101  54   48   97   101  34   117  56   59   10   ...  
	Actual Code    | ...  57   50   54   98   57   51   98   54   55   56   49   52   54   102  99   56   34   117  56   59   10   ...  
	
	Difference     |                                |    |    |    |    |    |    |    |    |    |    |    |    |    |    |    |        
	               |                               \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/       
	Index          | ...  1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 ...  
	Expected Value | ...  \s   \s   \s   \s   \s   \s   i    n    t    e    r    n    a    l    \s   T    e    s    t    C    l    ...  
	Actual Value   | ...  \s   \s   \s   \s   \s   p    r    i    v    a    t    e    \s   P    y    O    b    j    e    c    t    ...  
	Expected Code  | ...  32   32   32   32   32   32   105  110  116  101  114  110  97   108  32   84   101  115  116  67   108  ...  
	Actual Code    | ...  32   32   32   32   32   112  114  105  118  97   116  101  32   80   121  79   98   106  101  99   116  ...  
	
	Difference     |       |    |    |    |    |    |    |    |    |    |    |    |    |    |    |    |    |    |    |    |    |        
	               |      \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/       
	Index          | ...  1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 ...  
	Expected Value | ...  t    C    l    a    s    s    I    n    t    e    r    n    a    l    (    I    L    o    g    g    e    ...  
	Actual Value   | ...  e    c    t    \s   _    _    f    u    n    c    _    t    e    s    t    _    g    e    n    e    r    ...  
	Expected Code  | ...  116  67   108  97   115  115  73   110  116  101  114  110  97   108  40   73   76   111  103  103  101  ...  
	Actual Code    | ...  101  99   116  32   95   95   102  117  110  99   95   116  101  115  116  95   103  101  110  101  114  ...  
	
	Difference     |       |    |    |    |    |    |    |    |    |    |         |    |    |    |    |    |    |    |    |    |        
	               |      \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/       \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/       
	Index          | ...  1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 ...  
	Expected Value | ...  r    <    I    P    y    t    h    o    n    E    n    v    i    r    o    n    m    e    n    t    >    ...  
	Actual Value   | ...  a    t    o    r    _    s    e    q    u    e    n    c    e    ;    \n   \n   \s   \s   \s   \s   \s   ...  
	Expected Code  | ...  114  60   73   80   121  116  104  111  110  69   110  118  105  114  111  110  109  101  110  116  62   ...  
	Actual Code    | ...  97   116  111  114  95   115  101  113  117  101  110  99   101  59   10   10   32   32   32   32   32   ...  
	
	Difference     |       |    |    |    |    |    |    |    |    |    |         |    |    |    |    |    |    |    |    |    |        
	               |      \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/       \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/       
	Index          | ...  1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 ...  
	Expected Value | ...  l    o    g    g    e    r    )    \n   \s   \s   \s   \s   \s   \s   \s   \s   {    \n   \s   \s   \s   ...  
	Actual Value   | ...  \s   \s   i    n    t    e    r    n    a    l    \s   T    e    s    t    C    l    a    s    s    I    ...  
	Expected Code  | ...  108  111  103  103  101  114  41   10   32   32   32   32   32   32   32   32   123  10   32   32   32   ...  
	Actual Code    | ...  32   32   105  110  116  101  114  110  97   108  32   84   101  115  116  67   108  97   115  115  73   ...  
	
	Difference     |       |    |    |    |    |    |    |    |    |    |    |    |    |    |    |    |    |    |    |    |    |        
	               |      \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/       
	Index          | ...  1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 ...  
	Expected Value | ...  \s   \s   \s   \s   \s   \s   \s   \s   \s   t    h    i    s    .    l    o    g    g    e    r    \s   ...  
	Actual Value   | ...  n    t    e    r    n    a    l    (    I    L    o    g    g    e    r    <    I    P    y    t    h    ...  
	Expected Code  | ...  32   32   32   32   32   32   32   32   32   116  104  105  115  46   108  111  103  103  101  114  32   ...  
	Actual Code    | ...  110  116  101  114  110  97   108  40   73   76   111  103  103  101  114  60   73   80   121  116  104  ...  
	
	Difference     |       |    |    |    |    |    |    |    |    |    |    |    |    |    |         |    |    |    |    |    |        
	               |      \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/       \|/  \|/  \|/  \|/  \|/  \|/       
	Index          | ...  1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 ...  
	Expected Value | ...  =    \s   l    o    g    g    e    r    ;    \n   \s   \s   \s   \s   \s   \s   \s   \s   \s   \s   \s   ...  
	Actual Value   | ...  o    n    E    n    v    i    r    o    n    m    e    n    t    >    \s   l    o    g    g    e    r    ...  
	Expected Code  | ...  61   32   108  111  103  103  101  114  59   10   32   32   32   32   32   32   32   32   32   32   32   ...  
	Actual Code    | ...  111  110  69   110  118  105  114  111  110  109  101  110  116  62   32   108  111  103  103  101  114  ...  
	
	Difference     |       |    |    |    |    |    |         |    |    |    |    |    |    |    |    |    |    |    |    |    |        
	               |      \|/  \|/  \|/  \|/  \|/  \|/       \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/       
	Index          | ...  1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 ...  
	Expected Value | ...  \s   u    s    i    n    g    \s   (    G    I    L    .    A    c    q    u    i    r    e    (    )    ...  
	Actual Value   | ...  )    \n   \s   \s   \s   \s   \s   \s   \s   \s   {    \n   \s   \s   \s   \s   \s   \s   \s   \s   \s   ...  
	Expected Code  | ...  32   117  115  105  110  103  32   40   71   73   76   46   65   99   113  117  105  114  101  40   41   ...  
	Actual Code    | ...  41   10   32   32   32   32   32   32   32   32   123  10   32   32   32   32   32   32   32   32   32   ...  
	
	Difference     |       |    |         |    |    |    |    |    |    |    |    |    |    |    |    |         |    |    |    |        
	               |      \|/  \|/       \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/       \|/  \|/  \|/  \|/       
	Index          | ...  1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 ...  
	Expected Value | ...  )    \n   \s   \s   \s   \s   \s   \s   \s   \s   \s   \s   \s   \s   {    \n   \s   \s   \s   \s   \s   ...  
	Actual Value   | ...  \s   \s   \s   t    h    i    s    .    l    o    g    g    e    r    \s   =    \s   l    o    g    g    ...  
	Expected Code  | ...  41   10   32   32   32   32   32   32   32   32   32   32   32   32   123  10   32   32   32   32   32   ...  
	Actual Code    | ...  32   32   32   116  104  105  115  46   108  111  103  103  101  114  32   61   32   108  111  103  103  ...  

✔️ Integration.Tests-ubuntu-latest-3.13-net8.0.trx

90 tests were completed in 31s with 90 passed, 0 failed and 0 skipped.

Test suite Passed Failed Skipped Time
Integration.Tests.ArgsTests 6✔️ 61ms
Integration.Tests.BasicTests 9✔️ 77ms
Integration.Tests.BufferTests 28✔️ 320ms
Integration.Tests.CoroutineTests 2✔️ 661ms
Integration.Tests.DefaultsTests 7✔️ 7ms
Integration.Tests.ExceptionTests 2✔️ 9ms
Integration.Tests.FalseReturns 12✔️ 11ms
Integration.Tests.GeneratorTests 2✔️ 7ms
Integration.Tests.NoneTests 2✔️ 7ms
Integration.Tests.ReloadTests 3✔️ 7ms
Integration.Tests.TestDependency 1✔️ 226ms
Integration.Tests.TestDicts 5✔️ 23ms
Integration.Tests.TupleTests 11✔️ 38ms

✔️ Integration.Tests-ubuntu-latest-3.13-net9.0.trx

100 tests were completed in 20s with 100 passed, 0 failed and 0 skipped.

Test suite Passed Failed Skipped Time
Integration.Tests.ArgsTests 6✔️ 52ms
Integration.Tests.BasicTests 9✔️ 93ms
Integration.Tests.BufferTests 32✔️ 183ms
Integration.Tests.CoroutineTests 2✔️ 382ms
Integration.Tests.DefaultsTests 7✔️ 11ms
Integration.Tests.ExceptionTests 2✔️ 7ms
Integration.Tests.FalseReturns 12✔️ 24ms
Integration.Tests.GeneratorTests 2✔️ 6ms
Integration.Tests.NoneTests 2✔️ 2ms
Integration.Tests.ReloadTests 3✔️ 8ms
Integration.Tests.TestDependency 1✔️ 135ms
Integration.Tests.TestDicts 5✔️ 15ms
Integration.Tests.TupleTests 17✔️ 40ms

Annotations

Check failure on line 19 in src/CSnakes.Runtime/Python/PyObject.cs

See this annotation in the file changed.

@github-actions github-actions / .NET Test report ubuntu-latest-3.13

Conda.Tests.BasicTests ► TestSimpleImport

Failed test found in:
  Conda.Tests-ubuntu-latest-3.13-net8.0.trx
Error:
  CSnakes.Runtime.PythonInvocationException : The Python runtime raised a ModuleNotFoundError exception, see InnerException for details.
  ---- CSnakes.Runtime.PythonRuntimeException : No module named 'httpx'
Raw output
CSnakes.Runtime.PythonInvocationException : The Python runtime raised a ModuleNotFoundError exception, see InnerException for details.
---- CSnakes.Runtime.PythonRuntimeException : No module named 'httpx'
   at CSnakes.Runtime.Python.PyObject..ctor(IntPtr pyObject, Boolean ownsHandle) in /_/src/CSnakes.Runtime/Python/PyObject.cs:line 19
   at CSnakes.Runtime.Python.PyObject.Create(IntPtr ptr) in /_/src/CSnakes.Runtime/Python/PyObject.cs:line 27
   at CSnakes.Runtime.CPython.CPythonAPI.Import(String name) in /_/src/CSnakes.Runtime/CPython/Import.cs:line 18
   at CSnakes.Runtime.Python.Import.ImportModule(String module) in /_/src/CSnakes.Runtime/Python/Import.cs:line 10
   at CSnakes.Runtime.TestSimpleExtensions.TestSimpleInternal..ctor(ILogger`1 logger) in /_/src/Conda.Tests/obj/Debug/net8.0/generated/CSnakes.SourceGeneration/CSnakes.PythonStaticGenerator/TestSimple.py.cs:line 52
   at CSnakes.Runtime.TestSimpleExtensions.TestSimple(IPythonEnvironment env) in /_/src/Conda.Tests/obj/Debug/net8.0/generated/CSnakes.SourceGeneration/CSnakes.PythonStaticGenerator/TestSimple.py.cs:line 28
   at Conda.Tests.BasicTests.TestSimpleImport() in /_/src/Conda.Tests/BasicTests.cs:line 8
   at System.RuntimeMethodHandle.InvokeMethod(Object target, Void** arguments, Signature sig, Boolean isConstructor)
   at System.Reflection.MethodBaseInvoker.InvokeWithNoArgs(Object obj, BindingFlags invokeAttr)
----- Inner Stack Trace -----
  File "/home/runner/work/CSnakes/CSnakes/src/Conda.Tests/bin/Debug/net8.0/python/test_simple.py", line 1, in <module>
    import httpx

Check failure on line 19 in src/CSnakes.Runtime/Python/PyObject.cs

See this annotation in the file changed.

@github-actions github-actions / .NET Test report ubuntu-latest-3.13

Conda.Tests.BasicTests ► TestSimpleImport

Failed test found in:
  Conda.Tests-ubuntu-latest-3.13-net9.0.trx
Error:
  CSnakes.Runtime.PythonInvocationException : The Python runtime raised a ModuleNotFoundError exception, see InnerException for details.
  ---- CSnakes.Runtime.PythonRuntimeException : No module named 'httpx'
Raw output
CSnakes.Runtime.PythonInvocationException : The Python runtime raised a ModuleNotFoundError exception, see InnerException for details.
---- CSnakes.Runtime.PythonRuntimeException : No module named 'httpx'
   at CSnakes.Runtime.Python.PyObject..ctor(IntPtr pyObject, Boolean ownsHandle) in /_/src/CSnakes.Runtime/Python/PyObject.cs:line 19
   at CSnakes.Runtime.Python.PyObject.Create(IntPtr ptr) in /_/src/CSnakes.Runtime/Python/PyObject.cs:line 27
   at CSnakes.Runtime.CPython.CPythonAPI.Import(String name) in /_/src/CSnakes.Runtime/CPython/Import.cs:line 18
   at CSnakes.Runtime.Python.Import.ImportModule(String module) in /_/src/CSnakes.Runtime/Python/Import.cs:line 10
   at CSnakes.Runtime.TestSimpleExtensions.TestSimpleInternal..ctor(ILogger`1 logger) in /_/src/Conda.Tests/obj/Debug/net9.0/generated/CSnakes.SourceGeneration/CSnakes.PythonStaticGenerator/TestSimple.py.cs:line 52
   at CSnakes.Runtime.TestSimpleExtensions.TestSimple(IPythonEnvironment env) in /_/src/Conda.Tests/obj/Debug/net9.0/generated/CSnakes.SourceGeneration/CSnakes.PythonStaticGenerator/TestSimple.py.cs:line 28
   at Conda.Tests.BasicTests.TestSimpleImport() in /_/src/Conda.Tests/BasicTests.cs:line 8
   at System.RuntimeMethodHandle.InvokeMethod(Object target, Void** arguments, Signature sig, Boolean isConstructor)
   at System.Reflection.MethodBaseInvoker.InvokeWithNoArgs(Object obj, BindingFlags invokeAttr)
----- Inner Stack Trace -----
  File "/home/runner/work/CSnakes/CSnakes/src/Conda.Tests/bin/Debug/net9.0/python/test_simple.py", line 1, in <module>
    import httpx

Check failure on line 42 in src/CSnakes.Tests/PythonStaticGeneratorTests.cs

See this annotation in the file changed.

@github-actions github-actions / .NET Test report ubuntu-latest-3.13

CSnakes.Tests.PythonStaticGeneratorTests ► FormatClassFromMethods(resourceName: "CSnakes.Tests.python.test_coroutines.py")

Failed test found in:
  CSnakes.Tests-ubuntu-latest-3.13-net8.0.trx
  CSnakes.Tests-ubuntu-latest-3.13-net9.0.trx
Error:
  Shouldly.ShouldMatchApprovedException : To approve the changes run this command:
  cp "/home/runner/work/CSnakes/CSnakes/src/CSnakes.Tests/PythonStaticGeneratorTests/FormatClassFromMethods.test_coroutines.received.txt" "/home/runner/work/CSnakes/CSnakes/src/CSnakes.Tests/PythonStaticGeneratorTests/FormatClassFromMethods.test_coroutines.approved.txt"
  ----------------------------
  
  Approval file /home/runner/work/CSnakes/CSnakes/src/CSnakes.Tests/PythonStaticGeneratorTests/FormatClassFromMethods.test_coroutines.approved.txt
      does not exist
Raw output
Shouldly.ShouldMatchApprovedException : To approve the changes run this command:
cp "/home/runner/work/CSnakes/CSnakes/src/CSnakes.Tests/PythonStaticGeneratorTests/FormatClassFromMethods.test_coroutines.received.txt" "/home/runner/work/CSnakes/CSnakes/src/CSnakes.Tests/PythonStaticGeneratorTests/FormatClassFromMethods.test_coroutines.approved.txt"
----------------------------

Approval file /home/runner/work/CSnakes/CSnakes/src/CSnakes.Tests/PythonStaticGeneratorTests/FormatClassFromMethods.test_coroutines.approved.txt
    does not exist
   at CSnakes.Tests.PythonStaticGeneratorTests.FormatClassFromMethods(String resourceName) in /_/src/CSnakes.Tests/PythonStaticGeneratorTests.cs:line 42
   at InvokeStub_PythonStaticGeneratorTests.FormatClassFromMethods(Object, Span`1)
   at System.Reflection.MethodBaseInvoker.InvokeWithOneArg(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)

Check failure on line 42 in src/CSnakes.Tests/PythonStaticGeneratorTests.cs

See this annotation in the file changed.

@github-actions github-actions / .NET Test report ubuntu-latest-3.13

CSnakes.Tests.PythonStaticGeneratorTests ► FormatClassFromMethods(resourceName: "CSnakes.Tests.python.test_generators.py")

Failed test found in:
  CSnakes.Tests-ubuntu-latest-3.13-net8.0.trx
  CSnakes.Tests-ubuntu-latest-3.13-net9.0.trx
Error:
  Shouldly.ShouldMatchApprovedException : To approve the changes run this command:
  cp "/home/runner/work/CSnakes/CSnakes/src/CSnakes.Tests/PythonStaticGeneratorTests/FormatClassFromMethods.test_generators.received.txt" "/home/runner/work/CSnakes/CSnakes/src/CSnakes.Tests/PythonStaticGeneratorTests/FormatClassFromMethods.test_generators.approved.txt"
  ----------------------------
  
  compiledCode
      should match approved with options: Ignoring line endings
  "// <auto-generated/>
  #nullable enable
  
  using CSnakes.Runtime;
  using CSnakes.Runtime.Python;
  
  using System;
  using System.Collections.Generic;
  using System.Diagnostics;
  using System.Reflection.Metadata;
  
  using Microsoft.Extensions.Logging;
  
  [assembly: MetadataUpdateHandler(typeof(Python.Generated.Tests.TestClassExtensions))]
  
  namespace Python.Generated.Tests;
  
  public static class TestClassExtensions
  {
      private static ITestClass? instance;
  
      private static ReadOnlySpan<byte> HotReloadHash => "657bc350954200f5d7103a2587de60ae"u8;
  
      public static ITestClass TestClass(this IPythonEnvironment env)
      {
          if (instance is null)
          {
              instance = new TestClassInternal(env.Logger);
          }
          Debug.Assert(!env.IsDisposed());
          return instance;
      }
  
      public static void UpdateApplication(Type[]? updatedTypes)
      {
          instance?.ReloadModule();
      }
  
      private class TestClassInternal : ITestClass
      {
          private PyObject module;
          private readonly ILogger<IPythonEnvironment> logger;
  
          private PyObject __func_example_generator;
          private PyObject __func_test_normal_generator;
  
          internal TestClassInternal(ILogger<IPythonEnvironment> logger)
          {
              this.logger = logger;
              using (GIL.Acquire())
              {
                  logger.LogDebug("Importing module {ModuleName}", "test");
                  module = Import.ImportModule("test");
                  this.__func_example_generator = module.GetAttr("example_generator");
                  this.__func_test_normal_generator = module.GetAttr("test_normal_generator");
              }
          }
  
          void IReloadableModuleImport.ReloadModule()
          {
              logger.LogDebug("Reloading module {ModuleName}", "test");
              using (GIL.Acquire())
              {
                  Import.ReloadModule(ref module);
                  // Dispose old functions
                  this.__func_example_generator.Dispose();
                  this.__func_test_normal_generator.Dispose();
                  // Bind to new functions
                  this.__func_example_generator = module.GetAttr("example_generator");
                  this.__func_test_normal_generator = module.GetAttr("test_normal_generator");
              }
          }
  
          public void Dispose()
          {
              logger.LogDebug("Disposing module {ModuleName}", "test");
              this.__func_example_generator.Dispose();
              this.__func_test_normal_generator.Dispose();
              module.Dispose();
          }
  
          public IGeneratorIterator<string, long, bool> ExampleGenerator(long length)
          {
              using (GIL.Acquire())
              {
                  logger.LogDebug("Invoking Python function: {FunctionName}", "example_generator");
                  PyObject __underlyingPythonFunc = this.__func_example_generator;
                  using PyObject length_pyObject = PyObject.From(length)!;
                  using PyObject __result_pyObject = __underlyingPythonFunc.Call(length_pyObject);
                  return __result_pyObject.As<IGeneratorIterator<string, long, bool>>();
              }
          }
  
          public IGeneratorIterator<string, PyObject, PyObject> TestNormalGenerator()
          {
              using (GIL.Acquire())
              {
                  logger.LogDebug("Invoking Python function: {FunctionName}", "test_normal_generator");
                  PyObject __underlyingPythonFunc = this.__func_test_normal_generator;
                  using PyObject __result_pyObject = __underlyingPythonFunc.Call();
                  return __result_pyObject.As<IGeneratorIterator<string, PyObject, PyObject>>();
              }
          }
      }
  }
  
  /// <summary>
  /// Represents functions of the Python module <c>test</c>.
  /// </summary>
  public interface ITestClass : IReloadableModuleImport
  {
      /// <summary>
      /// Invokes the Python function <c>example_generator</c>:
      /// <code><![CDATA[
      /// def example_generator(length: int) -> Generator[str, int, bool]: ...
      /// ]]></code>
      /// </summary>
      IGeneratorIterator<string, long, bool> ExampleGenerator(long length);
  
      /// <summary>
      /// Invokes the Python function <c>test_normal_generator</c>:
      /// <code><![CDATA[
      /// def test_normal_generator() -> Generator[str, None, None]: ...
      /// ]]></code>
      /// </summary>
      IGeneratorIterator<string, PyObject, PyObject> TestNormalGenerator();
  }
  "
      but was
  "// <auto-generated/>
  #nullable enable
  
  using CSnakes.Runtime;
  using CSnakes.Runtime.Python;
  
  using System;
  using System.Collections.Generic;
  using System.Diagnostics;
  using System.Reflection.Metadata;
  
  using Microsoft.Extensions.Logging;
  
  [assembly: MetadataUpdateHandler(typeof(Python.Generated.Tests.TestClassExtensions))]
  
  namespace Python.Generated.Tests;
  
  public static class TestClassExtensions
  {
      private static ITestClass? instance;
  
      private static ReadOnlySpan<byte> HotReloadHash => "628447fb6935f7e3926b93b678146fc8"u8;
  
      public static ITestClass TestClass(this IPythonEnvironment env)
      {
          if (instance is null)
          {
              instance = new TestClassInternal(env.Logger);
          }
          Debug.Assert(!env.IsDisposed());
          return instance;
      }
  
      public static void UpdateApplication(Type[]? updatedTypes)
      {
          instance?.ReloadModule();
      }
  
      private class TestClassInternal : ITestClass
      {
          private PyObject module;
          private readonly ILogger<IPythonEnvironment> logger;
  
          private PyObject __func_example_generator;
          private PyObject __func_test_normal_generator;
          private PyObject __func_test_generator_sequence;
  
          internal TestClassInternal(ILogger<IPythonEnvironment> logger)
          {
              this.logger = logger;
              using (GIL.Acquire())
              {
                  logger.LogDebug("Importing module {ModuleName}", "test");
                  module = Import.ImportModule("test");
                  this.__func_example_generator = module.GetAttr("example_generator");
                  this.__func_test_normal_generator = module.GetAttr("test_normal_generator");
                  this.__func_test_generator_sequence = module.GetAttr("test_generator_sequence");
              }
          }
  
          void IReloadableModuleImport.ReloadModule()
          {
              logger.LogDebug("Reloading module {ModuleName}", "test");
              using (GIL.Acquire())
              {
                  Import.ReloadModule(ref module);
                  // Dispose old functions
                  this.__func_example_generator.Dispose();
                  this.__func_test_normal_generator.Dispose();
                  this.__func_test_generator_sequence.Dispose();
                  // Bind to new functions
                  this.__func_example_generator = module.GetAttr("example_generator");
                  this.__func_test_normal_generator = module.GetAttr("test_normal_generator");
                  this.__func_test_generator_sequence = module.GetAttr("test_generator_sequence");
              }
          }
  
          public void Dispose()
          {
              logger.LogDebug("Disposing module {ModuleName}", "test");
              this.__func_example_generator.Dispose();
              this.__func_test_normal_generator.Dispose();
              this.__func_test_generator_sequence.Dispose();
              module.Dispose();
          }
  
          public IGeneratorIterator<string, long, bool> ExampleGenerator(long length)
          {
              using (GIL.Acquire())
              {
                  logger.LogDebug("Invoking Python function: {FunctionName}", "example_generator");
                  PyObject __underlyingPythonFunc = this.__func_example_generator;
                  using PyObject length_pyObject = PyObject.From(length)!;
                  using PyObject __result_pyObject = __underlyingPythonFunc.Call(length_pyObject);
                  return __result_pyObject.As<IGeneratorIterator<string, long, bool>>();
              }
          }
  
          public IGeneratorIterator<string, PyObject, PyObject> TestNormalGenerator()
          {
              using (GIL.Acquire())
              {
                  logger.LogDebug("Invoking Python function: {FunctionName}", "test_normal_generator");
                  PyObject __underlyingPythonFunc = this.__func_test_normal_generator;
                  using PyObject __result_pyObject = __underlyingPythonFunc.Call();
                  return __result_pyObject.As<IGeneratorIterator<string, PyObject, PyObject>>();
              }
          }
  
          public IGeneratorIterator<string, PyObject, PyObject> TestGeneratorSequence()
          {
              using (GIL.Acquire())
              {
                  logger.LogDebug("Invoking Python function: {FunctionName}", "test_generator_sequence");
                  PyObject __underlyingPythonFunc = this.__func_test_generator_sequence;
                  using PyObject __result_pyObject = __underlyingPythonFunc.Call();
                  return __result_pyObject.As<IGeneratorIterator<string, PyObject, PyObject>>();
              }
          }
      }
  }
  
  /// <summary>
  /// Represents functions of the Python module <c>test</c>.
  /// </summary>
  public interface ITestClass : IReloadableModuleImport
  {
      /// <summary>
      /// Invokes the Python function <c>example_generator</c>:
      /// <code><![CDATA[
      /// def example_generator(length: int) -> Generator[str, int, bool]: ...
      /// ]]></code>
      /// </summary>
      IGeneratorIterator<string, long, "
      difference
  Showing some of the 3577 differences
  Difference     |       |    |    |    |    |    |    |    |    |    |    |    |    |    |    |    |    |    |    |    |    |        
                 |      \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/       
  Index          | ...  502  503  504  505  506  507  508  509  510  511  512  513  514  515  516  517  518  519  520  521  522  ...  
  Expected Value | ...  5    7    b    c    3    5    0    9    5    4    2    0    0    f    5    d    7    1    0    3    a    ...  
  Actual Value   | ...  2    8    4    4    7    f    b    6    9    3    5    f    7    e    3    9    2    6    b    9    3    ...  
  Expected Code  | ...  53   55   98   99   51   53   48   57   53   52   50   48   48   102  53   100  55   49   48   51   97   ...  
  Actual Code    | ...  50   56   52   52   55   102  98   54   57   51   53   102  55   101  51   57   50   54   98   57   51   ...  
  
  Difference     |       |    |    |    |    |    |    |    |    |    |    |    |         |    |    |                                 
                 |      \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/       \|/  \|/  \|/                                
  Index          | ...  517  518  519  520  521  522  523  524  525  526  527  528  529  530  531  532  533  534  535  536  537  ...  
  Expected Value | ...  d    7    1    0    3    a    2    5    8    7    d    e    6    0    a    e    "    u    8    ;    \n   ...  
  Actual Value   | ...  9    2    6    b    9    3    b    6    7    8    1    4    6    f    c    8    "    u    8    ;    \n   ...  
  Expected Code  | ...  100  55   49   48   51   97   50   53   56   55   100  101  54   48   97   101  34   117  56   59   10   ...  
  Actual Code    | ...  57   50   54   98   57   51   98   54   55   56   49   52   54   102  99   56   34   117  56   59   10   ...  
  
  Difference     |                                |    |    |    |    |    |    |    |    |    |    |    |    |    |    |    |        
                 |                               \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/       
  Index          | ...  1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 ...  
  Expected Value | ...  \s   \s   \s   \s   \s   \s   i    n    t    e    r    n    a    l    \s   T    e    s    t    C    l    ...  
  Actual Value   | ...  \s   \s   \s   \s   \s   p    r    i    v    a    t    e    \s   P    y    O    b    j    e    c    t    ...  
  Expected Code  | ...  32   32   32   32   32   32   105  110  116  101  114  110  97   108  32   84   101  115  116  67   108  ...  
  Actual Code    | ...  32   32   32   32   32   112  114  105  118  97   116  101  32   80   121  79   98   106  101  99   116  ...  
  
  Difference     |       |    |    |    |    |    |    |    |    |    |    |    |    |    |    |    |    |    |    |    |    |        
                 |      \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/       
  Index          | ...  1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 ...  
  Expected Value | ...  t    C    l    a    s    s    I    n    t    e    r    n    a    l    (    I    L    o    g    g    e    ...  
  Actual Value   | ...  e    c    t    \s   _    _    f    u    n    c    _    t    e    s    t    _    g    e    n    e    r    ...  
  Expected Code  | ...  116  67   108  97   115  115  73   110  116  101  114  110  97   108  40   73   76   111  103  103  101  ...  
  Actual Code    | ...  101  99   116  32   95   95   102  117  110  99   95   116  101  115  116  95   103  101  110  101  114  ...  
  
  Difference     |       |    |    |    |    |    |    |    |    |    |         |    |    |    |    |    |    |    |    |    |        
                 |      \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/       \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/       
  Index          | ...  1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 ...  
  Expected Value | ...  r    <    I    P    y    t    h    o    n    E    n    v    i    r    o    n    m    e    n    t    >    ...  
  Actual Value   | ...  a    t    o    r    _    s    e    q    u    e    n    c    e    ;    \n   \n   \s   \s   \s   \s   \s   ...  
  Expected Code  | ...  114  60   73   80   121  116  104  111  110  69   110  118  105  114  111  110  109  101  110  116  62   ...  
  Actual Code    | ...  97   116  111  114  95   115  101  113  117  101  110  99   101  59   10   10   32   32   32   32   32   ...  
  
  Difference     |       |    |    |    |    |    |    |    |    |    |         |    |    |    |    |    |    |    |    |    |        
                 |      \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/       \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/       
  Index          | ...  1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 ...  
  Expected Value | ...  l    o    g    g    e    r    )    \n   \s   \s   \s   \s   \s   \s   \s   \s   {    \n   \s   \s   \s   ...  
  Actual Value   | ...  \s   \s   i    n    t    e    r    n    a    l    \s   T    e    s    t    C    l    a    s    s    I    ...  
  Expected Code  | ...  108  111  103  103  101  114  41   10   32   32   32   32   32   32   32   32   123  10   32   32   32   ...  
  Actual Code    | ...  32   32   105  110  116  101  114  110  97   108  32   84   101  115  116  67   108  97   115  115  73   ...  
  
  Difference     |       |    |    |    |    |    |    |    |    |    |    |    |    |    |    |    |    |    |    |    |    |        
                 |      \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/       
  Index          | ...  1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 ...  
  Expected Value | ...  \s   \s   \s   \s   \s   \s   \s   \s   \s   t    h    i    s    .    l    o    g    g    e    r    \s   ...  
  Actual Value   | ...  n    t    e    r    n    a    l    (    I    L    o    g    g    e    r    <    I    P    y    t    h    ...  
  Expected Code  | ...  32   32   32   32   32   32   32   32   32   116  104  105  115  46   108  111  103  103  101  114  32   ...  
  Actual Code    | ...  110  116  101  114  110  97   108  40   73   76   111  103  103  101  114  60   73   80   121  116  104  ...  
  
  Difference     |       |    |    |    |    |    |    |    |    |    |    |    |    |    |         |    |    |    |    |    |        
                 |      \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/       \|/  \|/  \|/  \|/  \|/  \|/       
  Index          | ...  1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 ...  
  Expected Value | ...  =    \s   l    o    g    g    e    r    ;    \n   \s   \s   \s   \s   \s   \s   \s   \s   \s   \s   \s   ...  
  Actual Value   | ...  o    n    E    n    v    i    r    o    n    m    e    n    t    >    \s   l    o    g    g    e    r    ...  
  Expected Code  | ...  61   32   108  111  103  103  101  114  59   10   32   32   32   32   32   32   32   32   32   32   32   ...  
  Actual Code    | ...  111  110  69   110  118  105  114  111  110  109  101  110  116  62   32   108  111  103  103  101  114  ...  
  
  Difference     |       |    |    |    |    |    |         |    |    |    |    |    |    |    |    |    |    |    |    |    |        
                 |      \|/  \|/  \|/  \|/  \|/  \|/       \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/       
  Index          | ...  1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 ...  
  Expected Value | ...  \s   u    s    i    n    g    \s   (    G    I    L    .    A    c    q    u    i    r    e    (    )    ...  
  Actual Value   | ...  )    \n   \s   \s   \s   \s   \s   \s   \s   \s   {    \n   \s   \s   \s   \s   \s   \s   \s   \s   \s   ...  
  Expected Code  | ...  32   117  115  105  110  103  32   40   71   73   76   46   65   99   113  117  105  114  101  40   41   ...  
  Actual Code    | ...  41   10   32   32   32   32   32   32   32   32   123  10   32   32   32   32   32   32   32   32   32   ...  
  
  Difference     |       |    |         |    |    |    |    |    |    |    |    |    |    |    |    |         |    |    |    |        
                 |      \|/  \|/       \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/       \|/  \|/  \|/  \|/       
  Index          | ...  1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 ...  
  Expected Value | ...  )    \n   \s   \s   \s   \s   \s   \s   \s   \s   \s   \s   \s   \s   {    \n   \s   \s   \s   \s   \s   ...  
  Actual Value   | ...  \s   \s   \s   t    h    i    s    .    l    o    g    g    e    r    \s   =    \s   l    o    g    g    ...  
  Expected Code  | ...  41   10   32   32   32   32   32   32   32   32   32   32   32   32   123  10   32   32   32   32   32   ...  
  Actual Code    | ...  32   32   32   116  104  105  115  46   108  111  103  103  101  114  32   61   32   108  111  103  103  ...  
Raw output
Shouldly.ShouldMatchApprovedException : To approve the changes run this command:
cp "/home/runner/work/CSnakes/CSnakes/src/CSnakes.Tests/PythonStaticGeneratorTests/FormatClassFromMethods.test_generators.received.txt" "/home/runner/work/CSnakes/CSnakes/src/CSnakes.Tests/PythonStaticGeneratorTests/FormatClassFromMethods.test_generators.approved.txt"
----------------------------

compiledCode
    should match approved with options: Ignoring line endings
"// <auto-generated/>
#nullable enable

using CSnakes.Runtime;
using CSnakes.Runtime.Python;

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection.Metadata;

using Microsoft.Extensions.Logging;

[assembly: MetadataUpdateHandler(typeof(Python.Generated.Tests.TestClassExtensions))]

namespace Python.Generated.Tests;

public static class TestClassExtensions
{
    private static ITestClass? instance;

    private static ReadOnlySpan<byte> HotReloadHash => "657bc350954200f5d7103a2587de60ae"u8;

    public static ITestClass TestClass(this IPythonEnvironment env)
    {
        if (instance is null)
        {
            instance = new TestClassInternal(env.Logger);
        }
        Debug.Assert(!env.IsDisposed());
        return instance;
    }

    public static void UpdateApplication(Type[]? updatedTypes)
    {
        instance?.ReloadModule();
    }

    private class TestClassInternal : ITestClass
    {
        private PyObject module;
        private readonly ILogger<IPythonEnvironment> logger;

        private PyObject __func_example_generator;
        private PyObject __func_test_normal_generator;

        internal TestClassInternal(ILogger<IPythonEnvironment> logger)
        {
            this.logger = logger;
            using (GIL.Acquire())
            {
                logger.LogDebug("Importing module {ModuleName}", "test");
                module = Import.ImportModule("test");
                this.__func_example_generator = module.GetAttr("example_generator");
                this.__func_test_normal_generator = module.GetAttr("test_normal_generator");
            }
        }

        void IReloadableModuleImport.ReloadModule()
        {
            logger.LogDebug("Reloading module {ModuleName}", "test");
            using (GIL.Acquire())
            {
                Import.ReloadModule(ref module);
                // Dispose old functions
                this.__func_example_generator.Dispose();
                this.__func_test_normal_generator.Dispose();
                // Bind to new functions
                this.__func_example_generator = module.GetAttr("example_generator");
                this.__func_test_normal_generator = module.GetAttr("test_normal_generator");
            }
        }

        public void Dispose()
        {
            logger.LogDebug("Disposing module {ModuleName}", "test");
            this.__func_example_generator.Dispose();
            this.__func_test_normal_generator.Dispose();
            module.Dispose();
        }

        public IGeneratorIterator<string, long, bool> ExampleGenerator(long length)
        {
            using (GIL.Acquire())
            {
                logger.LogDebug("Invoking Python function: {FunctionName}", "example_generator");
                PyObject __underlyingPythonFunc = this.__func_example_generator;
                using PyObject length_pyObject = PyObject.From(length)!;
                using PyObject __result_pyObject = __underlyingPythonFunc.Call(length_pyObject);
                return __result_pyObject.As<IGeneratorIterator<string, long, bool>>();
            }
        }

        public IGeneratorIterator<string, PyObject, PyObject> TestNormalGenerator()
        {
            using (GIL.Acquire())
            {
                logger.LogDebug("Invoking Python function: {FunctionName}", "test_normal_generator");
                PyObject __underlyingPythonFunc = this.__func_test_normal_generator;
                using PyObject __result_pyObject = __underlyingPythonFunc.Call();
                return __result_pyObject.As<IGeneratorIterator<string, PyObject, PyObject>>();
            }
        }
    }
}

/// <summary>
/// Represents functions of the Python module <c>test</c>.
/// </summary>
public interface ITestClass : IReloadableModuleImport
{
    /// <summary>
    /// Invokes the Python function <c>example_generator</c>:
    /// <code><![CDATA[
    /// def example_generator(length: int) -> Generator[str, int, bool]: ...
    /// ]]></code>
    /// </summary>
    IGeneratorIterator<string, long, bool> ExampleGenerator(long length);

    /// <summary>
    /// Invokes the Python function <c>test_normal_generator</c>:
    /// <code><![CDATA[
    /// def test_normal_generator() -> Generator[str, None, None]: ...
    /// ]]></code>
    /// </summary>
    IGeneratorIterator<string, PyObject, PyObject> TestNormalGenerator();
}
"
    but was
"// <auto-generated/>
#nullable enable

using CSnakes.Runtime;
using CSnakes.Runtime.Python;

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection.Metadata;

using Microsoft.Extensions.Logging;

[assembly: MetadataUpdateHandler(typeof(Python.Generated.Tests.TestClassExtensions))]

namespace Python.Generated.Tests;

public static class TestClassExtensions
{
    private static ITestClass? instance;

    private static ReadOnlySpan<byte> HotReloadHash => "628447fb6935f7e3926b93b678146fc8"u8;

    public static ITestClass TestClass(this IPythonEnvironment env)
    {
        if (instance is null)
        {
            instance = new TestClassInternal(env.Logger);
        }
        Debug.Assert(!env.IsDisposed());
        return instance;
    }

    public static void UpdateApplication(Type[]? updatedTypes)
    {
        instance?.ReloadModule();
    }

    private class TestClassInternal : ITestClass
    {
        private PyObject module;
        private readonly ILogger<IPythonEnvironment> logger;

        private PyObject __func_example_generator;
        private PyObject __func_test_normal_generator;
        private PyObject __func_test_generator_sequence;

        internal TestClassInternal(ILogger<IPythonEnvironment> logger)
        {
            this.logger = logger;
            using (GIL.Acquire())
            {
                logger.LogDebug("Importing module {ModuleName}", "test");
                module = Import.ImportModule("test");
                this.__func_example_generator = module.GetAttr("example_generator");
                this.__func_test_normal_generator = module.GetAttr("test_normal_generator");
                this.__func_test_generator_sequence = module.GetAttr("test_generator_sequence");
            }
        }

        void IReloadableModuleImport.ReloadModule()
        {
            logger.LogDebug("Reloading module {ModuleName}", "test");
            using (GIL.Acquire())
            {
                Import.ReloadModule(ref module);
                // Dispose old functions
                this.__func_example_generator.Dispose();
                this.__func_test_normal_generator.Dispose();
                this.__func_test_generator_sequence.Dispose();
                // Bind to new functions
                this.__func_example_generator = module.GetAttr("example_generator");
                this.__func_test_normal_generator = module.GetAttr("test_normal_generator");
                this.__func_test_generator_sequence = module.GetAttr("test_generator_sequence");
            }
        }

        public void Dispose()
        {
            logger.LogDebug("Disposing module {ModuleName}", "test");
            this.__func_example_generator.Dispose();
            this.__func_test_normal_generator.Dispose();
            this.__func_test_generator_sequence.Dispose();
            module.Dispose();
        }

        public IGeneratorIterator<string, long, bool> ExampleGenerator(long length)
        {
            using (GIL.Acquire())
            {
                logger.LogDebug("Invoking Python function: {FunctionName}", "example_generator");
                PyObject __underlyingPythonFunc = this.__func_example_generator;
                using PyObject length_pyObject = PyObject.From(length)!;
                using PyObject __result_pyObject = __underlyingPythonFunc.Call(length_pyObject);
                return __result_pyObject.As<IGeneratorIterator<string, long, bool>>();
            }
        }

        public IGeneratorIterator<string, PyObject, PyObject> TestNormalGenerator()
        {
            using (GIL.Acquire())
            {
                logger.LogDebug("Invoking Python function: {FunctionName}", "test_normal_generator");
                PyObject __underlyingPythonFunc = this.__func_test_normal_generator;
                using PyObject __result_pyObject = __underlyingPythonFunc.Call();
                return __result_pyObject.As<IGeneratorIterator<string, PyObject, PyObject>>();
            }
        }

        public IGeneratorIterator<string, PyObject, PyObject> TestGeneratorSequence()
        {
            using (GIL.Acquire())
            {
                logger.LogDebug("Invoking Python function: {FunctionName}", "test_generator_sequence");
                PyObject __underlyingPythonFunc = this.__func_test_generator_sequence;
                using PyObject __result_pyObject = __underlyingPythonFunc.Call();
                return __result_pyObject.As<IGeneratorIterator<string, PyObject, PyObject>>();
            }
        }
    }
}

/// <summary>
/// Represents functions of the Python module <c>test</c>.
/// </summary>
public interface ITestClass : IReloadableModuleImport
{
    /// <summary>
    /// Invokes the Python function <c>example_generator</c>:
    /// <code><![CDATA[
    /// def example_generator(length: int) -> Generator[str, int, bool]: ...
    /// ]]></code>
    /// </summary>
    IGeneratorIterator<string, long, "
    difference
Showing some of the 3577 differences
Difference     |       |    |    |    |    |    |    |    |    |    |    |    |    |    |    |    |    |    |    |    |    |        
               |      \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/       
Index          | ...  502  503  504  505  506  507  508  509  510  511  512  513  514  515  516  517  518  519  520  521  522  ...  
Expected Value | ...  5    7    b    c    3    5    0    9    5    4    2    0    0    f    5    d    7    1    0    3    a    ...  
Actual Value   | ...  2    8    4    4    7    f    b    6    9    3    5    f    7    e    3    9    2    6    b    9    3    ...  
Expected Code  | ...  53   55   98   99   51   53   48   57   53   52   50   48   48   102  53   100  55   49   48   51   97   ...  
Actual Code    | ...  50   56   52   52   55   102  98   54   57   51   53   102  55   101  51   57   50   54   98   57   51   ...  

Difference     |       |    |    |    |    |    |    |    |    |    |    |    |         |    |    |                                 
               |      \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/       \|/  \|/  \|/                                
Index          | ...  517  518  519  520  521  522  523  524  525  526  527  528  529  530  531  532  533  534  535  536  537  ...  
Expected Value | ...  d    7    1    0    3    a    2    5    8    7    d    e    6    0    a    e    "    u    8    ;    \n   ...  
Actual Value   | ...  9    2    6    b    9    3    b    6    7    8    1    4    6    f    c    8    "    u    8    ;    \n   ...  
Expected Code  | ...  100  55   49   48   51   97   50   53   56   55   100  101  54   48   97   101  34   117  56   59   10   ...  
Actual Code    | ...  57   50   54   98   57   51   98   54   55   56   49   52   54   102  99   56   34   117  56   59   10   ...  

Difference     |                                |    |    |    |    |    |    |    |    |    |    |    |    |    |    |    |        
               |                               \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/       
Index          | ...  1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 ...  
Expected Value | ...  \s   \s   \s   \s   \s   \s   i    n    t    e    r    n    a    l    \s   T    e    s    t    C    l    ...  
Actual Value   | ...  \s   \s   \s   \s   \s   p    r    i    v    a    t    e    \s   P    y    O    b    j    e    c    t    ...  
Expected Code  | ...  32   32   32   32   32   32   105  110  116  101  114  110  97   108  32   84   101  115  116  67   108  ...  
Actual Code    | ...  32   32   32   32   32   112  114  105  118  97   116  101  32   80   121  79   98   106  101  99   116  ...  

Difference     |       |    |    |    |    |    |    |    |    |    |    |    |    |    |    |    |    |    |    |    |    |        
               |      \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/       
Index          | ...  1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 ...  
Expected Value | ...  t    C    l    a    s    s    I    n    t    e    r    n    a    l    (    I    L    o    g    g    e    ...  
Actual Value   | ...  e    c    t    \s   _    _    f    u    n    c    _    t    e    s    t    _    g    e    n    e    r    ...  
Expected Code  | ...  116  67   108  97   115  115  73   110  116  101  114  110  97   108  40   73   76   111  103  103  101  ...  
Actual Code    | ...  101  99   116  32   95   95   102  117  110  99   95   116  101  115  116  95   103  101  110  101  114  ...  

Difference     |       |    |    |    |    |    |    |    |    |    |         |    |    |    |    |    |    |    |    |    |        
               |      \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/       \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/       
Index          | ...  1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 ...  
Expected Value | ...  r    <    I    P    y    t    h    o    n    E    n    v    i    r    o    n    m    e    n    t    >    ...  
Actual Value   | ...  a    t    o    r    _    s    e    q    u    e    n    c    e    ;    \n   \n   \s   \s   \s   \s   \s   ...  
Expected Code  | ...  114  60   73   80   121  116  104  111  110  69   110  118  105  114  111  110  109  101  110  116  62   ...  
Actual Code    | ...  97   116  111  114  95   115  101  113  117  101  110  99   101  59   10   10   32   32   32   32   32   ...  

Difference     |       |    |    |    |    |    |    |    |    |    |         |    |    |    |    |    |    |    |    |    |        
               |      \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/       \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/       
Index          | ...  1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 ...  
Expected Value | ...  l    o    g    g    e    r    )    \n   \s   \s   \s   \s   \s   \s   \s   \s   {    \n   \s   \s   \s   ...  
Actual Value   | ...  \s   \s   i    n    t    e    r    n    a    l    \s   T    e    s    t    C    l    a    s    s    I    ...  
Expected Code  | ...  108  111  103  103  101  114  41   10   32   32   32   32   32   32   32   32   123  10   32   32   32   ...  
Actual Code    | ...  32   32   105  110  116  101  114  110  97   108  32   84   101  115  116  67   108  97   115  115  73   ...  

Difference     |       |    |    |    |    |    |    |    |    |    |    |    |    |    |    |    |    |    |    |    |    |        
               |      \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/       
Index          | ...  1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 ...  
Expected Value | ...  \s   \s   \s   \s   \s   \s   \s   \s   \s   t    h    i    s    .    l    o    g    g    e    r    \s   ...  
Actual Value   | ...  n    t    e    r    n    a    l    (    I    L    o    g    g    e    r    <    I    P    y    t    h    ...  
Expected Code  | ...  32   32   32   32   32   32   32   32   32   116  104  105  115  46   108  111  103  103  101  114  32   ...  
Actual Code    | ...  110  116  101  114  110  97   108  40   73   76   111  103  103  101  114  60   73   80   121  116  104  ...  

Difference     |       |    |    |    |    |    |    |    |    |    |    |    |    |    |         |    |    |    |    |    |        
               |      \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/       \|/  \|/  \|/  \|/  \|/  \|/       
Index          | ...  1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 ...  
Expected Value | ...  =    \s   l    o    g    g    e    r    ;    \n   \s   \s   \s   \s   \s   \s   \s   \s   \s   \s   \s   ...  
Actual Value   | ...  o    n    E    n    v    i    r    o    n    m    e    n    t    >    \s   l    o    g    g    e    r    ...  
Expected Code  | ...  61   32   108  111  103  103  101  114  59   10   32   32   32   32   32   32   32   32   32   32   32   ...  
Actual Code    | ...  111  110  69   110  118  105  114  111  110  109  101  110  116  62   32   108  111  103  103  101  114  ...  

Difference     |       |    |    |    |    |    |         |    |    |    |    |    |    |    |    |    |    |    |    |    |        
               |      \|/  \|/  \|/  \|/  \|/  \|/       \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/       
Index          | ...  1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 ...  
Expected Value | ...  \s   u    s    i    n    g    \s   (    G    I    L    .    A    c    q    u    i    r    e    (    )    ...  
Actual Value   | ...  )    \n   \s   \s   \s   \s   \s   \s   \s   \s   {    \n   \s   \s   \s   \s   \s   \s   \s   \s   \s   ...  
Expected Code  | ...  32   117  115  105  110  103  32   40   71   73   76   46   65   99   113  117  105  114  101  40   41   ...  
Actual Code    | ...  41   10   32   32   32   32   32   32   32   32   123  10   32   32   32   32   32   32   32   32   32   ...  

Difference     |       |    |         |    |    |    |    |    |    |    |    |    |    |    |    |         |    |    |    |        
               |      \|/  \|/       \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/  \|/       \|/  \|/  \|/  \|/       
Index          | ...  1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 ...  
Expected Value | ...  )    \n   \s   \s   \s   \s   \s   \s   \s   \s   \s   \s   \s   \s   {    \n   \s   \s   \s   \s   \s   ...  
Actual Value   | ...  \s   \s   \s   t    h    i    s    .    l    o    g    g    e    r    \s   =    \s   l    o    g    g    ...  
Expected Code  | ...  41   10   32   32   32   32   32   32   32   32   32   32   32   32   123  10   32   32   32   32   32   ...  
Actual Code    | ...  32   32   32   116  104  105  115  46   108  111  103  103  101  114  32   61   32   108  111  103  103  ...  
   at CSnakes.Tests.PythonStaticGeneratorTests.FormatClassFromMethods(String resourceName) in /_/src/CSnakes.Tests/PythonStaticGeneratorTests.cs:line 42
   at InvokeStub_PythonStaticGeneratorTests.FormatClassFromMethods(Object, Span`1)
   at System.Reflection.MethodBaseInvoker.InvokeWithOneArg(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)