Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/core/IronPython/Runtime/AsyncGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -103,9 +103,9 @@ public object asend(object? value) {
/// </remarks>
[LightThrowing]
public object athrow(object? type, object? value, object? traceback) {
if (PythonOps.ValidateThrowArguments(type, value) is Exception error) return LightExceptions.Throw(error);
if (PythonOps.ValidateThrowArguments(type, value, traceback) is Exception error) return LightExceptions.Throw(error);

Exception ex = PythonOps.MakeExceptionForGenerator(DefaultContext.Default, type, value, traceback, cause: null);
Exception ex = PythonOps.MakeExceptionForGenerator(DefaultContext.Default, type, value, traceback);
_started = true;
_throwSlot.Value = ex;
_sendSlot.Value = null;
Expand Down
7 changes: 3 additions & 4 deletions src/core/IronPython/Runtime/Coroutine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public sealed class PythonCoroutine : ICodeFormattable, IWeakReferenceable {
// _cts — CancellationTokenSource whose Token was passed into AsyncExpression. throw(exc) cancels this.
// _cancellationException — StrongBox<Exception?> shared with DriveAsync's `cancellationException` parameter;
// when non-null at cancellation time, that exception is surfaced to the body
// instead of OperationCanceledException.
// instead of OperationCanceledException.
//
// Lazy start: the body is not executed at construction. _factory is the thunk that creates (and thereby starts driving) the Task on
// first access; _task caches the materialized Task. Calling an async def is therefore side-effect free until the coroutine is first
Expand Down Expand Up @@ -98,13 +98,12 @@ public object send(object? value) {
[LightThrowing]
public object @throw(object? type, object? value, object? traceback) {
// Validate up front so we don't mutate any state on bad input.
if (PythonOps.ValidateThrowArguments(type, value) is Exception error) return LightExceptions.Throw(error);
if (PythonOps.ValidateThrowArguments(type, value, traceback) is Exception error) return LightExceptions.Throw(error);

// Construct the actual exception object. DefaultContext.Default suffices here — throw()'s
// CodeContext role is limited to resolving class-form exception construction, and the
// coroutine's own context will re-bind the chain when the exception unwinds inside the body.
Exception ex = PythonOps.MakeExceptionForGenerator(
DefaultContext.Default, type, value, traceback, cause: null);
Exception ex = PythonOps.MakeExceptionForGenerator(DefaultContext.Default, type, value, traceback);

var task = EnsureTask();
if (task.IsCompleted) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,8 @@ internal set {
}
}

internal BaseException? RawContext => _context;

public bool __suppress_context__ { get; set; }

public TraceBack? __traceback__ {
Expand Down
28 changes: 14 additions & 14 deletions src/core/IronPython/Runtime/Generator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public sealed class PythonGenerator : IEnumerator, IEnumerator<object>, ICodeFor

/// <summary>
/// Fields set by Throw() to communicate an exception to the yield point.
/// These are plumbed through the generator to become parameters to Raise(...) invoked
/// These are plumbed through the generator to become parameters to Raise(...) invoked
/// at the yield suspension point in the generator.
/// </summary>
private object?[]? _excInfo;
Expand Down Expand Up @@ -131,15 +131,15 @@ public object @throw(object? type, object? value, object? traceback) {

/// <summary>
/// Throw(...) is like Raise(...) being called from the yield point within the generator.
/// Note it must come from inside the generator so that the traceback matches, and so that it can
/// Note it must come from inside the generator so that the traceback matches, and so that it can
/// properly cooperate with any try/catch/finallys inside the generator body.
///
///
/// If the generator catches the exception and yields another value, that is the return value of g.throw().
/// </summary>
[LightThrowing]
private object @throw(object? type, object? value, object? traceback, bool finalizing) {
// Do argument validation outside of the generator's body and do not update the state on failure
if (PythonOps.ValidateThrowArguments(type, value) is Exception error) return LightExceptions.Throw(error);
if (PythonOps.ValidateThrowArguments(type, value, traceback) is Exception error) return LightExceptions.Throw(error);

// Pep explicitly says that Throw on a closed generator throws the exception,
// and not a StopIteration exception. (This is different than Next()).
Expand Down Expand Up @@ -172,7 +172,7 @@ private object @throw(object? type, object? value, object? traceback, bool final
return ThrowOnClosed();

object ThrowOnClosed()
=> LightExceptions.Throw(PythonOps.MakeExceptionForGenerator(Context, type, value, traceback, null));
=> LightExceptions.Throw(PythonOps.MakeExceptionForGenerator(Context, type, value, traceback));
}

/// <summary>
Expand Down Expand Up @@ -234,7 +234,7 @@ public object send(object? value) {
return lightEh;
}

// Generator should not have exited normally.
// Generator should not have exited normally.
return LightExceptions.Throw(new RuntimeException("generator ignored GeneratorExit"));
} catch (StopIterationException) {
// Ignore, clear any stack frames we built up
Expand Down Expand Up @@ -352,7 +352,7 @@ private void HandleFinalizerException(Exception e) {
// PEP says:
// If close() raises an exception, a traceback for the exception is printed to sys.stderr
// and further ignored; it is not propagated back to the place that
// triggered the garbage collection.
// triggered the garbage collection.

// Sample error message from CPython 2.5 looks like:
// Exception __main__.MyError: MyError() in <generator object at 0x00D7F6E8> ignored
Expand Down Expand Up @@ -491,7 +491,7 @@ private object NextWorker() {
// The generator body here may:
// 1. return an item: _next() returns true and 'next' is set to the next item in the enumeration.
// 2. Exit normally: _next returns false.
// 3. Exit with a StopIteration exception: for-loops and other enumeration consumers will
// 3. Exit with a StopIteration exception: for-loops and other enumeration consumers will
// catch this and terminate the loop without propogating the exception.
// 4. Exit via some other unhandled exception: This will close the generator, but the exception still propagates.
// _next does not return, so ret is left assigned to false (closed), which we detect in the finally.
Expand Down Expand Up @@ -557,7 +557,7 @@ private static void AlreadyExecuting() {
/// <returns></returns>
[LightThrowing]
internal object? CheckThrowableAndReturnSendValue() {
// Since this method is called from the generator body's execution, the generator must be running
// Since this method is called from the generator body's execution, the generator must be running
// and not closed.
Debug.Assert(!Closed);

Expand Down Expand Up @@ -595,9 +595,9 @@ private object ThrowThrowable() {
// Clear it so that any future Next()/MoveNext() call doesn't pick up the exception again.
_excInfo = null;

// This may invoke user code such as __init__, thus MakeException may throw.
// Since this is invoked from the generator's body, the generator can catch this exception.
return LightExceptions.Throw(PythonOps.MakeExceptionForGenerator(Context, throwableBackup[0], throwableBackup[1], throwableBackup[2], null));
// This may invoke user code such as __init__, thus MakeException may throw.
// Since this is invoked from the generator's body, the generator can catch this exception.
return LightExceptions.Throw(PythonOps.MakeExceptionForGenerator(Context, throwableBackup[0], throwableBackup[1], throwableBackup[2]));
}

private void Close() {
Expand Down Expand Up @@ -628,7 +628,7 @@ private bool Closed {

/// <summary>
/// True if the thread is currently inside the generator (ie, invoking the _next delegate).
/// This can be used to enforce that a generator does not call back into itself.
/// This can be used to enforce that a generator does not call back into itself.
/// Pep255 says that a generator should throw a ValueError if called reentrantly.
/// </summary>
private bool Active => Volatile.Read(ref _active) != 0;
Expand Down Expand Up @@ -719,7 +719,7 @@ public GeneratorFinalizer(PythonGenerator generator) {
var gen = Generator;
if (gen != null) {
Debug.Assert(gen._finalizer == this);
// We set this to null to indicate that the GeneratorFinalizer has been finalized,
// We set this to null to indicate that the GeneratorFinalizer has been finalized,
// and should not be reused (ie saved in PythonGenerator._LastFinalizer)
gen._finalizer = null;

Expand Down
Loading
Loading