summaryrefslogtreecommitdiff
path: root/venv/lib/python3.11/site-packages/greenlet
diff options
context:
space:
mode:
Diffstat (limited to 'venv/lib/python3.11/site-packages/greenlet')
-rw-r--r--venv/lib/python3.11/site-packages/greenlet/TBrokenGreenlet.cpp45
-rw-r--r--venv/lib/python3.11/site-packages/greenlet/TExceptionState.cpp62
-rw-r--r--venv/lib/python3.11/site-packages/greenlet/TGreenlet.cpp714
-rw-r--r--venv/lib/python3.11/site-packages/greenlet/TGreenletGlobals.cpp94
-rw-r--r--venv/lib/python3.11/site-packages/greenlet/TMainGreenlet.cpp155
-rw-r--r--venv/lib/python3.11/site-packages/greenlet/TPythonState.cpp375
-rw-r--r--venv/lib/python3.11/site-packages/greenlet/TStackState.cpp265
-rw-r--r--venv/lib/python3.11/site-packages/greenlet/TThreadStateDestroy.cpp195
-rw-r--r--venv/lib/python3.11/site-packages/greenlet/TUserGreenlet.cpp667
-rw-r--r--venv/lib/python3.11/site-packages/greenlet/__init__.py71
-rw-r--r--venv/lib/python3.11/site-packages/greenlet/__pycache__/__init__.cpython-311.pycbin1346 -> 0 bytes
-rwxr-xr-xvenv/lib/python3.11/site-packages/greenlet/_greenlet.cpython-311-x86_64-linux-gnu.sobin1506232 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/greenlet/greenlet.cpp1494
-rw-r--r--venv/lib/python3.11/site-packages/greenlet/greenlet.h164
-rw-r--r--venv/lib/python3.11/site-packages/greenlet/greenlet_allocator.hpp63
-rw-r--r--venv/lib/python3.11/site-packages/greenlet/greenlet_compiler_compat.hpp95
-rw-r--r--venv/lib/python3.11/site-packages/greenlet/greenlet_cpython_add_pending.hpp172
-rw-r--r--venv/lib/python3.11/site-packages/greenlet/greenlet_cpython_compat.hpp127
-rw-r--r--venv/lib/python3.11/site-packages/greenlet/greenlet_exceptions.hpp150
-rw-r--r--venv/lib/python3.11/site-packages/greenlet/greenlet_greenlet.hpp805
-rw-r--r--venv/lib/python3.11/site-packages/greenlet/greenlet_internal.hpp106
-rw-r--r--venv/lib/python3.11/site-packages/greenlet/greenlet_refs.hpp1100
-rw-r--r--venv/lib/python3.11/site-packages/greenlet/greenlet_slp_switch.hpp99
-rw-r--r--venv/lib/python3.11/site-packages/greenlet/greenlet_thread_state.hpp543
-rw-r--r--venv/lib/python3.11/site-packages/greenlet/greenlet_thread_state_dict_cleanup.hpp118
-rw-r--r--venv/lib/python3.11/site-packages/greenlet/greenlet_thread_support.hpp31
-rw-r--r--venv/lib/python3.11/site-packages/greenlet/platform/__init__.py0
-rw-r--r--venv/lib/python3.11/site-packages/greenlet/platform/__pycache__/__init__.cpython-311.pycbin201 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/greenlet/platform/setup_switch_x64_masm.cmd2
-rw-r--r--venv/lib/python3.11/site-packages/greenlet/platform/switch_aarch64_gcc.h124
-rw-r--r--venv/lib/python3.11/site-packages/greenlet/platform/switch_alpha_unix.h30
-rw-r--r--venv/lib/python3.11/site-packages/greenlet/platform/switch_amd64_unix.h87
-rw-r--r--venv/lib/python3.11/site-packages/greenlet/platform/switch_arm32_gcc.h79
-rw-r--r--venv/lib/python3.11/site-packages/greenlet/platform/switch_arm32_ios.h67
-rw-r--r--venv/lib/python3.11/site-packages/greenlet/platform/switch_arm64_masm.asm53
-rw-r--r--venv/lib/python3.11/site-packages/greenlet/platform/switch_arm64_masm.objbin746 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/greenlet/platform/switch_arm64_msvc.h17
-rw-r--r--venv/lib/python3.11/site-packages/greenlet/platform/switch_csky_gcc.h48
-rw-r--r--venv/lib/python3.11/site-packages/greenlet/platform/switch_loongarch64_linux.h31
-rw-r--r--venv/lib/python3.11/site-packages/greenlet/platform/switch_m68k_gcc.h38
-rw-r--r--venv/lib/python3.11/site-packages/greenlet/platform/switch_mips_unix.h64
-rw-r--r--venv/lib/python3.11/site-packages/greenlet/platform/switch_ppc64_aix.h103
-rw-r--r--venv/lib/python3.11/site-packages/greenlet/platform/switch_ppc64_linux.h105
-rw-r--r--venv/lib/python3.11/site-packages/greenlet/platform/switch_ppc_aix.h87
-rw-r--r--venv/lib/python3.11/site-packages/greenlet/platform/switch_ppc_linux.h84
-rw-r--r--venv/lib/python3.11/site-packages/greenlet/platform/switch_ppc_macosx.h82
-rw-r--r--venv/lib/python3.11/site-packages/greenlet/platform/switch_ppc_unix.h82
-rw-r--r--venv/lib/python3.11/site-packages/greenlet/platform/switch_riscv_unix.h32
-rw-r--r--venv/lib/python3.11/site-packages/greenlet/platform/switch_s390_unix.h87
-rw-r--r--venv/lib/python3.11/site-packages/greenlet/platform/switch_sparc_sun_gcc.h92
-rw-r--r--venv/lib/python3.11/site-packages/greenlet/platform/switch_x32_unix.h63
-rw-r--r--venv/lib/python3.11/site-packages/greenlet/platform/switch_x64_masm.asm111
-rw-r--r--venv/lib/python3.11/site-packages/greenlet/platform/switch_x64_masm.objbin1078 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/greenlet/platform/switch_x64_msvc.h60
-rw-r--r--venv/lib/python3.11/site-packages/greenlet/platform/switch_x86_msvc.h326
-rw-r--r--venv/lib/python3.11/site-packages/greenlet/platform/switch_x86_unix.h105
-rw-r--r--venv/lib/python3.11/site-packages/greenlet/slp_platformselect.h71
-rw-r--r--venv/lib/python3.11/site-packages/greenlet/tests/__init__.py237
-rw-r--r--venv/lib/python3.11/site-packages/greenlet/tests/__pycache__/__init__.cpython-311.pycbin9744 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/greenlet/tests/__pycache__/fail_clearing_run_switches.cpython-311.pycbin2405 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/greenlet/tests/__pycache__/fail_cpp_exception.cpython-311.pycbin1721 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/greenlet/tests/__pycache__/fail_initialstub_already_started.cpython-311.pycbin3881 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/greenlet/tests/__pycache__/fail_slp_switch.cpython-311.pycbin1432 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/greenlet/tests/__pycache__/fail_switch_three_greenlets.cpython-311.pycbin1898 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/greenlet/tests/__pycache__/fail_switch_three_greenlets2.cpython-311.pycbin2906 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/greenlet/tests/__pycache__/fail_switch_two_greenlets.cpython-311.pycbin1901 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/greenlet/tests/__pycache__/leakcheck.cpython-311.pycbin12777 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/greenlet/tests/__pycache__/test_contextvars.cpython-311.pycbin18611 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/greenlet/tests/__pycache__/test_cpp.cpython-311.pycbin4567 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/greenlet/tests/__pycache__/test_extension_interface.cpython-311.pycbin8576 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/greenlet/tests/__pycache__/test_gc.cpython-311.pycbin5518 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/greenlet/tests/__pycache__/test_generator.cpython-311.pycbin3540 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/greenlet/tests/__pycache__/test_generator_nested.cpython-311.pycbin9394 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/greenlet/tests/__pycache__/test_greenlet.cpython-311.pycbin86450 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/greenlet/tests/__pycache__/test_greenlet_trash.cpython-311.pycbin7015 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/greenlet/tests/__pycache__/test_leaks.cpython-311.pycbin21765 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/greenlet/tests/__pycache__/test_stack_saved.cpython-311.pycbin1514 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/greenlet/tests/__pycache__/test_throw.cpython-311.pycbin8934 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/greenlet/tests/__pycache__/test_tracing.cpython-311.pycbin15840 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/greenlet/tests/__pycache__/test_version.cpython-311.pycbin2927 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/greenlet/tests/__pycache__/test_weakref.cpython-311.pycbin3080 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/greenlet/tests/_test_extension.c231
-rwxr-xr-xvenv/lib/python3.11/site-packages/greenlet/tests/_test_extension.cpython-311-x86_64-linux-gnu.sobin36624 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/greenlet/tests/_test_extension_cpp.cpp226
-rwxr-xr-xvenv/lib/python3.11/site-packages/greenlet/tests/_test_extension_cpp.cpython-311-x86_64-linux-gnu.sobin57288 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/greenlet/tests/fail_clearing_run_switches.py47
-rw-r--r--venv/lib/python3.11/site-packages/greenlet/tests/fail_cpp_exception.py33
-rw-r--r--venv/lib/python3.11/site-packages/greenlet/tests/fail_initialstub_already_started.py78
-rw-r--r--venv/lib/python3.11/site-packages/greenlet/tests/fail_slp_switch.py29
-rw-r--r--venv/lib/python3.11/site-packages/greenlet/tests/fail_switch_three_greenlets.py44
-rw-r--r--venv/lib/python3.11/site-packages/greenlet/tests/fail_switch_three_greenlets2.py55
-rw-r--r--venv/lib/python3.11/site-packages/greenlet/tests/fail_switch_two_greenlets.py41
-rw-r--r--venv/lib/python3.11/site-packages/greenlet/tests/leakcheck.py319
-rw-r--r--venv/lib/python3.11/site-packages/greenlet/tests/test_contextvars.py310
-rw-r--r--venv/lib/python3.11/site-packages/greenlet/tests/test_cpp.py73
-rw-r--r--venv/lib/python3.11/site-packages/greenlet/tests/test_extension_interface.py115
-rw-r--r--venv/lib/python3.11/site-packages/greenlet/tests/test_gc.py86
-rw-r--r--venv/lib/python3.11/site-packages/greenlet/tests/test_generator.py59
-rw-r--r--venv/lib/python3.11/site-packages/greenlet/tests/test_generator_nested.py168
-rw-r--r--venv/lib/python3.11/site-packages/greenlet/tests/test_greenlet.py1311
-rw-r--r--venv/lib/python3.11/site-packages/greenlet/tests/test_greenlet_trash.py178
-rw-r--r--venv/lib/python3.11/site-packages/greenlet/tests/test_leaks.py443
-rw-r--r--venv/lib/python3.11/site-packages/greenlet/tests/test_stack_saved.py19
-rw-r--r--venv/lib/python3.11/site-packages/greenlet/tests/test_throw.py128
-rw-r--r--venv/lib/python3.11/site-packages/greenlet/tests/test_tracing.py291
-rw-r--r--venv/lib/python3.11/site-packages/greenlet/tests/test_version.py41
-rw-r--r--venv/lib/python3.11/site-packages/greenlet/tests/test_weakref.py35
107 files changed, 0 insertions, 14437 deletions
diff --git a/venv/lib/python3.11/site-packages/greenlet/TBrokenGreenlet.cpp b/venv/lib/python3.11/site-packages/greenlet/TBrokenGreenlet.cpp
deleted file mode 100644
index 11a3bea..0000000
--- a/venv/lib/python3.11/site-packages/greenlet/TBrokenGreenlet.cpp
+++ /dev/null
@@ -1,45 +0,0 @@
-/* -*- indent-tabs-mode: nil; tab-width: 4; -*- */
-/**
- * Implementation of greenlet::UserGreenlet.
- *
- * Format with:
- * clang-format -i --style=file src/greenlet/greenlet.c
- *
- *
- * Fix missing braces with:
- * clang-tidy src/greenlet/greenlet.c -fix -checks="readability-braces-around-statements"
-*/
-
-#include "greenlet_greenlet.hpp"
-
-namespace greenlet {
-
-void* BrokenGreenlet::operator new(size_t UNUSED(count))
-{
- return allocator.allocate(1);
-}
-
-
-void BrokenGreenlet::operator delete(void* ptr)
-{
- return allocator.deallocate(static_cast<BrokenGreenlet*>(ptr),
- 1);
-}
-
-greenlet::PythonAllocator<greenlet::BrokenGreenlet> greenlet::BrokenGreenlet::allocator;
-
-bool
-BrokenGreenlet::force_slp_switch_error() const noexcept
-{
- return this->_force_slp_switch_error;
-}
-
-UserGreenlet::switchstack_result_t BrokenGreenlet::g_switchstack(void)
-{
- if (this->_force_switch_error) {
- return switchstack_result_t(-1);
- }
- return UserGreenlet::g_switchstack();
-}
-
-}; //namespace greenlet
diff --git a/venv/lib/python3.11/site-packages/greenlet/TExceptionState.cpp b/venv/lib/python3.11/site-packages/greenlet/TExceptionState.cpp
deleted file mode 100644
index ee6b191..0000000
--- a/venv/lib/python3.11/site-packages/greenlet/TExceptionState.cpp
+++ /dev/null
@@ -1,62 +0,0 @@
-#ifndef GREENLET_EXCEPTION_STATE_CPP
-#define GREENLET_EXCEPTION_STATE_CPP
-
-#include <Python.h>
-#include "greenlet_greenlet.hpp"
-
-namespace greenlet {
-
-
-ExceptionState::ExceptionState()
-{
- this->clear();
-}
-
-void ExceptionState::operator<<(const PyThreadState *const tstate) noexcept
-{
- this->exc_info = tstate->exc_info;
- this->exc_state = tstate->exc_state;
-}
-
-void ExceptionState::operator>>(PyThreadState *const tstate) noexcept
-{
- tstate->exc_state = this->exc_state;
- tstate->exc_info =
- this->exc_info ? this->exc_info : &tstate->exc_state;
- this->clear();
-}
-
-void ExceptionState::clear() noexcept
-{
- this->exc_info = nullptr;
- this->exc_state.exc_value = nullptr;
-#if !GREENLET_PY311
- this->exc_state.exc_type = nullptr;
- this->exc_state.exc_traceback = nullptr;
-#endif
- this->exc_state.previous_item = nullptr;
-}
-
-int ExceptionState::tp_traverse(visitproc visit, void* arg) noexcept
-{
- Py_VISIT(this->exc_state.exc_value);
-#if !GREENLET_PY311
- Py_VISIT(this->exc_state.exc_type);
- Py_VISIT(this->exc_state.exc_traceback);
-#endif
- return 0;
-}
-
-void ExceptionState::tp_clear() noexcept
-{
- Py_CLEAR(this->exc_state.exc_value);
-#if !GREENLET_PY311
- Py_CLEAR(this->exc_state.exc_type);
- Py_CLEAR(this->exc_state.exc_traceback);
-#endif
-}
-
-
-}; // namespace greenlet
-
-#endif // GREENLET_EXCEPTION_STATE_CPP
diff --git a/venv/lib/python3.11/site-packages/greenlet/TGreenlet.cpp b/venv/lib/python3.11/site-packages/greenlet/TGreenlet.cpp
deleted file mode 100644
index 51f8995..0000000
--- a/venv/lib/python3.11/site-packages/greenlet/TGreenlet.cpp
+++ /dev/null
@@ -1,714 +0,0 @@
-/* -*- indent-tabs-mode: nil; tab-width: 4; -*- */
-/**
- * Implementation of greenlet::Greenlet.
- *
- * Format with:
- * clang-format -i --style=file src/greenlet/greenlet.c
- *
- *
- * Fix missing braces with:
- * clang-tidy src/greenlet/greenlet.c -fix -checks="readability-braces-around-statements"
-*/
-
-#include "greenlet_internal.hpp"
-#include "greenlet_greenlet.hpp"
-#include "greenlet_thread_state.hpp"
-
-#include "TGreenletGlobals.cpp"
-#include "TThreadStateDestroy.cpp"
-
-namespace greenlet {
-
-Greenlet::Greenlet(PyGreenlet* p)
-{
- p ->pimpl = this;
-}
-
-Greenlet::~Greenlet()
-{
- // XXX: Can't do this. tp_clear is a virtual function, and by the
- // time we're here, we've sliced off our child classes.
- //this->tp_clear();
-}
-
-Greenlet::Greenlet(PyGreenlet* p, const StackState& initial_stack)
- : stack_state(initial_stack)
-{
- // can't use a delegating constructor because of
- // MSVC for Python 2.7
- p->pimpl = this;
-}
-
-bool
-Greenlet::force_slp_switch_error() const noexcept
-{
- return false;
-}
-
-void
-Greenlet::release_args()
-{
- this->switch_args.CLEAR();
-}
-
-/**
- * CAUTION: This will allocate memory and may trigger garbage
- * collection and arbitrary Python code.
- */
-OwnedObject
-Greenlet::throw_GreenletExit_during_dealloc(const ThreadState& UNUSED(current_thread_state))
-{
- // If we're killed because we lost all references in the
- // middle of a switch, that's ok. Don't reset the args/kwargs,
- // we still want to pass them to the parent.
- PyErr_SetString(mod_globs->PyExc_GreenletExit,
- "Killing the greenlet because all references have vanished.");
- // To get here it had to have run before
- return this->g_switch();
-}
-
-inline void
-Greenlet::slp_restore_state() noexcept
-{
-#ifdef SLP_BEFORE_RESTORE_STATE
- SLP_BEFORE_RESTORE_STATE();
-#endif
- this->stack_state.copy_heap_to_stack(
- this->thread_state()->borrow_current()->stack_state);
-}
-
-
-inline int
-Greenlet::slp_save_state(char *const stackref) noexcept
-{
- // XXX: This used to happen in the middle, before saving, but
- // after finding the next owner. Does that matter? This is
- // only defined for Sparc/GCC where it flushes register
- // windows to the stack (I think)
-#ifdef SLP_BEFORE_SAVE_STATE
- SLP_BEFORE_SAVE_STATE();
-#endif
- return this->stack_state.copy_stack_to_heap(stackref,
- this->thread_state()->borrow_current()->stack_state);
-}
-
-/**
- * CAUTION: This will allocate memory and may trigger garbage
- * collection and arbitrary Python code.
- */
-OwnedObject
-Greenlet::on_switchstack_or_initialstub_failure(
- Greenlet* target,
- const Greenlet::switchstack_result_t& err,
- const bool target_was_me,
- const bool was_initial_stub)
-{
- // If we get here, either g_initialstub()
- // failed, or g_switchstack() failed. Either one of those
- // cases SHOULD leave us in the original greenlet with a valid stack.
- if (!PyErr_Occurred()) {
- PyErr_SetString(
- PyExc_SystemError,
- was_initial_stub
- ? "Failed to switch stacks into a greenlet for the first time."
- : "Failed to switch stacks into a running greenlet.");
- }
- this->release_args();
-
- if (target && !target_was_me) {
- target->murder_in_place();
- }
-
- assert(!err.the_new_current_greenlet);
- assert(!err.origin_greenlet);
- return OwnedObject();
-
-}
-
-OwnedGreenlet
-Greenlet::g_switchstack_success() noexcept
-{
- PyThreadState* tstate = PyThreadState_GET();
- // restore the saved state
- this->python_state >> tstate;
- this->exception_state >> tstate;
-
- // The thread state hasn't been changed yet.
- ThreadState* thread_state = this->thread_state();
- OwnedGreenlet result(thread_state->get_current());
- thread_state->set_current(this->self());
- //assert(thread_state->borrow_current().borrow() == this->_self);
- return result;
-}
-
-Greenlet::switchstack_result_t
-Greenlet::g_switchstack(void)
-{
- // if any of these assertions fail, it's likely because we
- // switched away and tried to switch back to us. Early stages of
- // switching are not reentrant because we re-use ``this->args()``.
- // Switching away would happen if we trigger a garbage collection
- // (by just using some Python APIs that happen to allocate Python
- // objects) and some garbage had weakref callbacks or __del__ that
- // switches (people don't write code like that by hand, but with
- // gevent it's possible without realizing it)
- assert(this->args() || PyErr_Occurred());
- { /* save state */
- if (this->thread_state()->is_current(this->self())) {
- // Hmm, nothing to do.
- // TODO: Does this bypass trace events that are
- // important?
- return switchstack_result_t(0,
- this, this->thread_state()->borrow_current());
- }
- BorrowedGreenlet current = this->thread_state()->borrow_current();
- PyThreadState* tstate = PyThreadState_GET();
-
- current->python_state << tstate;
- current->exception_state << tstate;
- this->python_state.will_switch_from(tstate);
- switching_thread_state = this;
- current->expose_frames();
- }
- assert(this->args() || PyErr_Occurred());
- // If this is the first switch into a greenlet, this will
- // return twice, once with 1 in the new greenlet, once with 0
- // in the origin.
- int err;
- if (this->force_slp_switch_error()) {
- err = -1;
- }
- else {
- err = slp_switch();
- }
-
- if (err < 0) { /* error */
- // Tested by
- // test_greenlet.TestBrokenGreenlets.test_failed_to_slp_switch_into_running
- //
- // It's not clear if it's worth trying to clean up and
- // continue here. Failing to switch stacks is a big deal which
- // may not be recoverable (who knows what state the stack is in).
- // Also, we've stolen references in preparation for calling
- // ``g_switchstack_success()`` and we don't have a clean
- // mechanism for backing that all out.
- Py_FatalError("greenlet: Failed low-level slp_switch(). The stack is probably corrupt.");
- }
-
- // No stack-based variables are valid anymore.
-
- // But the global is volatile so we can reload it without the
- // compiler caching it from earlier.
- Greenlet* greenlet_that_switched_in = switching_thread_state; // aka this
- switching_thread_state = nullptr;
- // except that no stack variables are valid, we would:
- // assert(this == greenlet_that_switched_in);
-
- // switchstack success is where we restore the exception state,
- // etc. It returns the origin greenlet because its convenient.
-
- OwnedGreenlet origin = greenlet_that_switched_in->g_switchstack_success();
- assert(greenlet_that_switched_in->args() || PyErr_Occurred());
- return switchstack_result_t(err, greenlet_that_switched_in, origin);
-}
-
-
-inline void
-Greenlet::check_switch_allowed() const
-{
- // TODO: Make this take a parameter of the current greenlet,
- // or current main greenlet, to make the check for
- // cross-thread switching cheaper. Surely somewhere up the
- // call stack we've already accessed the thread local variable.
-
- // We expect to always have a main greenlet now; accessing the thread state
- // created it. However, if we get here and cleanup has already
- // begun because we're a greenlet that was running in a
- // (now dead) thread, these invariants will not hold true. In
- // fact, accessing `this->thread_state` may not even be possible.
-
- // If the thread this greenlet was running in is dead,
- // we'll still have a reference to a main greenlet, but the
- // thread state pointer we have is bogus.
- // TODO: Give the objects an API to determine if they belong
- // to a dead thread.
-
- const BorrowedMainGreenlet main_greenlet = this->find_main_greenlet_in_lineage();
-
- if (!main_greenlet) {
- throw PyErrOccurred(mod_globs->PyExc_GreenletError,
- "cannot switch to a garbage collected greenlet");
- }
-
- if (!main_greenlet->thread_state()) {
- throw PyErrOccurred(mod_globs->PyExc_GreenletError,
- "cannot switch to a different thread (which happens to have exited)");
- }
-
- // The main greenlet we found was from the .parent lineage.
- // That may or may not have any relationship to the main
- // greenlet of the running thread. We can't actually access
- // our this->thread_state members to try to check that,
- // because it could be in the process of getting destroyed,
- // but setting the main_greenlet->thread_state member to NULL
- // may not be visible yet. So we need to check against the
- // current thread state (once the cheaper checks are out of
- // the way)
- const BorrowedMainGreenlet current_main_greenlet = GET_THREAD_STATE().state().borrow_main_greenlet();
- if (
- // lineage main greenlet is not this thread's greenlet
- current_main_greenlet != main_greenlet
- || (
- // atteched to some thread
- this->main_greenlet()
- // XXX: Same condition as above. Was this supposed to be
- // this->main_greenlet()?
- && current_main_greenlet != main_greenlet)
- // switching into a known dead thread (XXX: which, if we get here,
- // is bad, because we just accessed the thread state, which is
- // gone!)
- || (!current_main_greenlet->thread_state())) {
- // CAUTION: This may trigger memory allocations, gc, and
- // arbitrary Python code.
- throw PyErrOccurred(mod_globs->PyExc_GreenletError,
- "cannot switch to a different thread");
- }
-}
-
-const OwnedObject
-Greenlet::context() const
-{
- using greenlet::PythonStateContext;
- OwnedObject result;
-
- if (this->is_currently_running_in_some_thread()) {
- /* Currently running greenlet: context is stored in the thread state,
- not the greenlet object. */
- if (GET_THREAD_STATE().state().is_current(this->self())) {
- result = PythonStateContext::context(PyThreadState_GET());
- }
- else {
- throw ValueError(
- "cannot get context of a "
- "greenlet that is running in a different thread");
- }
- }
- else {
- /* Greenlet is not running: just return context. */
- result = this->python_state.context();
- }
- if (!result) {
- result = OwnedObject::None();
- }
- return result;
-}
-
-
-void
-Greenlet::context(BorrowedObject given)
-{
- using greenlet::PythonStateContext;
- if (!given) {
- throw AttributeError("can't delete context attribute");
- }
- if (given.is_None()) {
- /* "Empty context" is stored as NULL, not None. */
- given = nullptr;
- }
-
- //checks type, incrs refcnt
- greenlet::refs::OwnedContext context(given);
- PyThreadState* tstate = PyThreadState_GET();
-
- if (this->is_currently_running_in_some_thread()) {
- if (!GET_THREAD_STATE().state().is_current(this->self())) {
- throw ValueError("cannot set context of a greenlet"
- " that is running in a different thread");
- }
-
- /* Currently running greenlet: context is stored in the thread state,
- not the greenlet object. */
- OwnedObject octx = OwnedObject::consuming(PythonStateContext::context(tstate));
- PythonStateContext::context(tstate, context.relinquish_ownership());
- }
- else {
- /* Greenlet is not running: just set context. Note that the
- greenlet may be dead.*/
- this->python_state.context() = context;
- }
-}
-
-/**
- * CAUTION: May invoke arbitrary Python code.
- *
- * Figure out what the result of ``greenlet.switch(arg, kwargs)``
- * should be and transfers ownership of it to the left-hand-side.
- *
- * If switch() was just passed an arg tuple, then we'll just return that.
- * If only keyword arguments were passed, then we'll pass the keyword
- * argument dict. Otherwise, we'll create a tuple of (args, kwargs) and
- * return both.
- *
- * CAUTION: This may allocate a new tuple object, which may
- * cause the Python garbage collector to run, which in turn may
- * run arbitrary Python code that switches.
- */
-OwnedObject& operator<<=(OwnedObject& lhs, greenlet::SwitchingArgs& rhs) noexcept
-{
- // Because this may invoke arbitrary Python code, which could
- // result in switching back to us, we need to get the
- // arguments locally on the stack.
- assert(rhs);
- OwnedObject args = rhs.args();
- OwnedObject kwargs = rhs.kwargs();
- rhs.CLEAR();
- // We shouldn't be called twice for the same switch.
- assert(args || kwargs);
- assert(!rhs);
-
- if (!kwargs) {
- lhs = args;
- }
- else if (!PyDict_Size(kwargs.borrow())) {
- lhs = args;
- }
- else if (!PySequence_Length(args.borrow())) {
- lhs = kwargs;
- }
- else {
- // PyTuple_Pack allocates memory, may GC, may run arbitrary
- // Python code.
- lhs = OwnedObject::consuming(PyTuple_Pack(2, args.borrow(), kwargs.borrow()));
- }
- return lhs;
-}
-
-static OwnedObject
-g_handle_exit(const OwnedObject& greenlet_result)
-{
- if (!greenlet_result && mod_globs->PyExc_GreenletExit.PyExceptionMatches()) {
- /* catch and ignore GreenletExit */
- PyErrFetchParam val;
- PyErr_Fetch(PyErrFetchParam(), val, PyErrFetchParam());
- if (!val) {
- return OwnedObject::None();
- }
- return OwnedObject(val);
- }
-
- if (greenlet_result) {
- // package the result into a 1-tuple
- // PyTuple_Pack increments the reference of its arguments,
- // so we always need to decref the greenlet result;
- // the owner will do that.
- return OwnedObject::consuming(PyTuple_Pack(1, greenlet_result.borrow()));
- }
-
- return OwnedObject();
-}
-
-
-
-/**
- * May run arbitrary Python code.
- */
-OwnedObject
-Greenlet::g_switch_finish(const switchstack_result_t& err)
-{
- assert(err.the_new_current_greenlet == this);
-
- ThreadState& state = *this->thread_state();
- // Because calling the trace function could do arbitrary things,
- // including switching away from this greenlet and then maybe
- // switching back, we need to capture the arguments now so that
- // they don't change.
- OwnedObject result;
- if (this->args()) {
- result <<= this->args();
- }
- else {
- assert(PyErr_Occurred());
- }
- assert(!this->args());
- try {
- // Our only caller handles the bad error case
- assert(err.status >= 0);
- assert(state.borrow_current() == this->self());
- if (OwnedObject tracefunc = state.get_tracefunc()) {
- assert(result || PyErr_Occurred());
- g_calltrace(tracefunc,
- result ? mod_globs->event_switch : mod_globs->event_throw,
- err.origin_greenlet,
- this->self());
- }
- // The above could have invoked arbitrary Python code, but
- // it couldn't switch back to this object and *also*
- // throw an exception, so the args won't have changed.
-
- if (PyErr_Occurred()) {
- // We get here if we fell of the end of the run() function
- // raising an exception. The switch itself was
- // successful, but the function raised.
- // valgrind reports that memory allocated here can still
- // be reached after a test run.
- throw PyErrOccurred::from_current();
- }
- return result;
- }
- catch (const PyErrOccurred&) {
- /* Turn switch errors into switch throws */
- /* Turn trace errors into switch throws */
- this->release_args();
- throw;
- }
-}
-
-void
-Greenlet::g_calltrace(const OwnedObject& tracefunc,
- const greenlet::refs::ImmortalEventName& event,
- const BorrowedGreenlet& origin,
- const BorrowedGreenlet& target)
-{
- PyErrPieces saved_exc;
- try {
- TracingGuard tracing_guard;
- // TODO: We have saved the active exception (if any) that's
- // about to be raised. In the 'throw' case, we could provide
- // the exception to the tracefunction, which seems very helpful.
- tracing_guard.CallTraceFunction(tracefunc, event, origin, target);
- }
- catch (const PyErrOccurred&) {
- // In case of exceptions trace function is removed,
- // and any existing exception is replaced with the tracing
- // exception.
- GET_THREAD_STATE().state().set_tracefunc(Py_None);
- throw;
- }
-
- saved_exc.PyErrRestore();
- assert(
- (event == mod_globs->event_throw && PyErr_Occurred())
- || (event == mod_globs->event_switch && !PyErr_Occurred())
- );
-}
-
-void
-Greenlet::murder_in_place()
-{
- if (this->active()) {
- assert(!this->is_currently_running_in_some_thread());
- this->deactivate_and_free();
- }
-}
-
-inline void
-Greenlet::deactivate_and_free()
-{
- if (!this->active()) {
- return;
- }
- // Throw away any saved stack.
- this->stack_state = StackState();
- assert(!this->stack_state.active());
- // Throw away any Python references.
- // We're holding a borrowed reference to the last
- // frame we executed. Since we borrowed it, the
- // normal traversal, clear, and dealloc functions
- // ignore it, meaning it leaks. (The thread state
- // object can't find it to clear it when that's
- // deallocated either, because by definition if we
- // got an object on this list, it wasn't
- // running and the thread state doesn't have
- // this frame.)
- // So here, we *do* clear it.
- this->python_state.tp_clear(true);
-}
-
-bool
-Greenlet::belongs_to_thread(const ThreadState* thread_state) const
-{
- if (!this->thread_state() // not running anywhere, or thread
- // exited
- || !thread_state) { // same, or there is no thread state.
- return false;
- }
- return true;
-}
-
-
-void
-Greenlet::deallocing_greenlet_in_thread(const ThreadState* current_thread_state)
-{
- /* Cannot raise an exception to kill the greenlet if
- it is not running in the same thread! */
- if (this->belongs_to_thread(current_thread_state)) {
- assert(current_thread_state);
- // To get here it had to have run before
- /* Send the greenlet a GreenletExit exception. */
-
- // We don't care about the return value, only whether an
- // exception happened.
- this->throw_GreenletExit_during_dealloc(*current_thread_state);
- return;
- }
-
- // Not the same thread! Temporarily save the greenlet
- // into its thread's deleteme list, *if* it exists.
- // If that thread has already exited, and processed its pending
- // cleanup, we'll never be able to clean everything up: we won't
- // be able to raise an exception.
- // That's mostly OK! Since we can't add it to a list, our refcount
- // won't increase, and we'll go ahead with the DECREFs later.
- ThreadState *const thread_state = this->thread_state();
- if (thread_state) {
- thread_state->delete_when_thread_running(this->self());
- }
- else {
- // The thread is dead, we can't raise an exception.
- // We need to make it look non-active, though, so that dealloc
- // finishes killing it.
- this->deactivate_and_free();
- }
- return;
-}
-
-
-int
-Greenlet::tp_traverse(visitproc visit, void* arg)
-{
-
- int result;
- if ((result = this->exception_state.tp_traverse(visit, arg)) != 0) {
- return result;
- }
- //XXX: This is ugly. But so is handling everything having to do
- //with the top frame.
- bool visit_top_frame = this->was_running_in_dead_thread();
- // When true, the thread is dead. Our implicit weak reference to the
- // frame is now all that's left; we consider ourselves to
- // strongly own it now.
- if ((result = this->python_state.tp_traverse(visit, arg, visit_top_frame)) != 0) {
- return result;
- }
- return 0;
-}
-
-int
-Greenlet::tp_clear()
-{
- bool own_top_frame = this->was_running_in_dead_thread();
- this->exception_state.tp_clear();
- this->python_state.tp_clear(own_top_frame);
- return 0;
-}
-
-bool Greenlet::is_currently_running_in_some_thread() const
-{
- return this->stack_state.active() && !this->python_state.top_frame();
-}
-
-#if GREENLET_PY312
-void GREENLET_NOINLINE(Greenlet::expose_frames)()
-{
- if (!this->python_state.top_frame()) {
- return;
- }
-
- _PyInterpreterFrame* last_complete_iframe = nullptr;
- _PyInterpreterFrame* iframe = this->python_state.top_frame()->f_frame;
- while (iframe) {
- // We must make a copy before looking at the iframe contents,
- // since iframe might point to a portion of the greenlet's C stack
- // that was spilled when switching greenlets.
- _PyInterpreterFrame iframe_copy;
- this->stack_state.copy_from_stack(&iframe_copy, iframe, sizeof(*iframe));
- if (!_PyFrame_IsIncomplete(&iframe_copy)) {
- // If the iframe were OWNED_BY_CSTACK then it would always be
- // incomplete. Since it's not incomplete, it's not on the C stack
- // and we can access it through the original `iframe` pointer
- // directly. This is important since GetFrameObject might
- // lazily _create_ the frame object and we don't want the
- // interpreter to lose track of it.
- assert(iframe_copy.owner != FRAME_OWNED_BY_CSTACK);
-
- // We really want to just write:
- // PyFrameObject* frame = _PyFrame_GetFrameObject(iframe);
- // but _PyFrame_GetFrameObject calls _PyFrame_MakeAndSetFrameObject
- // which is not a visible symbol in libpython. The easiest
- // way to get a public function to call it is using
- // PyFrame_GetBack, which is defined as follows:
- // assert(frame != NULL);
- // assert(!_PyFrame_IsIncomplete(frame->f_frame));
- // PyFrameObject *back = frame->f_back;
- // if (back == NULL) {
- // _PyInterpreterFrame *prev = frame->f_frame->previous;
- // prev = _PyFrame_GetFirstComplete(prev);
- // if (prev) {
- // back = _PyFrame_GetFrameObject(prev);
- // }
- // }
- // return (PyFrameObject*)Py_XNewRef(back);
- if (!iframe->frame_obj) {
- PyFrameObject dummy_frame;
- _PyInterpreterFrame dummy_iframe;
- dummy_frame.f_back = nullptr;
- dummy_frame.f_frame = &dummy_iframe;
- // force the iframe to be considered complete without
- // needing to check its code object:
- dummy_iframe.owner = FRAME_OWNED_BY_GENERATOR;
- dummy_iframe.previous = iframe;
- assert(!_PyFrame_IsIncomplete(&dummy_iframe));
- // Drop the returned reference immediately; the iframe
- // continues to hold a strong reference
- Py_XDECREF(PyFrame_GetBack(&dummy_frame));
- assert(iframe->frame_obj);
- }
-
- // This is a complete frame, so make the last one of those we saw
- // point at it, bypassing any incomplete frames (which may have
- // been on the C stack) in between the two. We're overwriting
- // last_complete_iframe->previous and need that to be reversible,
- // so we store the original previous ptr in the frame object
- // (which we must have created on a previous iteration through
- // this loop). The frame object has a bunch of storage that is
- // only used when its iframe is OWNED_BY_FRAME_OBJECT, which only
- // occurs when the frame object outlives the frame's execution,
- // which can't have happened yet because the frame is currently
- // executing as far as the interpreter is concerned. So, we can
- // reuse it for our own purposes.
- assert(iframe->owner == FRAME_OWNED_BY_THREAD
- || iframe->owner == FRAME_OWNED_BY_GENERATOR);
- if (last_complete_iframe) {
- assert(last_complete_iframe->frame_obj);
- memcpy(&last_complete_iframe->frame_obj->_f_frame_data[0],
- &last_complete_iframe->previous, sizeof(void *));
- last_complete_iframe->previous = iframe;
- }
- last_complete_iframe = iframe;
- }
- // Frames that are OWNED_BY_FRAME_OBJECT are linked via the
- // frame's f_back while all others are linked via the iframe's
- // previous ptr. Since all the frames we traverse are running
- // as far as the interpreter is concerned, we don't have to
- // worry about the OWNED_BY_FRAME_OBJECT case.
- iframe = iframe_copy.previous;
- }
-
- // Give the outermost complete iframe a null previous pointer to
- // account for any potential incomplete/C-stack iframes between it
- // and the actual top-of-stack
- if (last_complete_iframe) {
- assert(last_complete_iframe->frame_obj);
- memcpy(&last_complete_iframe->frame_obj->_f_frame_data[0],
- &last_complete_iframe->previous, sizeof(void *));
- last_complete_iframe->previous = nullptr;
- }
-}
-#else
-void Greenlet::expose_frames()
-{
-
-}
-#endif
-
-}; // namespace greenlet
diff --git a/venv/lib/python3.11/site-packages/greenlet/TGreenletGlobals.cpp b/venv/lib/python3.11/site-packages/greenlet/TGreenletGlobals.cpp
deleted file mode 100644
index c71c963..0000000
--- a/venv/lib/python3.11/site-packages/greenlet/TGreenletGlobals.cpp
+++ /dev/null
@@ -1,94 +0,0 @@
-/* -*- indent-tabs-mode: nil; tab-width: 4; -*- */
-/**
- * Implementation of GreenletGlobals.
- *
- * Format with:
- * clang-format -i --style=file src/greenlet/greenlet.c
- *
- *
- * Fix missing braces with:
- * clang-tidy src/greenlet/greenlet.c -fix -checks="readability-braces-around-statements"
-*/
-#ifndef T_GREENLET_GLOBALS
-#define T_GREENLET_GLOBALS
-
-#include "greenlet_refs.hpp"
-#include "greenlet_exceptions.hpp"
-#include "greenlet_thread_support.hpp"
-#include "greenlet_thread_state.hpp"
-
-namespace greenlet {
-
-// This encapsulates what were previously module global "constants"
-// established at init time.
-// This is a step towards Python3 style module state that allows
-// reloading.
-//
-// In an earlier iteration of this code, we used placement new to be
-// able to allocate this object statically still, so that references
-// to its members don't incur an extra pointer indirection.
-// But under some scenarios, that could result in crashes at
-// shutdown because apparently the destructor was getting run twice?
-class GreenletGlobals
-{
-
-public:
- const greenlet::refs::ImmortalEventName event_switch;
- const greenlet::refs::ImmortalEventName event_throw;
- const greenlet::refs::ImmortalException PyExc_GreenletError;
- const greenlet::refs::ImmortalException PyExc_GreenletExit;
- const greenlet::refs::ImmortalObject empty_tuple;
- const greenlet::refs::ImmortalObject empty_dict;
- const greenlet::refs::ImmortalString str_run;
- Mutex* const thread_states_to_destroy_lock;
- greenlet::cleanup_queue_t thread_states_to_destroy;
-
- GreenletGlobals() :
- event_switch("switch"),
- event_throw("throw"),
- PyExc_GreenletError("greenlet.error"),
- PyExc_GreenletExit("greenlet.GreenletExit", PyExc_BaseException),
- empty_tuple(Require(PyTuple_New(0))),
- empty_dict(Require(PyDict_New())),
- str_run("run"),
- thread_states_to_destroy_lock(new Mutex())
- {}
-
- ~GreenletGlobals()
- {
- // This object is (currently) effectively immortal, and not
- // just because of those placement new tricks; if we try to
- // deallocate the static object we allocated, and overwrote,
- // we would be doing so at C++ teardown time, which is after
- // the final Python GIL is released, and we can't use the API
- // then.
- // (The members will still be destructed, but they also don't
- // do any deallocation.)
- }
-
- void queue_to_destroy(ThreadState* ts) const
- {
- // we're currently accessed through a static const object,
- // implicitly marking our members as const, so code can't just
- // call push_back (or pop_back) without casting away the
- // const.
- //
- // Do that for callers.
- greenlet::cleanup_queue_t& q = const_cast<greenlet::cleanup_queue_t&>(this->thread_states_to_destroy);
- q.push_back(ts);
- }
-
- ThreadState* take_next_to_destroy() const
- {
- greenlet::cleanup_queue_t& q = const_cast<greenlet::cleanup_queue_t&>(this->thread_states_to_destroy);
- ThreadState* result = q.back();
- q.pop_back();
- return result;
- }
-};
-
-}; // namespace greenlet
-
-static const greenlet::GreenletGlobals* mod_globs;
-
-#endif // T_GREENLET_GLOBALS
diff --git a/venv/lib/python3.11/site-packages/greenlet/TMainGreenlet.cpp b/venv/lib/python3.11/site-packages/greenlet/TMainGreenlet.cpp
deleted file mode 100644
index c33aadb..0000000
--- a/venv/lib/python3.11/site-packages/greenlet/TMainGreenlet.cpp
+++ /dev/null
@@ -1,155 +0,0 @@
-/* -*- indent-tabs-mode: nil; tab-width: 4; -*- */
-/**
- * Implementation of greenlet::MainGreenlet.
- *
- * Format with:
- * clang-format -i --style=file src/greenlet/greenlet.c
- *
- *
- * Fix missing braces with:
- * clang-tidy src/greenlet/greenlet.c -fix -checks="readability-braces-around-statements"
-*/
-
-#include "greenlet_greenlet.hpp"
-#include "greenlet_thread_state.hpp"
-
-
-// Protected by the GIL. Incremented when we create a main greenlet,
-// in a new thread, decremented when it is destroyed.
-static Py_ssize_t G_TOTAL_MAIN_GREENLETS;
-
-namespace greenlet {
-greenlet::PythonAllocator<MainGreenlet> MainGreenlet::allocator;
-
-void* MainGreenlet::operator new(size_t UNUSED(count))
-{
- return allocator.allocate(1);
-}
-
-
-void MainGreenlet::operator delete(void* ptr)
-{
- return allocator.deallocate(static_cast<MainGreenlet*>(ptr),
- 1);
-}
-
-
-MainGreenlet::MainGreenlet(PyGreenlet* p, ThreadState* state)
- : Greenlet(p, StackState::make_main()),
- _self(p),
- _thread_state(state)
-{
- G_TOTAL_MAIN_GREENLETS++;
-}
-
-MainGreenlet::~MainGreenlet()
-{
- G_TOTAL_MAIN_GREENLETS--;
- this->tp_clear();
-}
-
-ThreadState*
-MainGreenlet::thread_state() const noexcept
-{
- return this->_thread_state;
-}
-
-void
-MainGreenlet::thread_state(ThreadState* t) noexcept
-{
- assert(!t);
- this->_thread_state = t;
-}
-
-BorrowedGreenlet
-MainGreenlet::self() const noexcept
-{
- return BorrowedGreenlet(this->_self.borrow());
-}
-
-
-const BorrowedMainGreenlet
-MainGreenlet::main_greenlet() const
-{
- return this->_self;
-}
-
-BorrowedMainGreenlet
-MainGreenlet::find_main_greenlet_in_lineage() const
-{
- return BorrowedMainGreenlet(this->_self);
-}
-
-bool
-MainGreenlet::was_running_in_dead_thread() const noexcept
-{
- return !this->_thread_state;
-}
-
-OwnedObject
-MainGreenlet::g_switch()
-{
- try {
- this->check_switch_allowed();
- }
- catch (const PyErrOccurred&) {
- this->release_args();
- throw;
- }
-
- switchstack_result_t err = this->g_switchstack();
- if (err.status < 0) {
- // XXX: This code path is untested, but it is shared
- // with the UserGreenlet path that is tested.
- return this->on_switchstack_or_initialstub_failure(
- this,
- err,
- true, // target was me
- false // was initial stub
- );
- }
-
- return err.the_new_current_greenlet->g_switch_finish(err);
-}
-
-int
-MainGreenlet::tp_traverse(visitproc visit, void* arg)
-{
- if (this->_thread_state) {
- // we've already traversed main, (self), don't do it again.
- int result = this->_thread_state->tp_traverse(visit, arg, false);
- if (result) {
- return result;
- }
- }
- return Greenlet::tp_traverse(visit, arg);
-}
-
-const OwnedObject&
-MainGreenlet::run() const
-{
- throw AttributeError("Main greenlets do not have a run attribute.");
-}
-
-void
-MainGreenlet::run(const BorrowedObject UNUSED(nrun))
-{
- throw AttributeError("Main greenlets do not have a run attribute.");
-}
-
-void
-MainGreenlet::parent(const BorrowedObject raw_new_parent)
-{
- if (!raw_new_parent) {
- throw AttributeError("can't delete attribute");
- }
- throw AttributeError("cannot set the parent of a main greenlet");
-}
-
-const OwnedGreenlet
-MainGreenlet::parent() const
-{
- return OwnedGreenlet(); // null becomes None
-}
-
-}; // namespace greenlet
diff --git a/venv/lib/python3.11/site-packages/greenlet/TPythonState.cpp b/venv/lib/python3.11/site-packages/greenlet/TPythonState.cpp
deleted file mode 100644
index 465d417..0000000
--- a/venv/lib/python3.11/site-packages/greenlet/TPythonState.cpp
+++ /dev/null
@@ -1,375 +0,0 @@
-#ifndef GREENLET_PYTHON_STATE_CPP
-#define GREENLET_PYTHON_STATE_CPP
-
-#include <Python.h>
-#include "greenlet_greenlet.hpp"
-
-namespace greenlet {
-
-PythonState::PythonState()
- : _top_frame()
-#if GREENLET_USE_CFRAME
- ,cframe(nullptr)
- ,use_tracing(0)
-#endif
-#if GREENLET_PY312
- ,py_recursion_depth(0)
- ,c_recursion_depth(0)
-#else
- ,recursion_depth(0)
-#endif
- ,trash_delete_nesting(0)
-#if GREENLET_PY311
- ,current_frame(nullptr)
- ,datastack_chunk(nullptr)
- ,datastack_top(nullptr)
- ,datastack_limit(nullptr)
-#endif
-{
-#if GREENLET_USE_CFRAME
- /*
- The PyThreadState->cframe pointer usually points to memory on
- the stack, alloceted in a call into PyEval_EvalFrameDefault.
-
- Initially, before any evaluation begins, it points to the
- initial PyThreadState object's ``root_cframe`` object, which is
- statically allocated for the lifetime of the thread.
-
- A greenlet can last for longer than a call to
- PyEval_EvalFrameDefault, so we can't set its ``cframe`` pointer
- to be the current ``PyThreadState->cframe``; nor could we use
- one from the greenlet parent for the same reason. Yet a further
- no: we can't allocate one scoped to the greenlet and then
- destroy it when the greenlet is deallocated, because inside the
- interpreter the _PyCFrame objects form a linked list, and that too
- can result in accessing memory beyond its dynamic lifetime (if
- the greenlet doesn't actually finish before it dies, its entry
- could still be in the list).
-
- Using the ``root_cframe`` is problematic, though, because its
- members are never modified by the interpreter and are set to 0,
- meaning that its ``use_tracing`` flag is never updated. We don't
- want to modify that value in the ``root_cframe`` ourself: it
- *shouldn't* matter much because we should probably never get
- back to the point where that's the only cframe on the stack;
- even if it did matter, the major consequence of an incorrect
- value for ``use_tracing`` is that if its true the interpreter
- does some extra work --- however, it's just good code hygiene.
-
- Our solution: before a greenlet runs, after its initial
- creation, it uses the ``root_cframe`` just to have something to
- put there. However, once the greenlet is actually switched to
- for the first time, ``g_initialstub`` (which doesn't actually
- "return" while the greenlet is running) stores a new _PyCFrame on
- its local stack, and copies the appropriate values from the
- currently running _PyCFrame; this is then made the _PyCFrame for the
- newly-minted greenlet. ``g_initialstub`` then proceeds to call
- ``glet.run()``, which results in ``PyEval_...`` adding the
- _PyCFrame to the list. Switches continue as normal. Finally, when
- the greenlet finishes, the call to ``glet.run()`` returns and
- the _PyCFrame is taken out of the linked list and the stack value
- is now unused and free to expire.
-
- XXX: I think we can do better. If we're deallocing in the same
- thread, can't we traverse the list and unlink our frame?
- Can we just keep a reference to the thread state in case we
- dealloc in another thread? (Is that even possible if we're still
- running and haven't returned from g_initialstub?)
- */
- this->cframe = &PyThreadState_GET()->root_cframe;
-#endif
-}
-
-
-inline void PythonState::may_switch_away() noexcept
-{
-#if GREENLET_PY311
- // PyThreadState_GetFrame is probably going to have to allocate a
- // new frame object. That may trigger garbage collection. Because
- // we call this during the early phases of a switch (it doesn't
- // matter to which greenlet, as this has a global effect), if a GC
- // triggers a switch away, two things can happen, both bad:
- // - We might not get switched back to, halting forward progress.
- // this is pathological, but possible.
- // - We might get switched back to with a different set of
- // arguments or a throw instead of a switch. That would corrupt
- // our state (specifically, PyErr_Occurred() and this->args()
- // would no longer agree).
- //
- // Thus, when we call this API, we need to have GC disabled.
- // This method serves as a bottleneck we call when maybe beginning
- // a switch. In this way, it is always safe -- no risk of GC -- to
- // use ``_GetFrame()`` whenever we need to, just as it was in
- // <=3.10 (because subsequent calls will be cached and not
- // allocate memory).
-
- GCDisabledGuard no_gc;
- Py_XDECREF(PyThreadState_GetFrame(PyThreadState_GET()));
-#endif
-}
-
-void PythonState::operator<<(const PyThreadState *const tstate) noexcept
-{
- this->_context.steal(tstate->context);
-#if GREENLET_USE_CFRAME
- /*
- IMPORTANT: ``cframe`` is a pointer into the STACK. Thus, because
- the call to ``slp_switch()`` changes the contents of the stack,
- you cannot read from ``ts_current->cframe`` after that call and
- necessarily get the same values you get from reading it here.
- Anything you need to restore from now to then must be saved in a
- global/threadlocal variable (because we can't use stack
- variables here either). For things that need to persist across
- the switch, use `will_switch_from`.
- */
- this->cframe = tstate->cframe;
- #if !GREENLET_PY312
- this->use_tracing = tstate->cframe->use_tracing;
- #endif
-#endif // GREENLET_USE_CFRAME
-#if GREENLET_PY311
- #if GREENLET_PY312
- this->py_recursion_depth = tstate->py_recursion_limit - tstate->py_recursion_remaining;
- this->c_recursion_depth = C_RECURSION_LIMIT - tstate->c_recursion_remaining;
- #else // not 312
- this->recursion_depth = tstate->recursion_limit - tstate->recursion_remaining;
- #endif // GREENLET_PY312
- this->current_frame = tstate->cframe->current_frame;
- this->datastack_chunk = tstate->datastack_chunk;
- this->datastack_top = tstate->datastack_top;
- this->datastack_limit = tstate->datastack_limit;
-
- PyFrameObject *frame = PyThreadState_GetFrame((PyThreadState *)tstate);
- Py_XDECREF(frame); // PyThreadState_GetFrame gives us a new
- // reference.
- this->_top_frame.steal(frame);
- #if GREENLET_PY312
- this->trash_delete_nesting = tstate->trash.delete_nesting;
- #else // not 312
- this->trash_delete_nesting = tstate->trash_delete_nesting;
- #endif // GREENLET_PY312
-#else // Not 311
- this->recursion_depth = tstate->recursion_depth;
- this->_top_frame.steal(tstate->frame);
- this->trash_delete_nesting = tstate->trash_delete_nesting;
-#endif // GREENLET_PY311
-}
-
-#if GREENLET_PY312
-void GREENLET_NOINLINE(PythonState::unexpose_frames)()
-{
- if (!this->top_frame()) {
- return;
- }
-
- // See GreenletState::expose_frames() and the comment on frames_were_exposed
- // for more information about this logic.
- _PyInterpreterFrame *iframe = this->_top_frame->f_frame;
- while (iframe != nullptr) {
- _PyInterpreterFrame *prev_exposed = iframe->previous;
- assert(iframe->frame_obj);
- memcpy(&iframe->previous, &iframe->frame_obj->_f_frame_data[0],
- sizeof(void *));
- iframe = prev_exposed;
- }
-}
-#else
-void PythonState::unexpose_frames()
-{}
-#endif
-
-void PythonState::operator>>(PyThreadState *const tstate) noexcept
-{
- tstate->context = this->_context.relinquish_ownership();
- /* Incrementing this value invalidates the contextvars cache,
- which would otherwise remain valid across switches */
- tstate->context_ver++;
-#if GREENLET_USE_CFRAME
- tstate->cframe = this->cframe;
- /*
- If we were tracing, we need to keep tracing.
- There should never be the possibility of hitting the
- root_cframe here. See note above about why we can't
- just copy this from ``origin->cframe->use_tracing``.
- */
- #if !GREENLET_PY312
- tstate->cframe->use_tracing = this->use_tracing;
- #endif
-#endif // GREENLET_USE_CFRAME
-#if GREENLET_PY311
- #if GREENLET_PY312
- tstate->py_recursion_remaining = tstate->py_recursion_limit - this->py_recursion_depth;
- tstate->c_recursion_remaining = C_RECURSION_LIMIT - this->c_recursion_depth;
- this->unexpose_frames();
- #else // \/ 3.11
- tstate->recursion_remaining = tstate->recursion_limit - this->recursion_depth;
- #endif // GREENLET_PY312
- tstate->cframe->current_frame = this->current_frame;
- tstate->datastack_chunk = this->datastack_chunk;
- tstate->datastack_top = this->datastack_top;
- tstate->datastack_limit = this->datastack_limit;
- this->_top_frame.relinquish_ownership();
- #if GREENLET_PY312
- tstate->trash.delete_nesting = this->trash_delete_nesting;
- #else // not 3.12
- tstate->trash_delete_nesting = this->trash_delete_nesting;
- #endif // GREENLET_PY312
-#else // not 3.11
- tstate->frame = this->_top_frame.relinquish_ownership();
- tstate->recursion_depth = this->recursion_depth;
- tstate->trash_delete_nesting = this->trash_delete_nesting;
-#endif // GREENLET_PY311
-}
-
-inline void PythonState::will_switch_from(PyThreadState *const origin_tstate) noexcept
-{
-#if GREENLET_USE_CFRAME && !GREENLET_PY312
- // The weird thing is, we don't actually save this for an
- // effect on the current greenlet, it's saved for an
- // effect on the target greenlet. That is, we want
- // continuity of this setting across the greenlet switch.
- this->use_tracing = origin_tstate->cframe->use_tracing;
-#endif
-}
-
-void PythonState::set_initial_state(const PyThreadState* const tstate) noexcept
-{
- this->_top_frame = nullptr;
-#if GREENLET_PY312
- this->py_recursion_depth = tstate->py_recursion_limit - tstate->py_recursion_remaining;
- // XXX: TODO: Comment from a reviewer:
- // Should this be ``C_RECURSION_LIMIT - tstate->c_recursion_remaining``?
- // But to me it looks more like that might not be the right
- // initialization either?
- this->c_recursion_depth = tstate->py_recursion_limit - tstate->py_recursion_remaining;
-#elif GREENLET_PY311
- this->recursion_depth = tstate->recursion_limit - tstate->recursion_remaining;
-#else
- this->recursion_depth = tstate->recursion_depth;
-#endif
-}
-// TODO: Better state management about when we own the top frame.
-int PythonState::tp_traverse(visitproc visit, void* arg, bool own_top_frame) noexcept
-{
- Py_VISIT(this->_context.borrow());
- if (own_top_frame) {
- Py_VISIT(this->_top_frame.borrow());
- }
- return 0;
-}
-
-void PythonState::tp_clear(bool own_top_frame) noexcept
-{
- PythonStateContext::tp_clear();
- // If we get here owning a frame,
- // we got dealloc'd without being finished. We may or may not be
- // in the same thread.
- if (own_top_frame) {
- this->_top_frame.CLEAR();
- }
-}
-
-#if GREENLET_USE_CFRAME
-void PythonState::set_new_cframe(_PyCFrame& frame) noexcept
-{
- frame = *PyThreadState_GET()->cframe;
- /* Make the target greenlet refer to the stack value. */
- this->cframe = &frame;
- /*
- And restore the link to the previous frame so this one gets
- unliked appropriately.
- */
- this->cframe->previous = &PyThreadState_GET()->root_cframe;
-}
-#endif
-
-const PythonState::OwnedFrame& PythonState::top_frame() const noexcept
-{
- return this->_top_frame;
-}
-
-void PythonState::did_finish(PyThreadState* tstate) noexcept
-{
-#if GREENLET_PY311
- // See https://github.com/gevent/gevent/issues/1924 and
- // https://github.com/python-greenlet/greenlet/issues/328. In
- // short, Python 3.11 allocates memory for frames as a sort of
- // linked list that's kept as part of PyThreadState in the
- // ``datastack_chunk`` member and friends. These are saved and
- // restored as part of switching greenlets.
- //
- // When we initially switch to a greenlet, we set those to NULL.
- // That causes the frame management code to treat this like a
- // brand new thread and start a fresh list of chunks, beginning
- // with a new "root" chunk. As we make calls in this greenlet,
- // those chunks get added, and as calls return, they get popped.
- // But the frame code (pystate.c) is careful to make sure that the
- // root chunk never gets popped.
- //
- // Thus, when a greenlet exits for the last time, there will be at
- // least a single root chunk that we must be responsible for
- // deallocating.
- //
- // The complex part is that these chunks are allocated and freed
- // using ``_PyObject_VirtualAlloc``/``Free``. Those aren't public
- // functions, and they aren't exported for linking. It so happens
- // that we know they are just thin wrappers around the Arena
- // allocator, so we can use that directly to deallocate in a
- // compatible way.
- //
- // CAUTION: Check this implementation detail on every major version.
- //
- // It might be nice to be able to do this in our destructor, but
- // can we be sure that no one else is using that memory? Plus, as
- // described below, our pointers may not even be valid anymore. As
- // a special case, there is one time that we know we can do this,
- // and that's from the destructor of the associated UserGreenlet
- // (NOT main greenlet)
- PyObjectArenaAllocator alloc;
- _PyStackChunk* chunk = nullptr;
- if (tstate) {
- // We really did finish, we can never be switched to again.
- chunk = tstate->datastack_chunk;
- // Unfortunately, we can't do much sanity checking. Our
- // this->datastack_chunk pointer is out of date (evaluation may
- // have popped down through it already) so we can't verify that
- // we deallocate it. I don't think we can even check datastack_top
- // for the same reason.
-
- PyObject_GetArenaAllocator(&alloc);
- tstate->datastack_chunk = nullptr;
- tstate->datastack_limit = nullptr;
- tstate->datastack_top = nullptr;
-
- }
- else if (this->datastack_chunk) {
- // The UserGreenlet (NOT the main greenlet!) is being deallocated. If we're
- // still holding a stack chunk, it's garbage because we know
- // we can never switch back to let cPython clean it up.
- // Because the last time we got switched away from, and we
- // haven't run since then, we know our chain is valid and can
- // be dealloced.
- chunk = this->datastack_chunk;
- PyObject_GetArenaAllocator(&alloc);
- }
-
- if (alloc.free && chunk) {
- // In case the arena mechanism has been torn down already.
- while (chunk) {
- _PyStackChunk *prev = chunk->previous;
- chunk->previous = nullptr;
- alloc.free(alloc.ctx, chunk, chunk->size);
- chunk = prev;
- }
- }
-
- this->datastack_chunk = nullptr;
- this->datastack_limit = nullptr;
- this->datastack_top = nullptr;
-#endif
-}
-
-
-}; // namespace greenlet
-
-#endif // GREENLET_PYTHON_STATE_CPP
diff --git a/venv/lib/python3.11/site-packages/greenlet/TStackState.cpp b/venv/lib/python3.11/site-packages/greenlet/TStackState.cpp
deleted file mode 100644
index 9aab596..0000000
--- a/venv/lib/python3.11/site-packages/greenlet/TStackState.cpp
+++ /dev/null
@@ -1,265 +0,0 @@
-#ifndef GREENLET_STACK_STATE_CPP
-#define GREENLET_STACK_STATE_CPP
-
-#include "greenlet_greenlet.hpp"
-
-namespace greenlet {
-
-#ifdef GREENLET_USE_STDIO
-#include <iostream>
-using std::cerr;
-using std::endl;
-
-std::ostream& operator<<(std::ostream& os, const StackState& s)
-{
- os << "StackState(stack_start=" << (void*)s._stack_start
- << ", stack_stop=" << (void*)s.stack_stop
- << ", stack_copy=" << (void*)s.stack_copy
- << ", stack_saved=" << s._stack_saved
- << ", stack_prev=" << s.stack_prev
- << ", addr=" << &s
- << ")";
- return os;
-}
-#endif
-
-StackState::StackState(void* mark, StackState& current)
- : _stack_start(nullptr),
- stack_stop((char*)mark),
- stack_copy(nullptr),
- _stack_saved(0),
- /* Skip a dying greenlet */
- stack_prev(current._stack_start
- ? &current
- : current.stack_prev)
-{
-}
-
-StackState::StackState()
- : _stack_start(nullptr),
- stack_stop(nullptr),
- stack_copy(nullptr),
- _stack_saved(0),
- stack_prev(nullptr)
-{
-}
-
-StackState::StackState(const StackState& other)
-// can't use a delegating constructor because of
-// MSVC for Python 2.7
- : _stack_start(nullptr),
- stack_stop(nullptr),
- stack_copy(nullptr),
- _stack_saved(0),
- stack_prev(nullptr)
-{
- this->operator=(other);
-}
-
-StackState& StackState::operator=(const StackState& other)
-{
- if (&other == this) {
- return *this;
- }
- if (other._stack_saved) {
- throw std::runtime_error("Refusing to steal memory.");
- }
-
- //If we have memory allocated, dispose of it
- this->free_stack_copy();
-
- this->_stack_start = other._stack_start;
- this->stack_stop = other.stack_stop;
- this->stack_copy = other.stack_copy;
- this->_stack_saved = other._stack_saved;
- this->stack_prev = other.stack_prev;
- return *this;
-}
-
-inline void StackState::free_stack_copy() noexcept
-{
- PyMem_Free(this->stack_copy);
- this->stack_copy = nullptr;
- this->_stack_saved = 0;
-}
-
-inline void StackState::copy_heap_to_stack(const StackState& current) noexcept
-{
-
- /* Restore the heap copy back into the C stack */
- if (this->_stack_saved != 0) {
- memcpy(this->_stack_start, this->stack_copy, this->_stack_saved);
- this->free_stack_copy();
- }
- StackState* owner = const_cast<StackState*>(&current);
- if (!owner->_stack_start) {
- owner = owner->stack_prev; /* greenlet is dying, skip it */
- }
- while (owner && owner->stack_stop <= this->stack_stop) {
- // cerr << "\tOwner: " << owner << endl;
- owner = owner->stack_prev; /* find greenlet with more stack */
- }
- this->stack_prev = owner;
- // cerr << "\tFinished with: " << *this << endl;
-}
-
-inline int StackState::copy_stack_to_heap_up_to(const char* const stop) noexcept
-{
- /* Save more of g's stack into the heap -- at least up to 'stop'
- g->stack_stop |________|
- | |
- | __ stop . . . . .
- | | ==> . .
- |________| _______
- | | | |
- | | | |
- g->stack_start | | |_______| g->stack_copy
- */
- intptr_t sz1 = this->_stack_saved;
- intptr_t sz2 = stop - this->_stack_start;
- assert(this->_stack_start);
- if (sz2 > sz1) {
- char* c = (char*)PyMem_Realloc(this->stack_copy, sz2);
- if (!c) {
- PyErr_NoMemory();
- return -1;
- }
- memcpy(c + sz1, this->_stack_start + sz1, sz2 - sz1);
- this->stack_copy = c;
- this->_stack_saved = sz2;
- }
- return 0;
-}
-
-inline int StackState::copy_stack_to_heap(char* const stackref,
- const StackState& current) noexcept
-{
- /* must free all the C stack up to target_stop */
- const char* const target_stop = this->stack_stop;
-
- StackState* owner = const_cast<StackState*>(&current);
- assert(owner->_stack_saved == 0); // everything is present on the stack
- if (!owner->_stack_start) {
- owner = owner->stack_prev; /* not saved if dying */
- }
- else {
- owner->_stack_start = stackref;
- }
-
- while (owner->stack_stop < target_stop) {
- /* ts_current is entierely within the area to free */
- if (owner->copy_stack_to_heap_up_to(owner->stack_stop)) {
- return -1; /* XXX */
- }
- owner = owner->stack_prev;
- }
- if (owner != this) {
- if (owner->copy_stack_to_heap_up_to(target_stop)) {
- return -1; /* XXX */
- }
- }
- return 0;
-}
-
-inline bool StackState::started() const noexcept
-{
- return this->stack_stop != nullptr;
-}
-
-inline bool StackState::main() const noexcept
-{
- return this->stack_stop == (char*)-1;
-}
-
-inline bool StackState::active() const noexcept
-{
- return this->_stack_start != nullptr;
-}
-
-inline void StackState::set_active() noexcept
-{
- assert(this->_stack_start == nullptr);
- this->_stack_start = (char*)1;
-}
-
-inline void StackState::set_inactive() noexcept
-{
- this->_stack_start = nullptr;
- // XXX: What if we still have memory out there?
- // That case is actually triggered by
- // test_issue251_issue252_explicit_reference_not_collectable (greenlet.tests.test_leaks.TestLeaks)
- // and
- // test_issue251_issue252_need_to_collect_in_background
- // (greenlet.tests.test_leaks.TestLeaks)
- //
- // Those objects never get deallocated, so the destructor never
- // runs.
- // It *seems* safe to clean up the memory here?
- if (this->_stack_saved) {
- this->free_stack_copy();
- }
-}
-
-inline intptr_t StackState::stack_saved() const noexcept
-{
- return this->_stack_saved;
-}
-
-inline char* StackState::stack_start() const noexcept
-{
- return this->_stack_start;
-}
-
-
-inline StackState StackState::make_main() noexcept
-{
- StackState s;
- s._stack_start = (char*)1;
- s.stack_stop = (char*)-1;
- return s;
-}
-
-StackState::~StackState()
-{
- if (this->_stack_saved != 0) {
- this->free_stack_copy();
- }
-}
-
-void StackState::copy_from_stack(void* vdest, const void* vsrc, size_t n) const
-{
- char* dest = static_cast<char*>(vdest);
- const char* src = static_cast<const char*>(vsrc);
- if (src + n <= this->_stack_start
- || src >= this->_stack_start + this->_stack_saved
- || this->_stack_saved == 0) {
- // Nothing we're copying was spilled from the stack
- memcpy(dest, src, n);
- return;
- }
-
- if (src < this->_stack_start) {
- // Copy the part before the saved stack.
- // We know src + n > _stack_start due to the test above.
- const size_t nbefore = this->_stack_start - src;
- memcpy(dest, src, nbefore);
- dest += nbefore;
- src += nbefore;
- n -= nbefore;
- }
- // We know src >= _stack_start after the before-copy, and
- // src < _stack_start + _stack_saved due to the first if condition
- size_t nspilled = std::min<size_t>(n, this->_stack_start + this->_stack_saved - src);
- memcpy(dest, this->stack_copy + (src - this->_stack_start), nspilled);
- dest += nspilled;
- src += nspilled;
- n -= nspilled;
- if (n > 0) {
- // Copy the part after the saved stack
- memcpy(dest, src, n);
- }
-}
-
-}; // namespace greenlet
-
-#endif // GREENLET_STACK_STATE_CPP
diff --git a/venv/lib/python3.11/site-packages/greenlet/TThreadStateDestroy.cpp b/venv/lib/python3.11/site-packages/greenlet/TThreadStateDestroy.cpp
deleted file mode 100644
index a149a1a..0000000
--- a/venv/lib/python3.11/site-packages/greenlet/TThreadStateDestroy.cpp
+++ /dev/null
@@ -1,195 +0,0 @@
-/* -*- indent-tabs-mode: nil; tab-width: 4; -*- */
-/**
- * Implementation of the ThreadState destructors.
- *
- * Format with:
- * clang-format -i --style=file src/greenlet/greenlet.c
- *
- *
- * Fix missing braces with:
- * clang-tidy src/greenlet/greenlet.c -fix -checks="readability-braces-around-statements"
-*/
-#ifndef T_THREADSTATE_DESTROY
-#define T_THREADSTATE_DESTROY
-
-#include "greenlet_greenlet.hpp"
-#include "greenlet_thread_state.hpp"
-#include "greenlet_thread_support.hpp"
-#include "greenlet_cpython_add_pending.hpp"
-#include "TGreenletGlobals.cpp"
-
-namespace greenlet {
-
-struct ThreadState_DestroyWithGIL
-{
- ThreadState_DestroyWithGIL(ThreadState* state)
- {
- if (state && state->has_main_greenlet()) {
- DestroyWithGIL(state);
- }
- }
-
- static int
- DestroyWithGIL(ThreadState* state)
- {
- // Holding the GIL.
- // Passed a non-shared pointer to the actual thread state.
- // state -> main greenlet
- assert(state->has_main_greenlet());
- PyGreenlet* main(state->borrow_main_greenlet());
- // When we need to do cross-thread operations, we check this.
- // A NULL value means the thread died some time ago.
- // We do this here, rather than in a Python dealloc function
- // for the greenlet, in case there's still a reference out
- // there.
- static_cast<MainGreenlet*>(main->pimpl)->thread_state(nullptr);
-
- delete state; // Deleting this runs the destructor, DECREFs the main greenlet.
- return 0;
- }
-};
-
-
-
-struct ThreadState_DestroyNoGIL
-{
- // ensure this is actually defined.
- static_assert(GREENLET_BROKEN_PY_ADD_PENDING == 1 || GREENLET_BROKEN_PY_ADD_PENDING == 0,
- "GREENLET_BROKEN_PY_ADD_PENDING not defined correctly.");
-
-#if GREENLET_BROKEN_PY_ADD_PENDING
- static int _push_pending_call(struct _pending_calls *pending,
- int (*func)(void *), void *arg)
- {
- int i = pending->last;
- int j = (i + 1) % NPENDINGCALLS;
- if (j == pending->first) {
- return -1; /* Queue full */
- }
- pending->calls[i].func = func;
- pending->calls[i].arg = arg;
- pending->last = j;
- return 0;
- }
-
- static int AddPendingCall(int (*func)(void *), void *arg)
- {
- _PyRuntimeState *runtime = &_PyRuntime;
- if (!runtime) {
- // obviously impossible
- return 0;
- }
- struct _pending_calls *pending = &runtime->ceval.pending;
- if (!pending->lock) {
- return 0;
- }
- int result = 0;
- PyThread_acquire_lock(pending->lock, WAIT_LOCK);
- if (!pending->finishing) {
- result = _push_pending_call(pending, func, arg);
- }
- PyThread_release_lock(pending->lock);
- SIGNAL_PENDING_CALLS(&runtime->ceval);
- return result;
- }
-#else
- // Python < 3.8 or >= 3.9
- static int AddPendingCall(int (*func)(void*), void* arg)
- {
- return Py_AddPendingCall(func, arg);
- }
-#endif
-
- ThreadState_DestroyNoGIL(ThreadState* state)
- {
- // We are *NOT* holding the GIL. Our thread is in the middle
- // of its death throes and the Python thread state is already
- // gone so we can't use most Python APIs. One that is safe is
- // ``Py_AddPendingCall``, unless the interpreter itself has
- // been torn down. There is a limited number of calls that can
- // be queued: 32 (NPENDINGCALLS) in CPython 3.10, so we
- // coalesce these calls using our own queue.
- if (state && state->has_main_greenlet()) {
- // mark the thread as dead ASAP.
- // this is racy! If we try to throw or switch to a
- // greenlet from this thread from some other thread before
- // we clear the state pointer, it won't realize the state
- // is dead which can crash the process.
- PyGreenlet* p = state->borrow_main_greenlet();
- assert(p->pimpl->thread_state() == state || p->pimpl->thread_state() == nullptr);
- static_cast<MainGreenlet*>(p->pimpl)->thread_state(nullptr);
- }
-
- // NOTE: Because we're not holding the GIL here, some other
- // Python thread could run and call ``os.fork()``, which would
- // be bad if that happenend while we are holding the cleanup
- // lock (it wouldn't function in the child process).
- // Make a best effort to try to keep the duration we hold the
- // lock short.
- // TODO: On platforms that support it, use ``pthread_atfork`` to
- // drop this lock.
- LockGuard cleanup_lock(*mod_globs->thread_states_to_destroy_lock);
-
- if (state && state->has_main_greenlet()) {
- // Because we don't have the GIL, this is a race condition.
- if (!PyInterpreterState_Head()) {
- // We have to leak the thread state, if the
- // interpreter has shut down when we're getting
- // deallocated, we can't run the cleanup code that
- // deleting it would imply.
- return;
- }
-
- mod_globs->queue_to_destroy(state);
- if (mod_globs->thread_states_to_destroy.size() == 1) {
- // We added the first item to the queue. We need to schedule
- // the cleanup.
- int result = ThreadState_DestroyNoGIL::AddPendingCall(
- ThreadState_DestroyNoGIL::DestroyQueueWithGIL,
- NULL);
- if (result < 0) {
- // Hmm, what can we do here?
- fprintf(stderr,
- "greenlet: WARNING: failed in call to Py_AddPendingCall; "
- "expect a memory leak.\n");
- }
- }
- }
- }
-
- static int
- DestroyQueueWithGIL(void* UNUSED(arg))
- {
- // We're holding the GIL here, so no Python code should be able to
- // run to call ``os.fork()``.
- while (1) {
- ThreadState* to_destroy;
- {
- LockGuard cleanup_lock(*mod_globs->thread_states_to_destroy_lock);
- if (mod_globs->thread_states_to_destroy.empty()) {
- break;
- }
- to_destroy = mod_globs->take_next_to_destroy();
- }
- // Drop the lock while we do the actual deletion.
- ThreadState_DestroyWithGIL::DestroyWithGIL(to_destroy);
- }
- return 0;
- }
-
-};
-
-}; // namespace greenlet
-
-// The intent when GET_THREAD_STATE() is needed multiple times in a
-// function is to take a reference to its return value in a local
-// variable, to avoid the thread-local indirection. On some platforms
-// (macOS), accessing a thread-local involves a function call (plus an
-// initial function call in each function that uses a thread local);
-// in contrast, static volatile variables are at some pre-computed
-// offset.
-typedef greenlet::ThreadStateCreator<greenlet::ThreadState_DestroyNoGIL> ThreadStateCreator;
-static thread_local ThreadStateCreator g_thread_state_global;
-#define GET_THREAD_STATE() g_thread_state_global
-
-#endif //T_THREADSTATE_DESTROY
diff --git a/venv/lib/python3.11/site-packages/greenlet/TUserGreenlet.cpp b/venv/lib/python3.11/site-packages/greenlet/TUserGreenlet.cpp
deleted file mode 100644
index 495a794..0000000
--- a/venv/lib/python3.11/site-packages/greenlet/TUserGreenlet.cpp
+++ /dev/null
@@ -1,667 +0,0 @@
-/* -*- indent-tabs-mode: nil; tab-width: 4; -*- */
-/**
- * Implementation of greenlet::UserGreenlet.
- *
- * Format with:
- * clang-format -i --style=file src/greenlet/greenlet.c
- *
- *
- * Fix missing braces with:
- * clang-tidy src/greenlet/greenlet.c -fix -checks="readability-braces-around-statements"
-*/
-
-#include "greenlet_internal.hpp"
-#include "greenlet_greenlet.hpp"
-#include "greenlet_thread_state.hpp"
-#include "TThreadStateDestroy.cpp"
-
-
-namespace greenlet {
-using greenlet::refs::BorrowedMainGreenlet;
-greenlet::PythonAllocator<UserGreenlet> UserGreenlet::allocator;
-
-void* UserGreenlet::operator new(size_t UNUSED(count))
-{
- return allocator.allocate(1);
-}
-
-
-void UserGreenlet::operator delete(void* ptr)
-{
- return allocator.deallocate(static_cast<UserGreenlet*>(ptr),
- 1);
-}
-
-
-UserGreenlet::UserGreenlet(PyGreenlet* p, BorrowedGreenlet the_parent)
- : Greenlet(p), _parent(the_parent)
-{
- this->_self = p;
-}
-
-UserGreenlet::~UserGreenlet()
-{
- // Python 3.11: If we don't clear out the raw frame datastack
- // when deleting an unfinished greenlet,
- // TestLeaks.test_untracked_memory_doesnt_increase_unfinished_thread_dealloc_in_main fails.
- this->python_state.did_finish(nullptr);
- this->tp_clear();
-}
-
-BorrowedGreenlet
-UserGreenlet::self() const noexcept
-{
- return this->_self;
-}
-
-
-
-const BorrowedMainGreenlet
-UserGreenlet::main_greenlet() const
-{
- return this->_main_greenlet;
-}
-
-
-BorrowedMainGreenlet
-UserGreenlet::find_main_greenlet_in_lineage() const
-{
- if (this->started()) {
- assert(this->_main_greenlet);
- return BorrowedMainGreenlet(this->_main_greenlet);
- }
-
- if (!this->_parent) {
- /* garbage collected greenlet in chain */
- // XXX: WHAT?
- return BorrowedMainGreenlet(nullptr);
- }
-
- return this->_parent->find_main_greenlet_in_lineage();
-}
-
-
-/**
- * CAUTION: This will allocate memory and may trigger garbage
- * collection and arbitrary Python code.
- */
-OwnedObject
-UserGreenlet::throw_GreenletExit_during_dealloc(const ThreadState& current_thread_state)
-{
- /* The dying greenlet cannot be a parent of ts_current
- because the 'parent' field chain would hold a
- reference */
- UserGreenlet::ParentIsCurrentGuard with_current_parent(this, current_thread_state);
-
- // We don't care about the return value, only whether an
- // exception happened. Whether or not an exception happens,
- // we need to restore the parent in case the greenlet gets
- // resurrected.
- return Greenlet::throw_GreenletExit_during_dealloc(current_thread_state);
-}
-
-ThreadState*
-UserGreenlet::thread_state() const noexcept
-{
- // TODO: maybe make this throw, if the thread state isn't there?
- // if (!this->main_greenlet) {
- // throw std::runtime_error("No thread state"); // TODO: Better exception
- // }
- if (!this->_main_greenlet) {
- return nullptr;
- }
- return this->_main_greenlet->thread_state();
-}
-
-
-bool
-UserGreenlet::was_running_in_dead_thread() const noexcept
-{
- return this->_main_greenlet && !this->thread_state();
-}
-
-OwnedObject
-UserGreenlet::g_switch()
-{
- assert(this->args() || PyErr_Occurred());
-
- try {
- this->check_switch_allowed();
- }
- catch (const PyErrOccurred&) {
- this->release_args();
- throw;
- }
-
- // Switching greenlets used to attempt to clean out ones that need
- // deleted *if* we detected a thread switch. Should it still do
- // that?
- // An issue is that if we delete a greenlet from another thread,
- // it gets queued to this thread, and ``kill_greenlet()`` switches
- // back into the greenlet
-
- /* find the real target by ignoring dead greenlets,
- and if necessary starting a greenlet. */
- switchstack_result_t err;
- Greenlet* target = this;
- // TODO: probably cleaner to handle the case where we do
- // switch to ourself separately from the other cases.
- // This can probably even further be simplified if we keep
- // track of the switching_state we're going for and just call
- // into g_switch() if it's not ourself. The main problem with that
- // is that we would be using more stack space.
- bool target_was_me = true;
- bool was_initial_stub = false;
- while (target) {
- if (target->active()) {
- if (!target_was_me) {
- target->args() <<= this->args();
- assert(!this->args());
- }
- err = target->g_switchstack();
- break;
- }
- if (!target->started()) {
- // We never encounter a main greenlet that's not started.
- assert(!target->main());
- UserGreenlet* real_target = static_cast<UserGreenlet*>(target);
- assert(real_target);
- void* dummymarker;
- was_initial_stub = true;
- if (!target_was_me) {
- target->args() <<= this->args();
- assert(!this->args());
- }
- try {
- // This can only throw back to us while we're
- // still in this greenlet. Once the new greenlet
- // is bootstrapped, it has its own exception state.
- err = real_target->g_initialstub(&dummymarker);
- }
- catch (const PyErrOccurred&) {
- this->release_args();
- throw;
- }
- catch (const GreenletStartedWhileInPython&) {
- // The greenlet was started sometime before this
- // greenlet actually switched to it, i.e.,
- // "concurrent" calls to switch() or throw().
- // We need to retry the switch.
- // Note that the current greenlet has been reset
- // to this one (or we wouldn't be running!)
- continue;
- }
- break;
- }
-
- target = target->parent();
- target_was_me = false;
- }
- // The ``this`` pointer and all other stack or register based
- // variables are invalid now, at least where things succeed
- // above.
- // But this one, probably not so much? It's not clear if it's
- // safe to throw an exception at this point.
-
- if (err.status < 0) {
- // If we get here, either g_initialstub()
- // failed, or g_switchstack() failed. Either one of those
- // cases SHOULD leave us in the original greenlet with a valid
- // stack.
- return this->on_switchstack_or_initialstub_failure(target, err, target_was_me, was_initial_stub);
- }
-
- // err.the_new_current_greenlet would be the same as ``target``,
- // if target wasn't probably corrupt.
- return err.the_new_current_greenlet->g_switch_finish(err);
-}
-
-
-
-Greenlet::switchstack_result_t
-UserGreenlet::g_initialstub(void* mark)
-{
- OwnedObject run;
-
- // We need to grab a reference to the current switch arguments
- // in case we're entered concurrently during the call to
- // GetAttr() and have to try again.
- // We'll restore them when we return in that case.
- // Scope them tightly to avoid ref leaks.
- {
- SwitchingArgs args(this->args());
-
- /* save exception in case getattr clears it */
- PyErrPieces saved;
-
- /*
- self.run is the object to call in the new greenlet.
- This could run arbitrary python code and switch greenlets!
- */
- run = this->_self.PyRequireAttr(mod_globs->str_run);
- /* restore saved exception */
- saved.PyErrRestore();
-
-
- /* recheck that it's safe to switch in case greenlet reparented anywhere above */
- this->check_switch_allowed();
-
- /* by the time we got here another start could happen elsewhere,
- * that means it should now be a regular switch.
- * This can happen if the Python code is a subclass that implements
- * __getattribute__ or __getattr__, or makes ``run`` a descriptor;
- * all of those can run arbitrary code that switches back into
- * this greenlet.
- */
- if (this->stack_state.started()) {
- // the successful switch cleared these out, we need to
- // restore our version. They will be copied on up to the
- // next target.
- assert(!this->args());
- this->args() <<= args;
- throw GreenletStartedWhileInPython();
- }
- }
-
- // Sweet, if we got here, we have the go-ahead and will switch
- // greenlets.
- // Nothing we do from here on out should allow for a thread or
- // greenlet switch: No arbitrary calls to Python, including
- // decref'ing
-
-#if GREENLET_USE_CFRAME
- /* OK, we need it, we're about to switch greenlets, save the state. */
- /*
- See green_new(). This is a stack-allocated variable used
- while *self* is in PyObject_Call().
- We want to defer copying the state info until we're sure
- we need it and are in a stable place to do so.
- */
- _PyCFrame trace_info;
-
- this->python_state.set_new_cframe(trace_info);
-#endif
- /* start the greenlet */
- ThreadState& thread_state = GET_THREAD_STATE().state();
- this->stack_state = StackState(mark,
- thread_state.borrow_current()->stack_state);
- this->python_state.set_initial_state(PyThreadState_GET());
- this->exception_state.clear();
- this->_main_greenlet = thread_state.get_main_greenlet();
-
- /* perform the initial switch */
- switchstack_result_t err = this->g_switchstack();
- /* returns twice!
- The 1st time with ``err == 1``: we are in the new greenlet.
- This one owns a greenlet that used to be current.
- The 2nd time with ``err <= 0``: back in the caller's
- greenlet; this happens if the child finishes or switches
- explicitly to us. Either way, the ``err`` variable is
- created twice at the same memory location, but possibly
- having different ``origin`` values. Note that it's not
- constructed for the second time until the switch actually happens.
- */
- if (err.status == 1) {
- // In the new greenlet.
-
- // This never returns! Calling inner_bootstrap steals
- // the contents of our run object within this stack frame, so
- // it is not valid to do anything with it.
- try {
- this->inner_bootstrap(err.origin_greenlet.relinquish_ownership(),
- run.relinquish_ownership());
- }
- // Getting a C++ exception here isn't good. It's probably a
- // bug in the underlying greenlet, meaning it's probably a
- // C++ extension. We're going to abort anyway, but try to
- // display some nice information *if* possible. Some obscure
- // platforms don't properly support this (old 32-bit Arm, see see
- // https://github.com/python-greenlet/greenlet/issues/385); that's not
- // great, but should usually be OK because, as mentioned above, we're
- // terminating anyway.
- //
- // The catching is tested by
- // ``test_cpp.CPPTests.test_unhandled_exception_in_greenlet_aborts``.
- //
- // PyErrOccurred can theoretically be thrown by
- // inner_bootstrap() -> g_switch_finish(), but that should
- // never make it back to here. It is a std::exception and
- // would be caught if it is.
- catch (const std::exception& e) {
- std::string base = "greenlet: Unhandled C++ exception: ";
- base += e.what();
- Py_FatalError(base.c_str());
- }
- catch (...) {
- // Some compilers/runtimes use exceptions internally.
- // It appears that GCC on Linux with libstdc++ throws an
- // exception internally at process shutdown time to unwind
- // stacks and clean up resources. Depending on exactly
- // where we are when the process exits, that could result
- // in an unknown exception getting here. If we
- // Py_FatalError() or abort() here, we interfere with
- // orderly process shutdown. Throwing the exception on up
- // is the right thing to do.
- //
- // gevent's ``examples/dns_mass_resolve.py`` demonstrates this.
-#ifndef NDEBUG
- fprintf(stderr,
- "greenlet: inner_bootstrap threw unknown exception; "
- "is the process terminating?\n");
-#endif
- throw;
- }
- Py_FatalError("greenlet: inner_bootstrap returned with no exception.\n");
- }
-
-
- // In contrast, notice that we're keeping the origin greenlet
- // around as an owned reference; we need it to call the trace
- // function for the switch back into the parent. It was only
- // captured at the time the switch actually happened, though,
- // so we haven't been keeping an extra reference around this
- // whole time.
-
- /* back in the parent */
- if (err.status < 0) {
- /* start failed badly, restore greenlet state */
- this->stack_state = StackState();
- this->_main_greenlet.CLEAR();
- // CAUTION: This may run arbitrary Python code.
- run.CLEAR(); // inner_bootstrap didn't run, we own the reference.
- }
-
- // In the success case, the spawned code (inner_bootstrap) will
- // take care of decrefing this, so we relinquish ownership so as
- // to not double-decref.
-
- run.relinquish_ownership();
-
- return err;
-}
-
-
-void
-UserGreenlet::inner_bootstrap(PyGreenlet* origin_greenlet, PyObject* run)
-{
- // The arguments here would be another great place for move.
- // As it is, we take them as a reference so that when we clear
- // them we clear what's on the stack above us. Do that NOW, and
- // without using a C++ RAII object,
- // so there's no way that exiting the parent frame can clear it,
- // or we clear it unexpectedly. This arises in the context of the
- // interpreter shutting down. See https://github.com/python-greenlet/greenlet/issues/325
- //PyObject* run = _run.relinquish_ownership();
-
- /* in the new greenlet */
- assert(this->thread_state()->borrow_current() == this->_self);
- // C++ exceptions cannot propagate to the parent greenlet from
- // here. (TODO: Do we need a catch(...) clause, perhaps on the
- // function itself? ALl we could do is terminate the program.)
- // NOTE: On 32-bit Windows, the call chain is extremely
- // important here in ways that are subtle, having to do with
- // the depth of the SEH list. The call to restore it MUST NOT
- // add a new SEH handler to the list, or we'll restore it to
- // the wrong thing.
- this->thread_state()->restore_exception_state();
- /* stack variables from above are no good and also will not unwind! */
- // EXCEPT: That can't be true, we access run, among others, here.
-
- this->stack_state.set_active(); /* running */
-
- // We're about to possibly run Python code again, which
- // could switch back/away to/from us, so we need to grab the
- // arguments locally.
- SwitchingArgs args;
- args <<= this->args();
- assert(!this->args());
-
- // XXX: We could clear this much earlier, right?
- // Or would that introduce the possibility of running Python
- // code when we don't want to?
- // CAUTION: This may run arbitrary Python code.
- this->_run_callable.CLEAR();
-
-
- // The first switch we need to manually call the trace
- // function here instead of in g_switch_finish, because we
- // never return there.
- if (OwnedObject tracefunc = this->thread_state()->get_tracefunc()) {
- OwnedGreenlet trace_origin;
- trace_origin = origin_greenlet;
- try {
- g_calltrace(tracefunc,
- args ? mod_globs->event_switch : mod_globs->event_throw,
- trace_origin,
- this->_self);
- }
- catch (const PyErrOccurred&) {
- /* Turn trace errors into switch throws */
- args.CLEAR();
- }
- }
-
- // We no longer need the origin, it was only here for
- // tracing.
- // We may never actually exit this stack frame so we need
- // to explicitly clear it.
- // This could run Python code and switch.
- Py_CLEAR(origin_greenlet);
-
- OwnedObject result;
- if (!args) {
- /* pending exception */
- result = NULL;
- }
- else {
- /* call g.run(*args, **kwargs) */
- // This could result in further switches
- try {
- //result = run.PyCall(args.args(), args.kwargs());
- // CAUTION: Just invoking this, before the function even
- // runs, may cause memory allocations, which may trigger
- // GC, which may run arbitrary Python code.
- result = OwnedObject::consuming(PyObject_Call(run, args.args().borrow(), args.kwargs().borrow()));
- }
- catch (...) {
- // Unhandled C++ exception!
-
- // If we declare ourselves as noexcept, if we don't catch
- // this here, most platforms will just abort() the
- // process. But on 64-bit Windows with older versions of
- // the C runtime, this can actually corrupt memory and
- // just return. We see this when compiling with the
- // Windows 7.0 SDK targeting Windows Server 2008, but not
- // when using the Appveyor Visual Studio 2019 image. So
- // this currently only affects Python 2.7 on Windows 64.
- // That is, the tests pass and the runtime aborts
- // everywhere else.
- //
- // However, if we catch it and try to continue with a
- // Python error, then all Windows 64 bit platforms corrupt
- // memory. So all we can do is manually abort, hopefully
- // with a good error message. (Note that the above was
- // tested WITHOUT the `/EHr` switch being used at compile
- // time, so MSVC may have "optimized" out important
- // checking. Using that switch, we may be in a better
- // place in terms of memory corruption.) But sometimes it
- // can't be caught here at all, which is confusing but not
- // terribly surprising; so again, the G_NOEXCEPT_WIN32
- // plus "/EHr".
- //
- // Hopefully the basic C stdlib is still functional enough
- // for us to at least print an error.
- //
- // It gets more complicated than that, though, on some
- // platforms, specifically at least Linux/gcc/libstdc++. They use
- // an exception to unwind the stack when a background
- // thread exits. (See comments about noexcept.) So this
- // may not actually represent anything untoward. On those
- // platforms we allow throws of this to propagate, or
- // attempt to anyway.
-# if defined(WIN32) || defined(_WIN32)
- Py_FatalError(
- "greenlet: Unhandled C++ exception from a greenlet run function. "
- "Because memory is likely corrupted, terminating process.");
- std::abort();
-#else
- throw;
-#endif
- }
- }
- // These lines may run arbitrary code
- args.CLEAR();
- Py_CLEAR(run);
-
- if (!result
- && mod_globs->PyExc_GreenletExit.PyExceptionMatches()
- && (this->args())) {
- // This can happen, for example, if our only reference
- // goes away after we switch back to the parent.
- // See test_dealloc_switch_args_not_lost
- PyErrPieces clear_error;
- result <<= this->args();
- result = single_result(result);
- }
- this->release_args();
- this->python_state.did_finish(PyThreadState_GET());
-
- result = g_handle_exit(result);
- assert(this->thread_state()->borrow_current() == this->_self);
-
- /* jump back to parent */
- this->stack_state.set_inactive(); /* dead */
-
-
- // TODO: Can we decref some things here? Release our main greenlet
- // and maybe parent?
- for (Greenlet* parent = this->_parent;
- parent;
- parent = parent->parent()) {
- // We need to somewhere consume a reference to
- // the result; in most cases we'll never have control
- // back in this stack frame again. Calling
- // green_switch actually adds another reference!
- // This would probably be clearer with a specific API
- // to hand results to the parent.
- parent->args() <<= result;
- assert(!result);
- // The parent greenlet now owns the result; in the
- // typical case we'll never get back here to assign to
- // result and thus release the reference.
- try {
- result = parent->g_switch();
- }
- catch (const PyErrOccurred&) {
- // Ignore, keep passing the error on up.
- }
-
- /* Return here means switch to parent failed,
- * in which case we throw *current* exception
- * to the next parent in chain.
- */
- assert(!result);
- }
- /* We ran out of parents, cannot continue */
- PyErr_WriteUnraisable(this->self().borrow_o());
- Py_FatalError("greenlet: ran out of parent greenlets while propagating exception; "
- "cannot continue");
- std::abort();
-}
-
-void
-UserGreenlet::run(const BorrowedObject nrun)
-{
- if (this->started()) {
- throw AttributeError(
- "run cannot be set "
- "after the start of the greenlet");
- }
- this->_run_callable = nrun;
-}
-
-const OwnedGreenlet
-UserGreenlet::parent() const
-{
- return this->_parent;
-}
-
-void
-UserGreenlet::parent(const BorrowedObject raw_new_parent)
-{
- if (!raw_new_parent) {
- throw AttributeError("can't delete attribute");
- }
-
- BorrowedMainGreenlet main_greenlet_of_new_parent;
- BorrowedGreenlet new_parent(raw_new_parent.borrow()); // could
- // throw
- // TypeError!
- for (BorrowedGreenlet p = new_parent; p; p = p->parent()) {
- if (p == this->_self) {
- throw ValueError("cyclic parent chain");
- }
- main_greenlet_of_new_parent = p->main_greenlet();
- }
-
- if (!main_greenlet_of_new_parent) {
- throw ValueError("parent must not be garbage collected");
- }
-
- if (this->started()
- && this->_main_greenlet != main_greenlet_of_new_parent) {
- throw ValueError("parent cannot be on a different thread");
- }
-
- this->_parent = new_parent;
-}
-
-void
-UserGreenlet::murder_in_place()
-{
- this->_main_greenlet.CLEAR();
- Greenlet::murder_in_place();
-}
-
-bool
-UserGreenlet::belongs_to_thread(const ThreadState* thread_state) const
-{
- return Greenlet::belongs_to_thread(thread_state) && this->_main_greenlet == thread_state->borrow_main_greenlet();
-}
-
-
-int
-UserGreenlet::tp_traverse(visitproc visit, void* arg)
-{
- Py_VISIT(this->_parent.borrow_o());
- Py_VISIT(this->_main_greenlet.borrow_o());
- Py_VISIT(this->_run_callable.borrow_o());
-
- return Greenlet::tp_traverse(visit, arg);
-}
-
-int
-UserGreenlet::tp_clear()
-{
- Greenlet::tp_clear();
- this->_parent.CLEAR();
- this->_main_greenlet.CLEAR();
- this->_run_callable.CLEAR();
- return 0;
-}
-
-UserGreenlet::ParentIsCurrentGuard::ParentIsCurrentGuard(UserGreenlet* p,
- const ThreadState& thread_state)
- : oldparent(p->_parent),
- greenlet(p)
-{
- p->_parent = thread_state.get_current();
-}
-
-UserGreenlet::ParentIsCurrentGuard::~ParentIsCurrentGuard()
-{
- this->greenlet->_parent = oldparent;
- oldparent.CLEAR();
-}
-
-}; //namespace greenlet
diff --git a/venv/lib/python3.11/site-packages/greenlet/__init__.py b/venv/lib/python3.11/site-packages/greenlet/__init__.py
deleted file mode 100644
index 298a19d..0000000
--- a/venv/lib/python3.11/site-packages/greenlet/__init__.py
+++ /dev/null
@@ -1,71 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-The root of the greenlet package.
-"""
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-__all__ = [
- '__version__',
- '_C_API',
-
- 'GreenletExit',
- 'error',
-
- 'getcurrent',
- 'greenlet',
-
- 'gettrace',
- 'settrace',
-]
-
-# pylint:disable=no-name-in-module
-
-###
-# Metadata
-###
-__version__ = '3.0.3'
-from ._greenlet import _C_API # pylint:disable=no-name-in-module
-
-###
-# Exceptions
-###
-from ._greenlet import GreenletExit
-from ._greenlet import error
-
-###
-# greenlets
-###
-from ._greenlet import getcurrent
-from ._greenlet import greenlet
-
-###
-# tracing
-###
-try:
- from ._greenlet import gettrace
- from ._greenlet import settrace
-except ImportError:
- # Tracing wasn't supported.
- # XXX: The option to disable it was removed in 1.0,
- # so this branch should be dead code.
- pass
-
-###
-# Constants
-# These constants aren't documented and aren't recommended.
-# In 1.0, USE_GC and USE_TRACING are always true, and USE_CONTEXT_VARS
-# is the same as ``sys.version_info[:2] >= 3.7``
-###
-from ._greenlet import GREENLET_USE_CONTEXT_VARS # pylint:disable=unused-import
-from ._greenlet import GREENLET_USE_GC # pylint:disable=unused-import
-from ._greenlet import GREENLET_USE_TRACING # pylint:disable=unused-import
-
-# Controlling the use of the gc module. Provisional API for this greenlet
-# implementation in 2.0.
-from ._greenlet import CLOCKS_PER_SEC # pylint:disable=unused-import
-from ._greenlet import enable_optional_cleanup # pylint:disable=unused-import
-from ._greenlet import get_clocks_used_doing_optional_cleanup # pylint:disable=unused-import
-
-# Other APIS in the _greenlet module are for test support.
diff --git a/venv/lib/python3.11/site-packages/greenlet/__pycache__/__init__.cpython-311.pyc b/venv/lib/python3.11/site-packages/greenlet/__pycache__/__init__.cpython-311.pyc
deleted file mode 100644
index 88a0be3..0000000
--- a/venv/lib/python3.11/site-packages/greenlet/__pycache__/__init__.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/greenlet/_greenlet.cpython-311-x86_64-linux-gnu.so b/venv/lib/python3.11/site-packages/greenlet/_greenlet.cpython-311-x86_64-linux-gnu.so
deleted file mode 100755
index 1d293a3..0000000
--- a/venv/lib/python3.11/site-packages/greenlet/_greenlet.cpython-311-x86_64-linux-gnu.so
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/greenlet/greenlet.cpp b/venv/lib/python3.11/site-packages/greenlet/greenlet.cpp
deleted file mode 100644
index 5a9818e..0000000
--- a/venv/lib/python3.11/site-packages/greenlet/greenlet.cpp
+++ /dev/null
@@ -1,1494 +0,0 @@
-/* -*- indent-tabs-mode: nil; tab-width: 4; -*- */
-/* Format with:
- * clang-format -i --style=file src/greenlet/greenlet.c
- *
- *
- * Fix missing braces with:
- * clang-tidy src/greenlet/greenlet.c -fix -checks="readability-braces-around-statements"
-*/
-#include <cstdlib>
-#include <string>
-#include <algorithm>
-#include <exception>
-
-
-#define PY_SSIZE_T_CLEAN
-#include <Python.h>
-#include "structmember.h" // PyMemberDef
-
-#include "greenlet_internal.hpp"
-// Code after this point can assume access to things declared in stdint.h,
-// including the fixed-width types. This goes for the platform-specific switch functions
-// as well.
-#include "greenlet_refs.hpp"
-#include "greenlet_slp_switch.hpp"
-#include "greenlet_thread_state.hpp"
-#include "greenlet_thread_support.hpp"
-#include "greenlet_greenlet.hpp"
-
-#include "TGreenletGlobals.cpp"
-#include "TThreadStateDestroy.cpp"
-#include "TGreenlet.cpp"
-#include "TMainGreenlet.cpp"
-#include "TUserGreenlet.cpp"
-#include "TBrokenGreenlet.cpp"
-#include "TExceptionState.cpp"
-#include "TPythonState.cpp"
-#include "TStackState.cpp"
-
-
-using greenlet::LockGuard;
-using greenlet::LockInitError;
-using greenlet::PyErrOccurred;
-using greenlet::Require;
-
-using greenlet::g_handle_exit;
-using greenlet::single_result;
-
-using greenlet::Greenlet;
-using greenlet::UserGreenlet;
-using greenlet::MainGreenlet;
-using greenlet::BrokenGreenlet;
-using greenlet::ThreadState;
-using greenlet::PythonState;
-
-
-
-// ******* Implementation of things from included files
-template<typename T, greenlet::refs::TypeChecker TC>
-greenlet::refs::_BorrowedGreenlet<T, TC>& greenlet::refs::_BorrowedGreenlet<T, TC>::operator=(const greenlet::refs::BorrowedObject& other)
-{
- this->_set_raw_pointer(static_cast<PyObject*>(other));
- return *this;
-}
-
-template <typename T, greenlet::refs::TypeChecker TC>
-inline greenlet::refs::_BorrowedGreenlet<T, TC>::operator Greenlet*() const noexcept
-{
- if (!this->p) {
- return nullptr;
- }
- return reinterpret_cast<PyGreenlet*>(this->p)->pimpl;
-}
-
-template<typename T, greenlet::refs::TypeChecker TC>
-greenlet::refs::_BorrowedGreenlet<T, TC>::_BorrowedGreenlet(const BorrowedObject& p)
- : BorrowedReference<T, TC>(nullptr)
-{
-
- this->_set_raw_pointer(p.borrow());
-}
-
-template <typename T, greenlet::refs::TypeChecker TC>
-inline greenlet::refs::_OwnedGreenlet<T, TC>::operator Greenlet*() const noexcept
-{
- if (!this->p) {
- return nullptr;
- }
- return reinterpret_cast<PyGreenlet*>(this->p)->pimpl;
-}
-
-
-
-#ifdef __clang__
-# pragma clang diagnostic push
-# pragma clang diagnostic ignored "-Wmissing-field-initializers"
-# pragma clang diagnostic ignored "-Wwritable-strings"
-#elif defined(__GNUC__)
-# pragma GCC diagnostic push
-// warning: ISO C++ forbids converting a string constant to ‘char*’
-// (The python APIs aren't const correct and accept writable char*)
-# pragma GCC diagnostic ignored "-Wwrite-strings"
-#endif
-
-
-/***********************************************************
-
-A PyGreenlet is a range of C stack addresses that must be
-saved and restored in such a way that the full range of the
-stack contains valid data when we switch to it.
-
-Stack layout for a greenlet:
-
- | ^^^ |
- | older data |
- | |
- stack_stop . |_______________|
- . | |
- . | greenlet data |
- . | in stack |
- . * |_______________| . . _____________ stack_copy + stack_saved
- . | | | |
- . | data | |greenlet data|
- . | unrelated | | saved |
- . | to | | in heap |
- stack_start . | this | . . |_____________| stack_copy
- | greenlet |
- | |
- | newer data |
- | vvv |
-
-
-Note that a greenlet's stack data is typically partly at its correct
-place in the stack, and partly saved away in the heap, but always in
-the above configuration: two blocks, the more recent one in the heap
-and the older one still in the stack (either block may be empty).
-
-Greenlets are chained: each points to the previous greenlet, which is
-the one that owns the data currently in the C stack above my
-stack_stop. The currently running greenlet is the first element of
-this chain. The main (initial) greenlet is the last one. Greenlets
-whose stack is entirely in the heap can be skipped from the chain.
-
-The chain is not related to execution order, but only to the order
-in which bits of C stack happen to belong to greenlets at a particular
-point in time.
-
-The main greenlet doesn't have a stack_stop: it is responsible for the
-complete rest of the C stack, and we don't know where it begins. We
-use (char*) -1, the largest possible address.
-
-States:
- stack_stop == NULL && stack_start == NULL: did not start yet
- stack_stop != NULL && stack_start == NULL: already finished
- stack_stop != NULL && stack_start != NULL: active
-
-The running greenlet's stack_start is undefined but not NULL.
-
- ***********************************************************/
-
-static PyGreenlet*
-green_create_main(ThreadState* state)
-{
- PyGreenlet* gmain;
-
- /* create the main greenlet for this thread */
- gmain = (PyGreenlet*)PyType_GenericAlloc(&PyGreenlet_Type, 0);
- if (gmain == NULL) {
- Py_FatalError("green_create_main failed to alloc");
- return NULL;
- }
- new MainGreenlet(gmain, state);
-
- assert(Py_REFCNT(gmain) == 1);
- return gmain;
-}
-
-
-
-/***********************************************************/
-
-/* Some functions must not be inlined:
- * slp_restore_state, when inlined into slp_switch might cause
- it to restore stack over its own local variables
- * slp_save_state, when inlined would add its own local
- variables to the saved stack, wasting space
- * slp_switch, cannot be inlined for obvious reasons
- * g_initialstub, when inlined would receive a pointer into its
- own stack frame, leading to incomplete stack save/restore
-
-g_initialstub is a member function and declared virtual so that the
-compiler always calls it through a vtable.
-
-slp_save_state and slp_restore_state are also member functions. They
-are called from trampoline functions that themselves are declared as
-not eligible for inlining.
-*/
-
-extern "C" {
-static int GREENLET_NOINLINE(slp_save_state_trampoline)(char* stackref)
-{
- return switching_thread_state->slp_save_state(stackref);
-}
-static void GREENLET_NOINLINE(slp_restore_state_trampoline)()
-{
- switching_thread_state->slp_restore_state();
-}
-}
-
-
-/***********************************************************/
-
-static PyGreenlet*
-green_new(PyTypeObject* type, PyObject* UNUSED(args), PyObject* UNUSED(kwds))
-{
- PyGreenlet* o =
- (PyGreenlet*)PyBaseObject_Type.tp_new(type, mod_globs->empty_tuple, mod_globs->empty_dict);
- if (o) {
- new UserGreenlet(o, GET_THREAD_STATE().state().borrow_current());
- assert(Py_REFCNT(o) == 1);
- }
- return o;
-}
-
-static PyGreenlet*
-green_unswitchable_new(PyTypeObject* type, PyObject* UNUSED(args), PyObject* UNUSED(kwds))
-{
- PyGreenlet* o =
- (PyGreenlet*)PyBaseObject_Type.tp_new(type, mod_globs->empty_tuple, mod_globs->empty_dict);
- if (o) {
- new BrokenGreenlet(o, GET_THREAD_STATE().state().borrow_current());
- assert(Py_REFCNT(o) == 1);
- }
- return o;
-}
-
-static int
-green_setrun(BorrowedGreenlet self, BorrowedObject nrun, void* c);
-static int
-green_setparent(BorrowedGreenlet self, BorrowedObject nparent, void* c);
-
-static int
-green_init(BorrowedGreenlet self, BorrowedObject args, BorrowedObject kwargs)
-{
- PyArgParseParam run;
- PyArgParseParam nparent;
- static const char* const kwlist[] = {
- "run",
- "parent",
- NULL
- };
-
- // recall: The O specifier does NOT increase the reference count.
- if (!PyArg_ParseTupleAndKeywords(
- args, kwargs, "|OO:green", (char**)kwlist, &run, &nparent)) {
- return -1;
- }
-
- if (run) {
- if (green_setrun(self, run, NULL)) {
- return -1;
- }
- }
- if (nparent && !nparent.is_None()) {
- return green_setparent(self, nparent, NULL);
- }
- return 0;
-}
-
-
-
-static int
-green_traverse(PyGreenlet* self, visitproc visit, void* arg)
-{
- // We must only visit referenced objects, i.e. only objects
- // Py_INCREF'ed by this greenlet (directly or indirectly):
- //
- // - stack_prev is not visited: holds previous stack pointer, but it's not
- // referenced
- // - frames are not visited as we don't strongly reference them;
- // alive greenlets are not garbage collected
- // anyway. This can be a problem, however, if this greenlet is
- // never allowed to finish, and is referenced from the frame: we
- // have an uncollectible cycle in that case. Note that the
- // frame object itself is also frequently not even tracked by the GC
- // starting with Python 3.7 (frames are allocated by the
- // interpreter untracked, and only become tracked when their
- // evaluation is finished if they have a refcount > 1). All of
- // this is to say that we should probably strongly reference
- // the frame object. Doing so, while always allowing GC on a
- // greenlet, solves several leaks for us.
-
- Py_VISIT(self->dict);
- if (!self->pimpl) {
- // Hmm. I have seen this at interpreter shutdown time,
- // I think. That's very odd because this doesn't go away until
- // we're ``green_dealloc()``, at which point we shouldn't be
- // traversed anymore.
- return 0;
- }
-
- return self->pimpl->tp_traverse(visit, arg);
-}
-
-static int
-green_is_gc(BorrowedGreenlet self)
-{
- int result = 0;
- /* Main greenlet can be garbage collected since it can only
- become unreachable if the underlying thread exited.
- Active greenlets --- including those that are suspended ---
- cannot be garbage collected, however.
- */
- if (self->main() || !self->active()) {
- result = 1;
- }
- // The main greenlet pointer will eventually go away after the thread dies.
- if (self->was_running_in_dead_thread()) {
- // Our thread is dead! We can never run again. Might as well
- // GC us. Note that if a tuple containing only us and other
- // immutable objects had been scanned before this, when we
- // would have returned 0, the tuple will take itself out of GC
- // tracking and never be investigated again. So that could
- // result in both us and the tuple leaking due to an
- // unreachable/uncollectible reference. The same goes for
- // dictionaries.
- //
- // It's not a great idea to be changing our GC state on the
- // fly.
- result = 1;
- }
- return result;
-}
-
-
-static int
-green_clear(PyGreenlet* self)
-{
- /* Greenlet is only cleared if it is about to be collected.
- Since active greenlets are not garbage collectable, we can
- be sure that, even if they are deallocated during clear,
- nothing they reference is in unreachable or finalizers,
- so even if it switches we are relatively safe. */
- // XXX: Are we responsible for clearing weakrefs here?
- Py_CLEAR(self->dict);
- return self->pimpl->tp_clear();
-}
-
-/**
- * Returns 0 on failure (the object was resurrected) or 1 on success.
- **/
-static int
-_green_dealloc_kill_started_non_main_greenlet(BorrowedGreenlet self)
-{
- /* Hacks hacks hacks copied from instance_dealloc() */
- /* Temporarily resurrect the greenlet. */
- assert(self.REFCNT() == 0);
- Py_SET_REFCNT(self.borrow(), 1);
- /* Save the current exception, if any. */
- PyErrPieces saved_err;
- try {
- // BY THE TIME WE GET HERE, the state may actually be going
- // away
- // if we're shutting down the interpreter and freeing thread
- // entries,
- // this could result in freeing greenlets that were leaked. So
- // we can't try to read the state.
- self->deallocing_greenlet_in_thread(
- self->thread_state()
- ? static_cast<ThreadState*>(GET_THREAD_STATE())
- : nullptr);
- }
- catch (const PyErrOccurred&) {
- PyErr_WriteUnraisable(self.borrow_o());
- /* XXX what else should we do? */
- }
- /* Check for no resurrection must be done while we keep
- * our internal reference, otherwise PyFile_WriteObject
- * causes recursion if using Py_INCREF/Py_DECREF
- */
- if (self.REFCNT() == 1 && self->active()) {
- /* Not resurrected, but still not dead!
- XXX what else should we do? we complain. */
- PyObject* f = PySys_GetObject("stderr");
- Py_INCREF(self.borrow_o()); /* leak! */
- if (f != NULL) {
- PyFile_WriteString("GreenletExit did not kill ", f);
- PyFile_WriteObject(self.borrow_o(), f, 0);
- PyFile_WriteString("\n", f);
- }
- }
- /* Restore the saved exception. */
- saved_err.PyErrRestore();
- /* Undo the temporary resurrection; can't use DECREF here,
- * it would cause a recursive call.
- */
- assert(self.REFCNT() > 0);
-
- Py_ssize_t refcnt = self.REFCNT() - 1;
- Py_SET_REFCNT(self.borrow_o(), refcnt);
- if (refcnt != 0) {
- /* Resurrected! */
- _Py_NewReference(self.borrow_o());
- Py_SET_REFCNT(self.borrow_o(), refcnt);
- /* Better to use tp_finalizer slot (PEP 442)
- * and call ``PyObject_CallFinalizerFromDealloc``,
- * but that's only supported in Python 3.4+; see
- * Modules/_io/iobase.c for an example.
- *
- * The following approach is copied from iobase.c in CPython 2.7.
- * (along with much of this function in general). Here's their
- * comment:
- *
- * When called from a heap type's dealloc, the type will be
- * decref'ed on return (see e.g. subtype_dealloc in typeobject.c). */
- if (PyType_HasFeature(self.TYPE(), Py_TPFLAGS_HEAPTYPE)) {
- Py_INCREF(self.TYPE());
- }
-
- PyObject_GC_Track((PyObject*)self);
-
- _Py_DEC_REFTOTAL;
-#ifdef COUNT_ALLOCS
- --Py_TYPE(self)->tp_frees;
- --Py_TYPE(self)->tp_allocs;
-#endif /* COUNT_ALLOCS */
- return 0;
- }
- return 1;
-}
-
-
-static void
-green_dealloc(PyGreenlet* self)
-{
- PyObject_GC_UnTrack(self);
- BorrowedGreenlet me(self);
- if (me->active()
- && me->started()
- && !me->main()) {
- if (!_green_dealloc_kill_started_non_main_greenlet(me)) {
- return;
- }
- }
-
- if (self->weakreflist != NULL) {
- PyObject_ClearWeakRefs((PyObject*)self);
- }
- Py_CLEAR(self->dict);
-
- if (self->pimpl) {
- // In case deleting this, which frees some memory,
- // somehow winds up calling back into us. That's usually a
- //bug in our code.
- Greenlet* p = self->pimpl;
- self->pimpl = nullptr;
- delete p;
- }
- // and finally we're done. self is now invalid.
- Py_TYPE(self)->tp_free((PyObject*)self);
-}
-
-
-
-static OwnedObject
-throw_greenlet(BorrowedGreenlet self, PyErrPieces& err_pieces)
-{
- PyObject* result = nullptr;
- err_pieces.PyErrRestore();
- assert(PyErr_Occurred());
- if (self->started() && !self->active()) {
- /* dead greenlet: turn GreenletExit into a regular return */
- result = g_handle_exit(OwnedObject()).relinquish_ownership();
- }
- self->args() <<= result;
-
- return single_result(self->g_switch());
-}
-
-
-
-PyDoc_STRVAR(
- green_switch_doc,
- "switch(*args, **kwargs)\n"
- "\n"
- "Switch execution to this greenlet.\n"
- "\n"
- "If this greenlet has never been run, then this greenlet\n"
- "will be switched to using the body of ``self.run(*args, **kwargs)``.\n"
- "\n"
- "If the greenlet is active (has been run, but was switch()'ed\n"
- "out before leaving its run function), then this greenlet will\n"
- "be resumed and the return value to its switch call will be\n"
- "None if no arguments are given, the given argument if one\n"
- "argument is given, or the args tuple and keyword args dict if\n"
- "multiple arguments are given.\n"
- "\n"
- "If the greenlet is dead, or is the current greenlet then this\n"
- "function will simply return the arguments using the same rules as\n"
- "above.\n");
-
-static PyObject*
-green_switch(PyGreenlet* self, PyObject* args, PyObject* kwargs)
-{
- using greenlet::SwitchingArgs;
- SwitchingArgs switch_args(OwnedObject::owning(args), OwnedObject::owning(kwargs));
- self->pimpl->may_switch_away();
- self->pimpl->args() <<= switch_args;
-
- // If we're switching out of a greenlet, and that switch is the
- // last thing the greenlet does, the greenlet ought to be able to
- // go ahead and die at that point. Currently, someone else must
- // manually switch back to the greenlet so that we "fall off the
- // end" and can perform cleanup. You'd think we'd be able to
- // figure out that this is happening using the frame's ``f_lasti``
- // member, which is supposed to be an index into
- // ``frame->f_code->co_code``, the bytecode string. However, in
- // recent interpreters, ``f_lasti`` tends not to be updated thanks
- // to things like the PREDICT() macros in ceval.c. So it doesn't
- // really work to do that in many cases. For example, the Python
- // code:
- // def run():
- // greenlet.getcurrent().parent.switch()
- // produces bytecode of len 16, with the actual call to switch()
- // being at index 10 (in Python 3.10). However, the reported
- // ``f_lasti`` we actually see is...5! (Which happens to be the
- // second byte of the CALL_METHOD op for ``getcurrent()``).
-
- try {
- //OwnedObject result = single_result(self->pimpl->g_switch());
- OwnedObject result(single_result(self->pimpl->g_switch()));
-#ifndef NDEBUG
- // Note that the current greenlet isn't necessarily self. If self
- // finished, we went to one of its parents.
- assert(!self->pimpl->args());
-
- const BorrowedGreenlet& current = GET_THREAD_STATE().state().borrow_current();
- // It's possible it's never been switched to.
- assert(!current->args());
-#endif
- PyObject* p = result.relinquish_ownership();
-
- if (!p && !PyErr_Occurred()) {
- // This shouldn't be happening anymore, so the asserts
- // are there for debug builds. Non-debug builds
- // crash "gracefully" in this case, although there is an
- // argument to be made for killing the process in all
- // cases --- for this to be the case, our switches
- // probably nested in an incorrect way, so the state is
- // suspicious. Nothing should be corrupt though, just
- // confused at the Python level. Letting this propagate is
- // probably good enough.
- assert(p || PyErr_Occurred());
- throw PyErrOccurred(
- mod_globs->PyExc_GreenletError,
- "Greenlet.switch() returned NULL without an exception set."
- );
- }
- return p;
- }
- catch(const PyErrOccurred&) {
- return nullptr;
- }
-}
-
-PyDoc_STRVAR(
- green_throw_doc,
- "Switches execution to this greenlet, but immediately raises the\n"
- "given exception in this greenlet. If no argument is provided, the "
- "exception\n"
- "defaults to `greenlet.GreenletExit`. The normal exception\n"
- "propagation rules apply, as described for `switch`. Note that calling "
- "this\n"
- "method is almost equivalent to the following::\n"
- "\n"
- " def raiser():\n"
- " raise typ, val, tb\n"
- " g_raiser = greenlet(raiser, parent=g)\n"
- " g_raiser.switch()\n"
- "\n"
- "except that this trick does not work for the\n"
- "`greenlet.GreenletExit` exception, which would not propagate\n"
- "from ``g_raiser`` to ``g``.\n");
-
-static PyObject*
-green_throw(PyGreenlet* self, PyObject* args)
-{
- PyArgParseParam typ(mod_globs->PyExc_GreenletExit);
- PyArgParseParam val;
- PyArgParseParam tb;
-
- if (!PyArg_ParseTuple(args, "|OOO:throw", &typ, &val, &tb)) {
- return nullptr;
- }
-
- assert(typ.borrow() || val.borrow());
-
- self->pimpl->may_switch_away();
- try {
- // Both normalizing the error and the actual throw_greenlet
- // could throw PyErrOccurred.
- PyErrPieces err_pieces(typ.borrow(), val.borrow(), tb.borrow());
-
- return throw_greenlet(self, err_pieces).relinquish_ownership();
- }
- catch (const PyErrOccurred&) {
- return nullptr;
- }
-}
-
-static int
-green_bool(PyGreenlet* self)
-{
- return self->pimpl->active();
-}
-
-/**
- * CAUTION: Allocates memory, may run GC and arbitrary Python code.
- */
-static PyObject*
-green_getdict(PyGreenlet* self, void* UNUSED(context))
-{
- if (self->dict == NULL) {
- self->dict = PyDict_New();
- if (self->dict == NULL) {
- return NULL;
- }
- }
- Py_INCREF(self->dict);
- return self->dict;
-}
-
-static int
-green_setdict(PyGreenlet* self, PyObject* val, void* UNUSED(context))
-{
- PyObject* tmp;
-
- if (val == NULL) {
- PyErr_SetString(PyExc_TypeError, "__dict__ may not be deleted");
- return -1;
- }
- if (!PyDict_Check(val)) {
- PyErr_SetString(PyExc_TypeError, "__dict__ must be a dictionary");
- return -1;
- }
- tmp = self->dict;
- Py_INCREF(val);
- self->dict = val;
- Py_XDECREF(tmp);
- return 0;
-}
-
-static bool
-_green_not_dead(BorrowedGreenlet self)
-{
- // XXX: Where else should we do this?
- // Probably on entry to most Python-facing functions?
- if (self->was_running_in_dead_thread()) {
- self->deactivate_and_free();
- return false;
- }
- return self->active() || !self->started();
-}
-
-
-static PyObject*
-green_getdead(BorrowedGreenlet self, void* UNUSED(context))
-{
- if (_green_not_dead(self)) {
- Py_RETURN_FALSE;
- }
- else {
- Py_RETURN_TRUE;
- }
-}
-
-static PyObject*
-green_get_stack_saved(PyGreenlet* self, void* UNUSED(context))
-{
- return PyLong_FromSsize_t(self->pimpl->stack_saved());
-}
-
-
-static PyObject*
-green_getrun(BorrowedGreenlet self, void* UNUSED(context))
-{
- try {
- OwnedObject result(self->run());
- return result.relinquish_ownership();
- }
- catch(const PyErrOccurred&) {
- return nullptr;
- }
-}
-
-
-
-
-
-static int
-green_setrun(BorrowedGreenlet self, BorrowedObject nrun, void* UNUSED(context))
-{
- try {
- self->run(nrun);
- return 0;
- }
- catch(const PyErrOccurred&) {
- return -1;
- }
-}
-
-static PyObject*
-green_getparent(BorrowedGreenlet self, void* UNUSED(context))
-{
- return self->parent().acquire_or_None();
-}
-
-
-
-static int
-green_setparent(BorrowedGreenlet self, BorrowedObject nparent, void* UNUSED(context))
-{
- try {
- self->parent(nparent);
- }
- catch(const PyErrOccurred&) {
- return -1;
- }
- return 0;
-}
-
-
-static PyObject*
-green_getcontext(const PyGreenlet* self, void* UNUSED(context))
-{
- const Greenlet *const g = self->pimpl;
- try {
- OwnedObject result(g->context());
- return result.relinquish_ownership();
- }
- catch(const PyErrOccurred&) {
- return nullptr;
- }
-}
-
-static int
-green_setcontext(BorrowedGreenlet self, PyObject* nctx, void* UNUSED(context))
-{
- try {
- self->context(nctx);
- return 0;
- }
- catch(const PyErrOccurred&) {
- return -1;
- }
-}
-
-
-static PyObject*
-green_getframe(BorrowedGreenlet self, void* UNUSED(context))
-{
- const PythonState::OwnedFrame& top_frame = self->top_frame();
- return top_frame.acquire_or_None();
-}
-
-
-static PyObject*
-green_getstate(PyGreenlet* self)
-{
- PyErr_Format(PyExc_TypeError,
- "cannot serialize '%s' object",
- Py_TYPE(self)->tp_name);
- return nullptr;
-}
-
-static PyObject*
-green_repr(BorrowedGreenlet self)
-{
- /*
- Return a string like
- <greenlet.greenlet at 0xdeadbeef [current][active started]|dead main>
-
- The handling of greenlets across threads is not super good.
- We mostly use the internal definitions of these terms, but they
- generally should make sense to users as well.
- */
- PyObject* result;
- int never_started = !self->started() && !self->active();
-
- const char* const tp_name = Py_TYPE(self)->tp_name;
-
- if (_green_not_dead(self)) {
- /* XXX: The otid= is almost useless because you can't correlate it to
- any thread identifier exposed to Python. We could use
- PyThreadState_GET()->thread_id, but we'd need to save that in the
- greenlet, or save the whole PyThreadState object itself.
-
- As it stands, its only useful for identifying greenlets from the same thread.
- */
- const char* state_in_thread;
- if (self->was_running_in_dead_thread()) {
- // The thread it was running in is dead!
- // This can happen, especially at interpreter shut down.
- // It complicates debugging output because it may be
- // impossible to access the current thread state at that
- // time. Thus, don't access the current thread state.
- state_in_thread = " (thread exited)";
- }
- else {
- state_in_thread = GET_THREAD_STATE().state().is_current(self)
- ? " current"
- : (self->started() ? " suspended" : "");
- }
- result = PyUnicode_FromFormat(
- "<%s object at %p (otid=%p)%s%s%s%s>",
- tp_name,
- self.borrow_o(),
- self->thread_state(),
- state_in_thread,
- self->active() ? " active" : "",
- never_started ? " pending" : " started",
- self->main() ? " main" : ""
- );
- }
- else {
- result = PyUnicode_FromFormat(
- "<%s object at %p (otid=%p) %sdead>",
- tp_name,
- self.borrow_o(),
- self->thread_state(),
- self->was_running_in_dead_thread()
- ? "(thread exited) "
- : ""
- );
- }
-
- return result;
-}
-
-/*****************************************************************************
- * C interface
- *
- * These are exported using the CObject API
- */
-extern "C" {
-static PyGreenlet*
-PyGreenlet_GetCurrent(void)
-{
- return GET_THREAD_STATE().state().get_current().relinquish_ownership();
-}
-
-static int
-PyGreenlet_SetParent(PyGreenlet* g, PyGreenlet* nparent)
-{
- return green_setparent((PyGreenlet*)g, (PyObject*)nparent, NULL);
-}
-
-static PyGreenlet*
-PyGreenlet_New(PyObject* run, PyGreenlet* parent)
-{
- using greenlet::refs::NewDictReference;
- // In the past, we didn't use green_new and green_init, but that
- // was a maintenance issue because we duplicated code. This way is
- // much safer, but slightly slower. If that's a problem, we could
- // refactor green_init to separate argument parsing from initialization.
- OwnedGreenlet g = OwnedGreenlet::consuming(green_new(&PyGreenlet_Type, nullptr, nullptr));
- if (!g) {
- return NULL;
- }
-
- try {
- NewDictReference kwargs;
- if (run) {
- kwargs.SetItem(mod_globs->str_run, run);
- }
- if (parent) {
- kwargs.SetItem("parent", (PyObject*)parent);
- }
-
- Require(green_init(g, mod_globs->empty_tuple, kwargs));
- }
- catch (const PyErrOccurred&) {
- return nullptr;
- }
-
- return g.relinquish_ownership();
-}
-
-static PyObject*
-PyGreenlet_Switch(PyGreenlet* self, PyObject* args, PyObject* kwargs)
-{
- if (!PyGreenlet_Check(self)) {
- PyErr_BadArgument();
- return NULL;
- }
-
- if (args == NULL) {
- args = mod_globs->empty_tuple;
- }
-
- if (kwargs == NULL || !PyDict_Check(kwargs)) {
- kwargs = NULL;
- }
-
- return green_switch(self, args, kwargs);
-}
-
-static PyObject*
-PyGreenlet_Throw(PyGreenlet* self, PyObject* typ, PyObject* val, PyObject* tb)
-{
- if (!PyGreenlet_Check(self)) {
- PyErr_BadArgument();
- return nullptr;
- }
- try {
- PyErrPieces err_pieces(typ, val, tb);
- return throw_greenlet(self, err_pieces).relinquish_ownership();
- }
- catch (const PyErrOccurred&) {
- return nullptr;
- }
-}
-
-static int
-Extern_PyGreenlet_MAIN(PyGreenlet* self)
-{
- if (!PyGreenlet_Check(self)) {
- PyErr_BadArgument();
- return -1;
- }
- return self->pimpl->main();
-}
-
-static int
-Extern_PyGreenlet_ACTIVE(PyGreenlet* self)
-{
- if (!PyGreenlet_Check(self)) {
- PyErr_BadArgument();
- return -1;
- }
- return self->pimpl->active();
-}
-
-static int
-Extern_PyGreenlet_STARTED(PyGreenlet* self)
-{
- if (!PyGreenlet_Check(self)) {
- PyErr_BadArgument();
- return -1;
- }
- return self->pimpl->started();
-}
-
-static PyGreenlet*
-Extern_PyGreenlet_GET_PARENT(PyGreenlet* self)
-{
- if (!PyGreenlet_Check(self)) {
- PyErr_BadArgument();
- return NULL;
- }
- // This can return NULL even if there is no exception
- return self->pimpl->parent().acquire();
-}
-} // extern C.
-
-/** End C API ****************************************************************/
-
-static PyMethodDef green_methods[] = {
- {"switch",
- reinterpret_cast<PyCFunction>(green_switch),
- METH_VARARGS | METH_KEYWORDS,
- green_switch_doc},
- {"throw", (PyCFunction)green_throw, METH_VARARGS, green_throw_doc},
- {"__getstate__", (PyCFunction)green_getstate, METH_NOARGS, NULL},
- {NULL, NULL} /* sentinel */
-};
-
-static PyGetSetDef green_getsets[] = {
- /* name, getter, setter, doc, context pointer */
- {"__dict__", (getter)green_getdict, (setter)green_setdict, /*XXX*/ NULL},
- {"run", (getter)green_getrun, (setter)green_setrun, /*XXX*/ NULL},
- {"parent", (getter)green_getparent, (setter)green_setparent, /*XXX*/ NULL},
- {"gr_frame", (getter)green_getframe, NULL, /*XXX*/ NULL},
- {"gr_context",
- (getter)green_getcontext,
- (setter)green_setcontext,
- /*XXX*/ NULL},
- {"dead", (getter)green_getdead, NULL, /*XXX*/ NULL},
- {"_stack_saved", (getter)green_get_stack_saved, NULL, /*XXX*/ NULL},
- {NULL}
-};
-
-static PyMemberDef green_members[] = {
- {NULL}
-};
-
-static PyNumberMethods green_as_number = {
- NULL, /* nb_add */
- NULL, /* nb_subtract */
- NULL, /* nb_multiply */
- NULL, /* nb_remainder */
- NULL, /* nb_divmod */
- NULL, /* nb_power */
- NULL, /* nb_negative */
- NULL, /* nb_positive */
- NULL, /* nb_absolute */
- (inquiry)green_bool, /* nb_bool */
-};
-
-
-PyTypeObject PyGreenlet_Type = {
- PyVarObject_HEAD_INIT(NULL, 0)
- "greenlet.greenlet", /* tp_name */
- sizeof(PyGreenlet), /* tp_basicsize */
- 0, /* tp_itemsize */
- /* methods */
- (destructor)green_dealloc, /* tp_dealloc */
- 0, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- 0, /* tp_compare */
- (reprfunc)green_repr, /* tp_repr */
- &green_as_number, /* tp_as _number*/
- 0, /* tp_as _sequence*/
- 0, /* tp_as _mapping*/
- 0, /* tp_hash */
- 0, /* tp_call */
- 0, /* tp_str */
- 0, /* tp_getattro */
- 0, /* tp_setattro */
- 0, /* tp_as_buffer*/
- G_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
- "greenlet(run=None, parent=None) -> greenlet\n\n"
- "Creates a new greenlet object (without running it).\n\n"
- " - *run* -- The callable to invoke.\n"
- " - *parent* -- The parent greenlet. The default is the current "
- "greenlet.", /* tp_doc */
- (traverseproc)green_traverse, /* tp_traverse */
- (inquiry)green_clear, /* tp_clear */
- 0, /* tp_richcompare */
- offsetof(PyGreenlet, weakreflist), /* tp_weaklistoffset */
- 0, /* tp_iter */
- 0, /* tp_iternext */
- green_methods, /* tp_methods */
- green_members, /* tp_members */
- green_getsets, /* tp_getset */
- 0, /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- offsetof(PyGreenlet, dict), /* tp_dictoffset */
- (initproc)green_init, /* tp_init */
- PyType_GenericAlloc, /* tp_alloc */
- (newfunc)green_new, /* tp_new */
- PyObject_GC_Del, /* tp_free */
- (inquiry)green_is_gc, /* tp_is_gc */
-};
-
-
-
-static PyObject*
-green_unswitchable_getforce(PyGreenlet* self, void* UNUSED(context))
-{
- BrokenGreenlet* broken = dynamic_cast<BrokenGreenlet*>(self->pimpl);
- return PyBool_FromLong(broken->_force_switch_error);
-}
-
-static int
-green_unswitchable_setforce(PyGreenlet* self, BorrowedObject nforce, void* UNUSED(context))
-{
- if (!nforce) {
- PyErr_SetString(
- PyExc_AttributeError,
- "Cannot delete force_switch_error"
- );
- return -1;
- }
- BrokenGreenlet* broken = dynamic_cast<BrokenGreenlet*>(self->pimpl);
- int is_true = PyObject_IsTrue(nforce);
- if (is_true == -1) {
- return -1;
- }
- broken->_force_switch_error = is_true;
- return 0;
-}
-
-static PyObject*
-green_unswitchable_getforceslp(PyGreenlet* self, void* UNUSED(context))
-{
- BrokenGreenlet* broken = dynamic_cast<BrokenGreenlet*>(self->pimpl);
- return PyBool_FromLong(broken->_force_slp_switch_error);
-}
-
-static int
-green_unswitchable_setforceslp(PyGreenlet* self, BorrowedObject nforce, void* UNUSED(context))
-{
- if (!nforce) {
- PyErr_SetString(
- PyExc_AttributeError,
- "Cannot delete force_slp_switch_error"
- );
- return -1;
- }
- BrokenGreenlet* broken = dynamic_cast<BrokenGreenlet*>(self->pimpl);
- int is_true = PyObject_IsTrue(nforce);
- if (is_true == -1) {
- return -1;
- }
- broken->_force_slp_switch_error = is_true;
- return 0;
-}
-
-static PyGetSetDef green_unswitchable_getsets[] = {
- /* name, getter, setter, doc, context pointer */
- {"force_switch_error",
- (getter)green_unswitchable_getforce,
- (setter)green_unswitchable_setforce,
- /*XXX*/ NULL},
- {"force_slp_switch_error",
- (getter)green_unswitchable_getforceslp,
- (setter)green_unswitchable_setforceslp,
- /*XXX*/ NULL},
-
- {NULL}
-};
-
-PyTypeObject PyGreenletUnswitchable_Type = {
- PyVarObject_HEAD_INIT(NULL, 0)
- "greenlet._greenlet.UnswitchableGreenlet",
- 0, /* tp_basicsize */
- 0, /* tp_itemsize */
- /* methods */
- (destructor)green_dealloc, /* tp_dealloc */
- 0, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- 0, /* tp_compare */
- 0, /* tp_repr */
- 0, /* tp_as _number*/
- 0, /* tp_as _sequence*/
- 0, /* tp_as _mapping*/
- 0, /* tp_hash */
- 0, /* tp_call */
- 0, /* tp_str */
- 0, /* tp_getattro */
- 0, /* tp_setattro */
- 0, /* tp_as_buffer*/
- G_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
- "Undocumented internal class", /* tp_doc */
- (traverseproc)green_traverse, /* tp_traverse */
- (inquiry)green_clear, /* tp_clear */
- 0, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- 0, /* tp_iter */
- 0, /* tp_iternext */
- 0, /* tp_methods */
- 0, /* tp_members */
- green_unswitchable_getsets, /* tp_getset */
- &PyGreenlet_Type, /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- 0, /* tp_dictoffset */
- (initproc)green_init, /* tp_init */
- PyType_GenericAlloc, /* tp_alloc */
- (newfunc)green_unswitchable_new, /* tp_new */
- PyObject_GC_Del, /* tp_free */
- (inquiry)green_is_gc, /* tp_is_gc */
-};
-
-
-PyDoc_STRVAR(mod_getcurrent_doc,
- "getcurrent() -> greenlet\n"
- "\n"
- "Returns the current greenlet (i.e. the one which called this "
- "function).\n");
-
-static PyObject*
-mod_getcurrent(PyObject* UNUSED(module))
-{
- return GET_THREAD_STATE().state().get_current().relinquish_ownership_o();
-}
-
-PyDoc_STRVAR(mod_settrace_doc,
- "settrace(callback) -> object\n"
- "\n"
- "Sets a new tracing function and returns the previous one.\n");
-static PyObject*
-mod_settrace(PyObject* UNUSED(module), PyObject* args)
-{
- PyArgParseParam tracefunc;
- if (!PyArg_ParseTuple(args, "O", &tracefunc)) {
- return NULL;
- }
- ThreadState& state = GET_THREAD_STATE();
- OwnedObject previous = state.get_tracefunc();
- if (!previous) {
- previous = Py_None;
- }
-
- state.set_tracefunc(tracefunc);
-
- return previous.relinquish_ownership();
-}
-
-PyDoc_STRVAR(mod_gettrace_doc,
- "gettrace() -> object\n"
- "\n"
- "Returns the currently set tracing function, or None.\n");
-
-static PyObject*
-mod_gettrace(PyObject* UNUSED(module))
-{
- OwnedObject tracefunc = GET_THREAD_STATE().state().get_tracefunc();
- if (!tracefunc) {
- tracefunc = Py_None;
- }
- return tracefunc.relinquish_ownership();
-}
-
-PyDoc_STRVAR(mod_set_thread_local_doc,
- "set_thread_local(key, value) -> None\n"
- "\n"
- "Set a value in the current thread-local dictionary. Debbuging only.\n");
-
-static PyObject*
-mod_set_thread_local(PyObject* UNUSED(module), PyObject* args)
-{
- PyArgParseParam key;
- PyArgParseParam value;
- PyObject* result = NULL;
-
- if (PyArg_UnpackTuple(args, "set_thread_local", 2, 2, &key, &value)) {
- if(PyDict_SetItem(
- PyThreadState_GetDict(), // borrow
- key,
- value) == 0 ) {
- // success
- Py_INCREF(Py_None);
- result = Py_None;
- }
- }
- return result;
-}
-
-PyDoc_STRVAR(mod_get_pending_cleanup_count_doc,
- "get_pending_cleanup_count() -> Integer\n"
- "\n"
- "Get the number of greenlet cleanup operations pending. Testing only.\n");
-
-
-static PyObject*
-mod_get_pending_cleanup_count(PyObject* UNUSED(module))
-{
- LockGuard cleanup_lock(*mod_globs->thread_states_to_destroy_lock);
- return PyLong_FromSize_t(mod_globs->thread_states_to_destroy.size());
-}
-
-PyDoc_STRVAR(mod_get_total_main_greenlets_doc,
- "get_total_main_greenlets() -> Integer\n"
- "\n"
- "Quickly return the number of main greenlets that exist. Testing only.\n");
-
-static PyObject*
-mod_get_total_main_greenlets(PyObject* UNUSED(module))
-{
- return PyLong_FromSize_t(G_TOTAL_MAIN_GREENLETS);
-}
-
-PyDoc_STRVAR(mod_get_clocks_used_doing_optional_cleanup_doc,
- "get_clocks_used_doing_optional_cleanup() -> Integer\n"
- "\n"
- "Get the number of clock ticks the program has used doing optional "
- "greenlet cleanup.\n"
- "Beginning in greenlet 2.0, greenlet tries to find and dispose of greenlets\n"
- "that leaked after a thread exited. This requires invoking Python's garbage collector,\n"
- "which may have a performance cost proportional to the number of live objects.\n"
- "This function returns the amount of processor time\n"
- "greenlet has used to do this. In programs that run with very large amounts of live\n"
- "objects, this metric can be used to decide whether the cost of doing this cleanup\n"
- "is worth the memory leak being corrected. If not, you can disable the cleanup\n"
- "using ``enable_optional_cleanup(False)``.\n"
- "The units are arbitrary and can only be compared to themselves (similarly to ``time.clock()``);\n"
- "for example, to see how it scales with your heap. You can attempt to convert them into seconds\n"
- "by dividing by the value of CLOCKS_PER_SEC."
- "If cleanup has been disabled, returns None."
- "\n"
- "This is an implementation specific, provisional API. It may be changed or removed\n"
- "in the future.\n"
- ".. versionadded:: 2.0"
- );
-static PyObject*
-mod_get_clocks_used_doing_optional_cleanup(PyObject* UNUSED(module))
-{
- std::clock_t& clocks = ThreadState::clocks_used_doing_gc();
-
- if (clocks == std::clock_t(-1)) {
- Py_RETURN_NONE;
- }
- // This might not actually work on some implementations; clock_t
- // is an opaque type.
- return PyLong_FromSsize_t(clocks);
-}
-
-PyDoc_STRVAR(mod_enable_optional_cleanup_doc,
- "mod_enable_optional_cleanup(bool) -> None\n"
- "\n"
- "Enable or disable optional cleanup operations.\n"
- "See ``get_clocks_used_doing_optional_cleanup()`` for details.\n"
- );
-static PyObject*
-mod_enable_optional_cleanup(PyObject* UNUSED(module), PyObject* flag)
-{
- int is_true = PyObject_IsTrue(flag);
- if (is_true == -1) {
- return nullptr;
- }
-
- std::clock_t& clocks = ThreadState::clocks_used_doing_gc();
- if (is_true) {
- // If we already have a value, we don't want to lose it.
- if (clocks == std::clock_t(-1)) {
- clocks = 0;
- }
- }
- else {
- clocks = std::clock_t(-1);
- }
- Py_RETURN_NONE;
-}
-
-PyDoc_STRVAR(mod_get_tstate_trash_delete_nesting_doc,
- "get_tstate_trash_delete_nesting() -> Integer\n"
- "\n"
- "Return the 'trash can' nesting level. Testing only.\n");
-static PyObject*
-mod_get_tstate_trash_delete_nesting(PyObject* UNUSED(module))
-{
- PyThreadState* tstate = PyThreadState_GET();
-
-#if GREENLET_PY312
- return PyLong_FromLong(tstate->trash.delete_nesting);
-#else
- return PyLong_FromLong(tstate->trash_delete_nesting);
-#endif
-}
-
-static PyMethodDef GreenMethods[] = {
- {"getcurrent",
- (PyCFunction)mod_getcurrent,
- METH_NOARGS,
- mod_getcurrent_doc},
- {"settrace", (PyCFunction)mod_settrace, METH_VARARGS, mod_settrace_doc},
- {"gettrace", (PyCFunction)mod_gettrace, METH_NOARGS, mod_gettrace_doc},
- {"set_thread_local", (PyCFunction)mod_set_thread_local, METH_VARARGS, mod_set_thread_local_doc},
- {"get_pending_cleanup_count", (PyCFunction)mod_get_pending_cleanup_count, METH_NOARGS, mod_get_pending_cleanup_count_doc},
- {"get_total_main_greenlets", (PyCFunction)mod_get_total_main_greenlets, METH_NOARGS, mod_get_total_main_greenlets_doc},
- {"get_clocks_used_doing_optional_cleanup", (PyCFunction)mod_get_clocks_used_doing_optional_cleanup, METH_NOARGS, mod_get_clocks_used_doing_optional_cleanup_doc},
- {"enable_optional_cleanup", (PyCFunction)mod_enable_optional_cleanup, METH_O, mod_enable_optional_cleanup_doc},
- {"get_tstate_trash_delete_nesting", (PyCFunction)mod_get_tstate_trash_delete_nesting, METH_NOARGS, mod_get_tstate_trash_delete_nesting_doc},
- {NULL, NULL} /* Sentinel */
-};
-
-static const char* const copy_on_greentype[] = {
- "getcurrent",
- "error",
- "GreenletExit",
- "settrace",
- "gettrace",
- NULL
-};
-
-static struct PyModuleDef greenlet_module_def = {
- PyModuleDef_HEAD_INIT,
- "greenlet._greenlet",
- NULL,
- -1,
- GreenMethods,
-};
-
-
-
-static PyObject*
-greenlet_internal_mod_init() noexcept
-{
- static void* _PyGreenlet_API[PyGreenlet_API_pointers];
-
- try {
- CreatedModule m(greenlet_module_def);
-
- Require(PyType_Ready(&PyGreenlet_Type));
- Require(PyType_Ready(&PyGreenletUnswitchable_Type));
-
- mod_globs = new greenlet::GreenletGlobals;
- ThreadState::init();
-
- m.PyAddObject("greenlet", PyGreenlet_Type);
- m.PyAddObject("UnswitchableGreenlet", PyGreenletUnswitchable_Type);
- m.PyAddObject("error", mod_globs->PyExc_GreenletError);
- m.PyAddObject("GreenletExit", mod_globs->PyExc_GreenletExit);
-
- m.PyAddObject("GREENLET_USE_GC", 1);
- m.PyAddObject("GREENLET_USE_TRACING", 1);
- m.PyAddObject("GREENLET_USE_CONTEXT_VARS", 1L);
- m.PyAddObject("GREENLET_USE_STANDARD_THREADING", 1L);
-
- OwnedObject clocks_per_sec = OwnedObject::consuming(PyLong_FromSsize_t(CLOCKS_PER_SEC));
- m.PyAddObject("CLOCKS_PER_SEC", clocks_per_sec);
-
- /* also publish module-level data as attributes of the greentype. */
- // XXX: This is weird, and enables a strange pattern of
- // confusing the class greenlet with the module greenlet; with
- // the exception of (possibly) ``getcurrent()``, this
- // shouldn't be encouraged so don't add new items here.
- for (const char* const* p = copy_on_greentype; *p; p++) {
- OwnedObject o = m.PyRequireAttr(*p);
- PyDict_SetItemString(PyGreenlet_Type.tp_dict, *p, o.borrow());
- }
-
- /*
- * Expose C API
- */
-
- /* types */
- _PyGreenlet_API[PyGreenlet_Type_NUM] = (void*)&PyGreenlet_Type;
-
- /* exceptions */
- _PyGreenlet_API[PyExc_GreenletError_NUM] = (void*)mod_globs->PyExc_GreenletError;
- _PyGreenlet_API[PyExc_GreenletExit_NUM] = (void*)mod_globs->PyExc_GreenletExit;
-
- /* methods */
- _PyGreenlet_API[PyGreenlet_New_NUM] = (void*)PyGreenlet_New;
- _PyGreenlet_API[PyGreenlet_GetCurrent_NUM] = (void*)PyGreenlet_GetCurrent;
- _PyGreenlet_API[PyGreenlet_Throw_NUM] = (void*)PyGreenlet_Throw;
- _PyGreenlet_API[PyGreenlet_Switch_NUM] = (void*)PyGreenlet_Switch;
- _PyGreenlet_API[PyGreenlet_SetParent_NUM] = (void*)PyGreenlet_SetParent;
-
- /* Previously macros, but now need to be functions externally. */
- _PyGreenlet_API[PyGreenlet_MAIN_NUM] = (void*)Extern_PyGreenlet_MAIN;
- _PyGreenlet_API[PyGreenlet_STARTED_NUM] = (void*)Extern_PyGreenlet_STARTED;
- _PyGreenlet_API[PyGreenlet_ACTIVE_NUM] = (void*)Extern_PyGreenlet_ACTIVE;
- _PyGreenlet_API[PyGreenlet_GET_PARENT_NUM] = (void*)Extern_PyGreenlet_GET_PARENT;
-
- /* XXX: Note that our module name is ``greenlet._greenlet``, but for
- backwards compatibility with existing C code, we need the _C_API to
- be directly in greenlet.
- */
- const NewReference c_api_object(Require(
- PyCapsule_New(
- (void*)_PyGreenlet_API,
- "greenlet._C_API",
- NULL)));
- m.PyAddObject("_C_API", c_api_object);
- assert(c_api_object.REFCNT() == 2);
-
- // cerr << "Sizes:"
- // << "\n\tGreenlet : " << sizeof(Greenlet)
- // << "\n\tUserGreenlet : " << sizeof(UserGreenlet)
- // << "\n\tMainGreenlet : " << sizeof(MainGreenlet)
- // << "\n\tExceptionState : " << sizeof(greenlet::ExceptionState)
- // << "\n\tPythonState : " << sizeof(greenlet::PythonState)
- // << "\n\tStackState : " << sizeof(greenlet::StackState)
- // << "\n\tSwitchingArgs : " << sizeof(greenlet::SwitchingArgs)
- // << "\n\tOwnedObject : " << sizeof(greenlet::refs::OwnedObject)
- // << "\n\tBorrowedObject : " << sizeof(greenlet::refs::BorrowedObject)
- // << "\n\tPyGreenlet : " << sizeof(PyGreenlet)
- // << endl;
-
- return m.borrow(); // But really it's the main reference.
- }
- catch (const LockInitError& e) {
- PyErr_SetString(PyExc_MemoryError, e.what());
- return NULL;
- }
- catch (const PyErrOccurred&) {
- return NULL;
- }
-
-}
-
-extern "C" {
-
-PyMODINIT_FUNC
-PyInit__greenlet(void)
-{
- return greenlet_internal_mod_init();
-}
-
-}; // extern C
-
-#ifdef __clang__
-# pragma clang diagnostic pop
-#elif defined(__GNUC__)
-# pragma GCC diagnostic pop
-#endif
diff --git a/venv/lib/python3.11/site-packages/greenlet/greenlet.h b/venv/lib/python3.11/site-packages/greenlet/greenlet.h
deleted file mode 100644
index d02a16e..0000000
--- a/venv/lib/python3.11/site-packages/greenlet/greenlet.h
+++ /dev/null
@@ -1,164 +0,0 @@
-/* -*- indent-tabs-mode: nil; tab-width: 4; -*- */
-
-/* Greenlet object interface */
-
-#ifndef Py_GREENLETOBJECT_H
-#define Py_GREENLETOBJECT_H
-
-
-#include <Python.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* This is deprecated and undocumented. It does not change. */
-#define GREENLET_VERSION "1.0.0"
-
-#ifndef GREENLET_MODULE
-#define implementation_ptr_t void*
-#endif
-
-typedef struct _greenlet {
- PyObject_HEAD
- PyObject* weakreflist;
- PyObject* dict;
- implementation_ptr_t pimpl;
-} PyGreenlet;
-
-#define PyGreenlet_Check(op) (op && PyObject_TypeCheck(op, &PyGreenlet_Type))
-
-
-/* C API functions */
-
-/* Total number of symbols that are exported */
-#define PyGreenlet_API_pointers 12
-
-#define PyGreenlet_Type_NUM 0
-#define PyExc_GreenletError_NUM 1
-#define PyExc_GreenletExit_NUM 2
-
-#define PyGreenlet_New_NUM 3
-#define PyGreenlet_GetCurrent_NUM 4
-#define PyGreenlet_Throw_NUM 5
-#define PyGreenlet_Switch_NUM 6
-#define PyGreenlet_SetParent_NUM 7
-
-#define PyGreenlet_MAIN_NUM 8
-#define PyGreenlet_STARTED_NUM 9
-#define PyGreenlet_ACTIVE_NUM 10
-#define PyGreenlet_GET_PARENT_NUM 11
-
-#ifndef GREENLET_MODULE
-/* This section is used by modules that uses the greenlet C API */
-static void** _PyGreenlet_API = NULL;
-
-# define PyGreenlet_Type \
- (*(PyTypeObject*)_PyGreenlet_API[PyGreenlet_Type_NUM])
-
-# define PyExc_GreenletError \
- ((PyObject*)_PyGreenlet_API[PyExc_GreenletError_NUM])
-
-# define PyExc_GreenletExit \
- ((PyObject*)_PyGreenlet_API[PyExc_GreenletExit_NUM])
-
-/*
- * PyGreenlet_New(PyObject *args)
- *
- * greenlet.greenlet(run, parent=None)
- */
-# define PyGreenlet_New \
- (*(PyGreenlet * (*)(PyObject * run, PyGreenlet * parent)) \
- _PyGreenlet_API[PyGreenlet_New_NUM])
-
-/*
- * PyGreenlet_GetCurrent(void)
- *
- * greenlet.getcurrent()
- */
-# define PyGreenlet_GetCurrent \
- (*(PyGreenlet * (*)(void)) _PyGreenlet_API[PyGreenlet_GetCurrent_NUM])
-
-/*
- * PyGreenlet_Throw(
- * PyGreenlet *greenlet,
- * PyObject *typ,
- * PyObject *val,
- * PyObject *tb)
- *
- * g.throw(...)
- */
-# define PyGreenlet_Throw \
- (*(PyObject * (*)(PyGreenlet * self, \
- PyObject * typ, \
- PyObject * val, \
- PyObject * tb)) \
- _PyGreenlet_API[PyGreenlet_Throw_NUM])
-
-/*
- * PyGreenlet_Switch(PyGreenlet *greenlet, PyObject *args)
- *
- * g.switch(*args, **kwargs)
- */
-# define PyGreenlet_Switch \
- (*(PyObject * \
- (*)(PyGreenlet * greenlet, PyObject * args, PyObject * kwargs)) \
- _PyGreenlet_API[PyGreenlet_Switch_NUM])
-
-/*
- * PyGreenlet_SetParent(PyObject *greenlet, PyObject *new_parent)
- *
- * g.parent = new_parent
- */
-# define PyGreenlet_SetParent \
- (*(int (*)(PyGreenlet * greenlet, PyGreenlet * nparent)) \
- _PyGreenlet_API[PyGreenlet_SetParent_NUM])
-
-/*
- * PyGreenlet_GetParent(PyObject* greenlet)
- *
- * return greenlet.parent;
- *
- * This could return NULL even if there is no exception active.
- * If it does not return NULL, you are responsible for decrementing the
- * reference count.
- */
-# define PyGreenlet_GetParent \
- (*(PyGreenlet* (*)(PyGreenlet*)) \
- _PyGreenlet_API[PyGreenlet_GET_PARENT_NUM])
-
-/*
- * deprecated, undocumented alias.
- */
-# define PyGreenlet_GET_PARENT PyGreenlet_GetParent
-
-# define PyGreenlet_MAIN \
- (*(int (*)(PyGreenlet*)) \
- _PyGreenlet_API[PyGreenlet_MAIN_NUM])
-
-# define PyGreenlet_STARTED \
- (*(int (*)(PyGreenlet*)) \
- _PyGreenlet_API[PyGreenlet_STARTED_NUM])
-
-# define PyGreenlet_ACTIVE \
- (*(int (*)(PyGreenlet*)) \
- _PyGreenlet_API[PyGreenlet_ACTIVE_NUM])
-
-
-
-
-/* Macro that imports greenlet and initializes C API */
-/* NOTE: This has actually moved to ``greenlet._greenlet._C_API``, but we
- keep the older definition to be sure older code that might have a copy of
- the header still works. */
-# define PyGreenlet_Import() \
- { \
- _PyGreenlet_API = (void**)PyCapsule_Import("greenlet._C_API", 0); \
- }
-
-#endif /* GREENLET_MODULE */
-
-#ifdef __cplusplus
-}
-#endif
-#endif /* !Py_GREENLETOBJECT_H */
diff --git a/venv/lib/python3.11/site-packages/greenlet/greenlet_allocator.hpp b/venv/lib/python3.11/site-packages/greenlet/greenlet_allocator.hpp
deleted file mode 100644
index b452f54..0000000
--- a/venv/lib/python3.11/site-packages/greenlet/greenlet_allocator.hpp
+++ /dev/null
@@ -1,63 +0,0 @@
-#ifndef GREENLET_ALLOCATOR_HPP
-#define GREENLET_ALLOCATOR_HPP
-
-#define PY_SSIZE_T_CLEAN
-#include <Python.h>
-#include <memory>
-#include "greenlet_compiler_compat.hpp"
-
-
-namespace greenlet
-{
- // This allocator is stateless; all instances are identical.
- // It can *ONLY* be used when we're sure we're holding the GIL
- // (Python's allocators require the GIL).
- template <class T>
- struct PythonAllocator : public std::allocator<T> {
-
- PythonAllocator(const PythonAllocator& UNUSED(other))
- : std::allocator<T>()
- {
- }
-
- PythonAllocator(const std::allocator<T> other)
- : std::allocator<T>(other)
- {}
-
- template <class U>
- PythonAllocator(const std::allocator<U>& other)
- : std::allocator<T>(other)
- {
- }
-
- PythonAllocator() : std::allocator<T>() {}
-
- T* allocate(size_t number_objects, const void* UNUSED(hint)=0)
- {
- void* p;
- if (number_objects == 1)
- p = PyObject_Malloc(sizeof(T));
- else
- p = PyMem_Malloc(sizeof(T) * number_objects);
- return static_cast<T*>(p);
- }
-
- void deallocate(T* t, size_t n)
- {
- void* p = t;
- if (n == 1) {
- PyObject_Free(p);
- }
- else
- PyMem_Free(p);
- }
- // This member is deprecated in C++17 and removed in C++20
- template< class U >
- struct rebind {
- typedef PythonAllocator<U> other;
- };
-
- };
-}
-
-#endif
diff --git a/venv/lib/python3.11/site-packages/greenlet/greenlet_compiler_compat.hpp b/venv/lib/python3.11/site-packages/greenlet/greenlet_compiler_compat.hpp
deleted file mode 100644
index ee5bbdd..0000000
--- a/venv/lib/python3.11/site-packages/greenlet/greenlet_compiler_compat.hpp
+++ /dev/null
@@ -1,95 +0,0 @@
-/* -*- indent-tabs-mode: nil; tab-width: 4; -*- */
-#ifndef GREENLET_COMPILER_COMPAT_HPP
-#define GREENLET_COMPILER_COMPAT_HPP
-
-/**
- * Definitions to aid with compatibility with different compilers.
- *
- * .. caution:: Use extreme care with noexcept.
- * Some compilers and runtimes, specifically gcc/libgcc/libstdc++ on
- * Linux, implement stack unwinding by throwing an uncatchable
- * exception, one that specifically does not appear to be an active
- * exception to the rest of the runtime. If this happens while we're in a noexcept function,
- * we have violated our dynamic exception contract, and so the runtime
- * will call std::terminate(), which kills the process with the
- * unhelpful message "terminate called without an active exception".
- *
- * This has happened in this scenario: A background thread is running
- * a greenlet that has made a native call and released the GIL.
- * Meanwhile, the main thread finishes and starts shutting down the
- * interpreter. When the background thread is scheduled again and
- * attempts to obtain the GIL, it notices that the interpreter is
- * exiting and calls ``pthread_exit()``. This in turn starts to unwind
- * the stack by throwing that exception. But we had the ``PyCall``
- * functions annotated as noexcept, so the runtime terminated us.
- *
- * #2 0x00007fab26fec2b7 in std::terminate() () from /lib/x86_64-linux-gnu/libstdc++.so.6
- * #3 0x00007fab26febb3c in __gxx_personality_v0 () from /lib/x86_64-linux-gnu/libstdc++.so.6
- * #4 0x00007fab26f34de6 in ?? () from /lib/x86_64-linux-gnu/libgcc_s.so.1
- * #6 0x00007fab276a34c6 in __GI___pthread_unwind at ./nptl/unwind.c:130
- * #7 0x00007fab2769bd3a in __do_cancel () at ../sysdeps/nptl/pthreadP.h:280
- * #8 __GI___pthread_exit (value=value@entry=0x0) at ./nptl/pthread_exit.c:36
- * #9 0x000000000052e567 in PyThread_exit_thread () at ../Python/thread_pthread.h:370
- * #10 0x00000000004d60b5 in take_gil at ../Python/ceval_gil.h:224
- * #11 0x00000000004d65f9 in PyEval_RestoreThread at ../Python/ceval.c:467
- * #12 0x000000000060cce3 in setipaddr at ../Modules/socketmodule.c:1203
- * #13 0x00000000006101cd in socket_gethostbyname
- */
-
-#include <cstdint>
-
-# if defined(__clang__)
-# define G_FP_TMPL_STATIC static
-# else
-// GCC has no problem allowing static function pointers, but emits
-// tons of warnings about "whose type uses the anonymous namespace [-Wsubobject-linkage]"
-# define G_FP_TMPL_STATIC
-# endif
-
-# define G_NO_COPIES_OF_CLS(Cls) private: \
- Cls(const Cls& other) = delete; \
- Cls& operator=(const Cls& other) = delete
-
-# define G_NO_ASSIGNMENT_OF_CLS(Cls) private: \
- Cls& operator=(const Cls& other) = delete
-
-# define G_NO_COPY_CONSTRUCTOR_OF_CLS(Cls) private: \
- Cls(const Cls& other) = delete;
-
-
-// CAUTION: MSVC is stupidly picky:
-//
-// "The compiler ignores, without warning, any __declspec keywords
-// placed after * or & and in front of the variable identifier in a
-// declaration."
-// (https://docs.microsoft.com/en-us/cpp/cpp/declspec?view=msvc-160)
-//
-// So pointer return types must be handled differently (because of the
-// trailing *), or you get inscrutable compiler warnings like "error
-// C2059: syntax error: ''"
-//
-// In C++ 11, there is a standard syntax for attributes, and
-// GCC defines an attribute to use with this: [[gnu:noinline]].
-// In the future, this is expected to become standard.
-
-#if defined(__GNUC__) || defined(__clang__)
-/* We used to check for GCC 4+ or 3.4+, but those compilers are
- laughably out of date. Just assume they support it. */
-# define GREENLET_NOINLINE(name) __attribute__((noinline)) name
-# define GREENLET_NOINLINE_P(rtype, name) rtype __attribute__((noinline)) name
-# define UNUSED(x) UNUSED_ ## x __attribute__((__unused__))
-#elif defined(_MSC_VER)
-/* We used to check for && (_MSC_VER >= 1300) but that's also out of date. */
-# define GREENLET_NOINLINE(name) __declspec(noinline) name
-# define GREENLET_NOINLINE_P(rtype, name) __declspec(noinline) rtype name
-# define UNUSED(x) UNUSED_ ## x
-#endif
-
-#if defined(_MSC_VER)
-# define G_NOEXCEPT_WIN32 noexcept
-#else
-# define G_NOEXCEPT_WIN32
-#endif
-
-
-#endif
diff --git a/venv/lib/python3.11/site-packages/greenlet/greenlet_cpython_add_pending.hpp b/venv/lib/python3.11/site-packages/greenlet/greenlet_cpython_add_pending.hpp
deleted file mode 100644
index 0d28efd..0000000
--- a/venv/lib/python3.11/site-packages/greenlet/greenlet_cpython_add_pending.hpp
+++ /dev/null
@@ -1,172 +0,0 @@
-#ifndef GREENLET_CPYTHON_ADD_PENDING_HPP
-#define GREENLET_CPYTHON_ADD_PENDING_HPP
-
-#if (PY_VERSION_HEX >= 0x30800A0 && PY_VERSION_HEX < 0x3090000) && !(defined(_WIN32) || defined(WIN32))
-// XXX: From Python 3.8a3 [1] up until Python 3.9a6 [2][3],
-// ``Py_AddPendingCall`` would try to produce a Python exception if
-// the interpreter was in the beginning of shutting down when this
-// function is called. However, ``Py_AddPendingCall`` doesn't require
-// the GIL, and we are absolutely not holding it when we make that
-// call. That means that trying to create the Python exception is
-// using the C API in an undefined state; here the C API detects this
-// and aborts the process with an error ("Fatal Python error: Python
-// memory allocator called without holding the GIL": Add ->
-// PyErr_SetString -> PyUnicode_New -> PyObject_Malloc). This arises
-// (obviously) in multi-threaded programs and happens if one thread is
-// exiting and cleaning up its thread-local data while the other
-// thread is trying to shut down the interpreter. A crash on shutdown
-// is still a crash and could result in data loss (e.g., daemon
-// threads are still running, pending signal handlers may be present,
-// buffers may not be flushed, there may be __del__ that need run,
-// etc), so we have to work around it.
-//
-// Of course, we can (and do) check for whether the interpreter is
-// shutting down before calling ``Py_AddPendingCall``, but that's a
-// race condition since we don't hold the GIL, and so we may not
-// actually get the right answer. Plus, ``Py_FinalizeEx`` actually
-// calls ``_Py_FinishPendingCalls`` (which sets the pending->finishing
-// flag, which is used to gate creating the exceptioen) *before*
-// publishing any other data that would let us detect the shutdown
-// (such as runtime->finalizing). So that point is moot.
-//
-// Our solution for those versions is to inline the same code, without
-// the problematic bit that sets the exception. Unfortunately, all of
-// the structure definitions are private/opaque, *and* we can't
-// actually count on being able to include their definitions from
-// ``internal/pycore_*``, because on some platforms those header files
-// are incomplete (i.e., on macOS with macports 3.8, the includes are
-// fine, but on Ubuntu jammy with 3.8 from ppa:deadsnakes or GitHub
-// Actions 3.8 (I think it's Ubuntu 18.04), they con't be used; at
-// least, I couldn't get them to work). So we need to define the
-// structures and _PyRuntime data member ourself. Yet more
-// unfortunately, _PyRuntime won't link on Windows, so we can only do
-// this on other platforms.
-//
-// [1] https://github.com/python/cpython/commit/842a2f07f2f08a935ef470bfdaeef40f87490cfc
-// [2] https://github.com/python/cpython/commit/cfc3c2f8b34d3864717ab584c5b6c260014ba55a
-// [3] https://github.com/python/cpython/issues/81308
-# define GREENLET_BROKEN_PY_ADD_PENDING 1
-
-// When defining these structures, the important thing is to get
-// binary compatibility, i.e., structure layout. For that, we only
-// need to define fields up to the ones we use; after that they're
-// irrelevant UNLESS the structure is included in another structure
-// *before* the structure we're interested in --- in that case, it
-// must be complete. Ellipsis indicate elided trailing members.
-// Pointer types are changed to void* to keep from having to define
-// more structures.
-
-// From "internal/pycore_atomic.h"
-
-// There are several different definitions of this, including the
-// plain ``int`` version, a ``volatile int`` and an ``_Atomic int``
-// I don't think any of those change the size/layout.
-typedef struct _Py_atomic_int {
- volatile int _value;
-} _Py_atomic_int;
-
-// This needs too much infrastructure, so we just do a regular store.
-#define _Py_atomic_store_relaxed(ATOMIC_VAL, NEW_VAL) \
- (ATOMIC_VAL)->_value = NEW_VAL
-
-
-
-// From "internal/pycore_pymem.h"
-#define NUM_GENERATIONS 3
-
-
-struct gc_generation {
- PyGC_Head head; // We already have this defined.
- int threshold;
- int count;
-};
-struct gc_generation_stats {
- Py_ssize_t collections;
- Py_ssize_t collected;
- Py_ssize_t uncollectable;
-};
-
-struct _gc_runtime_state {
- void *trash_delete_later;
- int trash_delete_nesting;
- int enabled;
- int debug;
- struct gc_generation generations[NUM_GENERATIONS];
- void *generation0;
- struct gc_generation permanent_generation;
- struct gc_generation_stats generation_stats[NUM_GENERATIONS];
- int collecting;
- void *garbage;
- void *callbacks;
- Py_ssize_t long_lived_total;
- Py_ssize_t long_lived_pending;
-};
-
-// From "internal/pycore_pystate.h"
-struct _pending_calls {
- int finishing;
- PyThread_type_lock lock;
- _Py_atomic_int calls_to_do;
- int async_exc;
-#define NPENDINGCALLS 32
- struct {
- int (*func)(void *);
- void *arg;
- } calls[NPENDINGCALLS];
- int first;
- int last;
-};
-
-struct _ceval_runtime_state {
- int recursion_limit;
- int tracing_possible;
- _Py_atomic_int eval_breaker;
- _Py_atomic_int gil_drop_request;
- struct _pending_calls pending;
- // ...
-};
-
-typedef struct pyruntimestate {
- int preinitializing;
- int preinitialized;
- int core_initialized;
- int initialized;
- void *finalizing;
-
- struct pyinterpreters {
- PyThread_type_lock mutex;
- void *head;
- void *main;
- int64_t next_id;
- } interpreters;
- // XXX Remove this field once we have a tp_* slot.
- struct _xidregistry {
- PyThread_type_lock mutex;
- void *head;
- } xidregistry;
-
- unsigned long main_thread;
-
-#define NEXITFUNCS 32
- void (*exitfuncs[NEXITFUNCS])(void);
- int nexitfuncs;
-
- struct _gc_runtime_state gc;
- struct _ceval_runtime_state ceval;
- // ...
-} _PyRuntimeState;
-
-#define SIGNAL_PENDING_CALLS(ceval) \
- do { \
- _Py_atomic_store_relaxed(&(ceval)->pending.calls_to_do, 1); \
- _Py_atomic_store_relaxed(&(ceval)->eval_breaker, 1); \
- } while (0)
-
-extern _PyRuntimeState _PyRuntime;
-
-#else
-# define GREENLET_BROKEN_PY_ADD_PENDING 0
-#endif
-
-
-#endif
diff --git a/venv/lib/python3.11/site-packages/greenlet/greenlet_cpython_compat.hpp b/venv/lib/python3.11/site-packages/greenlet/greenlet_cpython_compat.hpp
deleted file mode 100644
index cdc1617..0000000
--- a/venv/lib/python3.11/site-packages/greenlet/greenlet_cpython_compat.hpp
+++ /dev/null
@@ -1,127 +0,0 @@
-/* -*- indent-tabs-mode: nil; tab-width: 4; -*- */
-#ifndef GREENLET_CPYTHON_COMPAT_H
-#define GREENLET_CPYTHON_COMPAT_H
-
-/**
- * Helpers for compatibility with multiple versions of CPython.
- */
-
-#define PY_SSIZE_T_CLEAN
-#include "Python.h"
-
-
-#if PY_VERSION_HEX >= 0x30A00B1
-# define GREENLET_PY310 1
-/*
-Python 3.10 beta 1 changed tstate->use_tracing to a nested cframe member.
-See https://github.com/python/cpython/pull/25276
-We have to save and restore this as well.
-*/
-# define GREENLET_USE_CFRAME 1
-#else
-# define GREENLET_USE_CFRAME 0
-# define GREENLET_PY310 0
-#endif
-
-
-
-#if PY_VERSION_HEX >= 0x30B00A4
-/*
-Greenlet won't compile on anything older than Python 3.11 alpha 4 (see
-https://bugs.python.org/issue46090). Summary of breaking internal changes:
-- Python 3.11 alpha 1 changed how frame objects are represented internally.
- - https://github.com/python/cpython/pull/30122
-- Python 3.11 alpha 3 changed how recursion limits are stored.
- - https://github.com/python/cpython/pull/29524
-- Python 3.11 alpha 4 changed how exception state is stored. It also includes a
- change to help greenlet save and restore the interpreter frame "data stack".
- - https://github.com/python/cpython/pull/30122
- - https://github.com/python/cpython/pull/30234
-*/
-# define GREENLET_PY311 1
-#else
-# define GREENLET_PY311 0
-#endif
-
-
-#if PY_VERSION_HEX >= 0x30C0000
-# define GREENLET_PY312 1
-#else
-# define GREENLET_PY312 0
-#endif
-
-#ifndef Py_SET_REFCNT
-/* Py_REFCNT and Py_SIZE macros are converted to functions
-https://bugs.python.org/issue39573 */
-# define Py_SET_REFCNT(obj, refcnt) Py_REFCNT(obj) = (refcnt)
-#endif
-
-#ifndef _Py_DEC_REFTOTAL
-/* _Py_DEC_REFTOTAL macro has been removed from Python 3.9 by:
- https://github.com/python/cpython/commit/49932fec62c616ec88da52642339d83ae719e924
-
- The symbol we use to replace it was removed by at least 3.12.
-*/
-# ifdef Py_REF_DEBUG
-# if GREENLET_PY312
-# define _Py_DEC_REFTOTAL
-# else
-# define _Py_DEC_REFTOTAL _Py_RefTotal--
-# endif
-# else
-# define _Py_DEC_REFTOTAL
-# endif
-#endif
-// Define these flags like Cython does if we're on an old version.
-#ifndef Py_TPFLAGS_CHECKTYPES
- #define Py_TPFLAGS_CHECKTYPES 0
-#endif
-#ifndef Py_TPFLAGS_HAVE_INDEX
- #define Py_TPFLAGS_HAVE_INDEX 0
-#endif
-#ifndef Py_TPFLAGS_HAVE_NEWBUFFER
- #define Py_TPFLAGS_HAVE_NEWBUFFER 0
-#endif
-
-#ifndef Py_TPFLAGS_HAVE_VERSION_TAG
- #define Py_TPFLAGS_HAVE_VERSION_TAG 0
-#endif
-
-#define G_TPFLAGS_DEFAULT Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_VERSION_TAG | Py_TPFLAGS_CHECKTYPES | Py_TPFLAGS_HAVE_NEWBUFFER | Py_TPFLAGS_HAVE_GC
-
-
-#if PY_VERSION_HEX < 0x03090000
-// The official version only became available in 3.9
-# define PyObject_GC_IsTracked(o) _PyObject_GC_IS_TRACKED(o)
-#endif
-
-
-// bpo-43760 added PyThreadState_EnterTracing() to Python 3.11.0a2
-#if PY_VERSION_HEX < 0x030B00A2 && !defined(PYPY_VERSION)
-static inline void PyThreadState_EnterTracing(PyThreadState *tstate)
-{
- tstate->tracing++;
-#if PY_VERSION_HEX >= 0x030A00A1
- tstate->cframe->use_tracing = 0;
-#else
- tstate->use_tracing = 0;
-#endif
-}
-#endif
-
-// bpo-43760 added PyThreadState_LeaveTracing() to Python 3.11.0a2
-#if PY_VERSION_HEX < 0x030B00A2 && !defined(PYPY_VERSION)
-static inline void PyThreadState_LeaveTracing(PyThreadState *tstate)
-{
- tstate->tracing--;
- int use_tracing = (tstate->c_tracefunc != NULL
- || tstate->c_profilefunc != NULL);
-#if PY_VERSION_HEX >= 0x030A00A1
- tstate->cframe->use_tracing = use_tracing;
-#else
- tstate->use_tracing = use_tracing;
-#endif
-}
-#endif
-
-#endif /* GREENLET_CPYTHON_COMPAT_H */
diff --git a/venv/lib/python3.11/site-packages/greenlet/greenlet_exceptions.hpp b/venv/lib/python3.11/site-packages/greenlet/greenlet_exceptions.hpp
deleted file mode 100644
index 3807018..0000000
--- a/venv/lib/python3.11/site-packages/greenlet/greenlet_exceptions.hpp
+++ /dev/null
@@ -1,150 +0,0 @@
-#ifndef GREENLET_EXCEPTIONS_HPP
-#define GREENLET_EXCEPTIONS_HPP
-
-#define PY_SSIZE_T_CLEAN
-#include <Python.h>
-#include <stdexcept>
-#include <string>
-
-#ifdef __clang__
-# pragma clang diagnostic push
-# pragma clang diagnostic ignored "-Wunused-function"
-#endif
-
-namespace greenlet {
-
- class PyErrOccurred : public std::runtime_error
- {
- public:
-
- // CAUTION: In debug builds, may run arbitrary Python code.
- static const PyErrOccurred
- from_current()
- {
- assert(PyErr_Occurred());
-#ifndef NDEBUG
- // This is not exception safe, and
- // not necessarily safe in general (what if it switches?)
- // But we only do this in debug mode, where we are in
- // tight control of what exceptions are getting raised and
- // can prevent those issues.
-
- // You can't call PyObject_Str with a pending exception.
- PyObject* typ;
- PyObject* val;
- PyObject* tb;
-
- PyErr_Fetch(&typ, &val, &tb);
- PyObject* typs = PyObject_Str(typ);
- PyObject* vals = PyObject_Str(val ? val : typ);
- const char* typ_msg = PyUnicode_AsUTF8(typs);
- const char* val_msg = PyUnicode_AsUTF8(vals);
- PyErr_Restore(typ, val, tb);
-
- std::string msg(typ_msg);
- msg += ": ";
- msg += val_msg;
- PyErrOccurred ex(msg);
- Py_XDECREF(typs);
- Py_XDECREF(vals);
-
- return ex;
-#else
- return PyErrOccurred();
-#endif
- }
-
- PyErrOccurred() : std::runtime_error("")
- {
- assert(PyErr_Occurred());
- }
-
- PyErrOccurred(const std::string& msg) : std::runtime_error(msg)
- {
- assert(PyErr_Occurred());
- }
-
- PyErrOccurred(PyObject* exc_kind, const char* const msg)
- : std::runtime_error(msg)
- {
- PyErr_SetString(exc_kind, msg);
- }
-
- PyErrOccurred(PyObject* exc_kind, const std::string msg)
- : std::runtime_error(msg)
- {
- // This copies the c_str, so we don't have any lifetime
- // issues to worry about.
- PyErr_SetString(exc_kind, msg.c_str());
- }
- };
-
- class TypeError : public PyErrOccurred
- {
- public:
- TypeError(const char* const what)
- : PyErrOccurred(PyExc_TypeError, what)
- {
- }
- TypeError(const std::string what)
- : PyErrOccurred(PyExc_TypeError, what)
- {
- }
- };
-
- class ValueError : public PyErrOccurred
- {
- public:
- ValueError(const char* const what)
- : PyErrOccurred(PyExc_ValueError, what)
- {
- }
- };
-
- class AttributeError : public PyErrOccurred
- {
- public:
- AttributeError(const char* const what)
- : PyErrOccurred(PyExc_AttributeError, what)
- {
- }
- };
-
- /**
- * Calls `Py_FatalError` when constructed, so you can't actually
- * throw this. It just makes static analysis easier.
- */
- class PyFatalError : public std::runtime_error
- {
- public:
- PyFatalError(const char* const msg)
- : std::runtime_error(msg)
- {
- Py_FatalError(msg);
- }
- };
-
- static inline PyObject*
- Require(PyObject* p, const std::string& msg="")
- {
- if (!p) {
- throw PyErrOccurred(msg);
- }
- return p;
- };
-
- static inline void
- Require(const int retval)
- {
- if (retval < 0) {
- throw PyErrOccurred();
- }
- };
-
-
-};
-#ifdef __clang__
-# pragma clang diagnostic pop
-#endif
-
-#endif
diff --git a/venv/lib/python3.11/site-packages/greenlet/greenlet_greenlet.hpp b/venv/lib/python3.11/site-packages/greenlet/greenlet_greenlet.hpp
deleted file mode 100644
index d52ce1f..0000000
--- a/venv/lib/python3.11/site-packages/greenlet/greenlet_greenlet.hpp
+++ /dev/null
@@ -1,805 +0,0 @@
-#ifndef GREENLET_GREENLET_HPP
-#define GREENLET_GREENLET_HPP
-/*
- * Declarations of the core data structures.
-*/
-
-#define PY_SSIZE_T_CLEAN
-#include <Python.h>
-
-#include "greenlet_compiler_compat.hpp"
-#include "greenlet_refs.hpp"
-#include "greenlet_cpython_compat.hpp"
-#include "greenlet_allocator.hpp"
-
-using greenlet::refs::OwnedObject;
-using greenlet::refs::OwnedGreenlet;
-using greenlet::refs::OwnedMainGreenlet;
-using greenlet::refs::BorrowedGreenlet;
-
-#if PY_VERSION_HEX < 0x30B00A6
-# define _PyCFrame CFrame
-# define _PyInterpreterFrame _interpreter_frame
-#endif
-
-#if GREENLET_PY312
-# include "internal/pycore_frame.h"
-#endif
-
-// XXX: TODO: Work to remove all virtual functions
-// for speed of calling and size of objects (no vtable).
-// One pattern is the Curiously Recurring Template
-namespace greenlet
-{
- class ExceptionState
- {
- private:
- G_NO_COPIES_OF_CLS(ExceptionState);
-
- // Even though these are borrowed objects, we actually own
- // them, when they're not null.
- // XXX: Express that in the API.
- private:
- _PyErr_StackItem* exc_info;
- _PyErr_StackItem exc_state;
- public:
- ExceptionState();
- void operator<<(const PyThreadState *const tstate) noexcept;
- void operator>>(PyThreadState* tstate) noexcept;
- void clear() noexcept;
-
- int tp_traverse(visitproc visit, void* arg) noexcept;
- void tp_clear() noexcept;
- };
-
- template<typename T>
- void operator<<(const PyThreadState *const tstate, T& exc);
-
- class PythonStateContext
- {
- protected:
- greenlet::refs::OwnedContext _context;
- public:
- inline const greenlet::refs::OwnedContext& context() const
- {
- return this->_context;
- }
- inline greenlet::refs::OwnedContext& context()
- {
- return this->_context;
- }
-
- inline void tp_clear()
- {
- this->_context.CLEAR();
- }
-
- template<typename T>
- inline static PyObject* context(T* tstate)
- {
- return tstate->context;
- }
-
- template<typename T>
- inline static void context(T* tstate, PyObject* new_context)
- {
- tstate->context = new_context;
- tstate->context_ver++;
- }
- };
- class SwitchingArgs;
- class PythonState : public PythonStateContext
- {
- public:
- typedef greenlet::refs::OwnedReference<struct _frame> OwnedFrame;
- private:
- G_NO_COPIES_OF_CLS(PythonState);
- // We own this if we're suspended (although currently we don't
- // tp_traverse into it; that's a TODO). If we're running, it's
- // empty. If we get deallocated and *still* have a frame, it
- // won't be reachable from the place that normally decref's
- // it, so we need to do it (hence owning it).
- OwnedFrame _top_frame;
-#if GREENLET_USE_CFRAME
- _PyCFrame* cframe;
- int use_tracing;
-#endif
-#if GREENLET_PY312
- int py_recursion_depth;
- int c_recursion_depth;
-#else
- int recursion_depth;
-#endif
- int trash_delete_nesting;
-#if GREENLET_PY311
- _PyInterpreterFrame* current_frame;
- _PyStackChunk* datastack_chunk;
- PyObject** datastack_top;
- PyObject** datastack_limit;
-#endif
- // The PyInterpreterFrame list on 3.12+ contains some entries that are
- // on the C stack, which can't be directly accessed while a greenlet is
- // suspended. In order to keep greenlet gr_frame introspection working,
- // we adjust stack switching to rewrite the interpreter frame list
- // to skip these C-stack frames; we call this "exposing" the greenlet's
- // frames because it makes them valid to work with in Python. Then when
- // the greenlet is resumed we need to remember to reverse the operation
- // we did. The C-stack frames are "entry frames" which are a low-level
- // interpreter detail; they're not needed for introspection, but do
- // need to be present for the eval loop to work.
- void unexpose_frames();
-
- public:
-
- PythonState();
- // You can use this for testing whether we have a frame
- // or not. It returns const so they can't modify it.
- const OwnedFrame& top_frame() const noexcept;
-
- inline void operator<<(const PyThreadState *const tstate) noexcept;
- inline void operator>>(PyThreadState* tstate) noexcept;
- void clear() noexcept;
-
- int tp_traverse(visitproc visit, void* arg, bool visit_top_frame) noexcept;
- void tp_clear(bool own_top_frame) noexcept;
- void set_initial_state(const PyThreadState* const tstate) noexcept;
-#if GREENLET_USE_CFRAME
- void set_new_cframe(_PyCFrame& frame) noexcept;
-#endif
-
- inline void may_switch_away() noexcept;
- inline void will_switch_from(PyThreadState *const origin_tstate) noexcept;
- void did_finish(PyThreadState* tstate) noexcept;
- };
-
- class StackState
- {
- // By having only plain C (POD) members, no virtual functions
- // or bases, we get a trivial assignment operator generated
- // for us. However, that's not safe since we do manage memory.
- // So we declare an assignment operator that only works if we
- // don't have any memory allocated. (We don't use
- // std::shared_ptr for reference counting just to keep this
- // object small)
- private:
- char* _stack_start;
- char* stack_stop;
- char* stack_copy;
- intptr_t _stack_saved;
- StackState* stack_prev;
- inline int copy_stack_to_heap_up_to(const char* const stop) noexcept;
- inline void free_stack_copy() noexcept;
-
- public:
- /**
- * Creates a started, but inactive, state, using *current*
- * as the previous.
- */
- StackState(void* mark, StackState& current);
- /**
- * Creates an inactive, unstarted, state.
- */
- StackState();
- ~StackState();
- StackState(const StackState& other);
- StackState& operator=(const StackState& other);
- inline void copy_heap_to_stack(const StackState& current) noexcept;
- inline int copy_stack_to_heap(char* const stackref, const StackState& current) noexcept;
- inline bool started() const noexcept;
- inline bool main() const noexcept;
- inline bool active() const noexcept;
- inline void set_active() noexcept;
- inline void set_inactive() noexcept;
- inline intptr_t stack_saved() const noexcept;
- inline char* stack_start() const noexcept;
- static inline StackState make_main() noexcept;
-#ifdef GREENLET_USE_STDIO
- friend std::ostream& operator<<(std::ostream& os, const StackState& s);
-#endif
-
- // Fill in [dest, dest + n) with the values that would be at
- // [src, src + n) while this greenlet is running. This is like memcpy
- // except that if the greenlet is suspended it accounts for the portion
- // of the greenlet's stack that was spilled to the heap. `src` may
- // be on this greenlet's stack, or on the heap, but not on a different
- // greenlet's stack.
- void copy_from_stack(void* dest, const void* src, size_t n) const;
- };
-#ifdef GREENLET_USE_STDIO
- std::ostream& operator<<(std::ostream& os, const StackState& s);
-#endif
-
- class SwitchingArgs
- {
- private:
- G_NO_ASSIGNMENT_OF_CLS(SwitchingArgs);
- // If args and kwargs are both false (NULL), this is a *throw*, not a
- // switch. PyErr_... must have been called already.
- OwnedObject _args;
- OwnedObject _kwargs;
- public:
-
- SwitchingArgs()
- {}
-
- SwitchingArgs(const OwnedObject& args, const OwnedObject& kwargs)
- : _args(args),
- _kwargs(kwargs)
- {}
-
- SwitchingArgs(const SwitchingArgs& other)
- : _args(other._args),
- _kwargs(other._kwargs)
- {}
-
- const OwnedObject& args()
- {
- return this->_args;
- }
-
- const OwnedObject& kwargs()
- {
- return this->_kwargs;
- }
-
- /**
- * Moves ownership from the argument to this object.
- */
- SwitchingArgs& operator<<=(SwitchingArgs& other)
- {
- if (this != &other) {
- this->_args = other._args;
- this->_kwargs = other._kwargs;
- other.CLEAR();
- }
- return *this;
- }
-
- /**
- * Acquires ownership of the argument (consumes the reference).
- */
- SwitchingArgs& operator<<=(PyObject* args)
- {
- this->_args = OwnedObject::consuming(args);
- this->_kwargs.CLEAR();
- return *this;
- }
-
- /**
- * Acquires ownership of the argument.
- *
- * Sets the args to be the given value; clears the kwargs.
- */
- SwitchingArgs& operator<<=(OwnedObject& args)
- {
- assert(&args != &this->_args);
- this->_args = args;
- this->_kwargs.CLEAR();
- args.CLEAR();
-
- return *this;
- }
-
- explicit operator bool() const noexcept
- {
- return this->_args || this->_kwargs;
- }
-
- inline void CLEAR()
- {
- this->_args.CLEAR();
- this->_kwargs.CLEAR();
- }
-
- const std::string as_str() const noexcept
- {
- return PyUnicode_AsUTF8(
- OwnedObject::consuming(
- PyUnicode_FromFormat(
- "SwitchingArgs(args=%R, kwargs=%R)",
- this->_args.borrow(),
- this->_kwargs.borrow()
- )
- ).borrow()
- );
- }
- };
-
- class ThreadState;
-
- class UserGreenlet;
- class MainGreenlet;
-
- class Greenlet
- {
- private:
- G_NO_COPIES_OF_CLS(Greenlet);
- private:
- // XXX: Work to remove these.
- friend class ThreadState;
- friend class UserGreenlet;
- friend class MainGreenlet;
- protected:
- ExceptionState exception_state;
- SwitchingArgs switch_args;
- StackState stack_state;
- PythonState python_state;
- Greenlet(PyGreenlet* p, const StackState& initial_state);
- public:
- Greenlet(PyGreenlet* p);
- virtual ~Greenlet();
-
- const OwnedObject context() const;
-
- // You MUST call this _very_ early in the switching process to
- // prepare anything that may need prepared. This might perform
- // garbage collections or otherwise run arbitrary Python code.
- //
- // One specific use of it is for Python 3.11+, preventing
- // running arbitrary code at unsafe times. See
- // PythonState::may_switch_away().
- inline void may_switch_away()
- {
- this->python_state.may_switch_away();
- }
-
- inline void context(refs::BorrowedObject new_context);
-
- inline SwitchingArgs& args()
- {
- return this->switch_args;
- }
-
- virtual const refs::BorrowedMainGreenlet main_greenlet() const = 0;
-
- inline intptr_t stack_saved() const noexcept
- {
- return this->stack_state.stack_saved();
- }
-
- // This is used by the macro SLP_SAVE_STATE to compute the
- // difference in stack sizes. It might be nice to handle the
- // computation ourself, but the type of the result
- // varies by platform, so doing it in the macro is the
- // simplest way.
- inline const char* stack_start() const noexcept
- {
- return this->stack_state.stack_start();
- }
-
- virtual OwnedObject throw_GreenletExit_during_dealloc(const ThreadState& current_thread_state);
- virtual OwnedObject g_switch() = 0;
- /**
- * Force the greenlet to appear dead. Used when it's not
- * possible to throw an exception into a greenlet anymore.
- *
- * This losses access to the thread state and the main greenlet.
- */
- virtual void murder_in_place();
-
- /**
- * Called when somebody notices we were running in a dead
- * thread to allow cleaning up resources (because we can't
- * raise GreenletExit into it anymore).
- * This is very similar to ``murder_in_place()``, except that
- * it DOES NOT lose the main greenlet or thread state.
- */
- inline void deactivate_and_free();
-
-
- // Called when some thread wants to deallocate a greenlet
- // object.
- // The thread may or may not be the same thread the greenlet
- // was running in.
- // The thread state will be null if the thread the greenlet
- // was running in was known to have exited.
- void deallocing_greenlet_in_thread(const ThreadState* current_state);
-
- // Must be called on 3.12+ before exposing a suspended greenlet's
- // frames to user code. This rewrites the linked list of interpreter
- // frames to skip the ones that are being stored on the C stack (which
- // can't be safely accessed while the greenlet is suspended because
- // that stack space might be hosting a different greenlet), and
- // sets PythonState::frames_were_exposed so we remember to restore
- // the original list before resuming the greenlet. The C-stack frames
- // are a low-level interpreter implementation detail; while they're
- // important to the bytecode eval loop, they're superfluous for
- // introspection purposes.
- void expose_frames();
-
-
- // TODO: Figure out how to make these non-public.
- inline void slp_restore_state() noexcept;
- inline int slp_save_state(char *const stackref) noexcept;
-
- inline bool is_currently_running_in_some_thread() const;
- virtual bool belongs_to_thread(const ThreadState* state) const;
-
- inline bool started() const
- {
- return this->stack_state.started();
- }
- inline bool active() const
- {
- return this->stack_state.active();
- }
- inline bool main() const
- {
- return this->stack_state.main();
- }
- virtual refs::BorrowedMainGreenlet find_main_greenlet_in_lineage() const = 0;
-
- virtual const OwnedGreenlet parent() const = 0;
- virtual void parent(const refs::BorrowedObject new_parent) = 0;
-
- inline const PythonState::OwnedFrame& top_frame()
- {
- return this->python_state.top_frame();
- }
-
- virtual const OwnedObject& run() const = 0;
- virtual void run(const refs::BorrowedObject nrun) = 0;
-
-
- virtual int tp_traverse(visitproc visit, void* arg);
- virtual int tp_clear();
-
-
- // Return the thread state that the greenlet is running in, or
- // null if the greenlet is not running or the thread is known
- // to have exited.
- virtual ThreadState* thread_state() const noexcept = 0;
-
- // Return true if the greenlet is known to have been running
- // (active) in a thread that has now exited.
- virtual bool was_running_in_dead_thread() const noexcept = 0;
-
- // Return a borrowed greenlet that is the Python object
- // this object represents.
- virtual BorrowedGreenlet self() const noexcept = 0;
-
- // For testing. If this returns true, we should pretend that
- // slp_switch() failed.
- virtual bool force_slp_switch_error() const noexcept;
-
- protected:
- inline void release_args();
-
- // The functions that must not be inlined are declared virtual.
- // We also mark them as protected, not private, so that the
- // compiler is forced to call them through a function pointer.
- // (A sufficiently smart compiler could directly call a private
- // virtual function since it can never be overridden in a
- // subclass).
-
- // Also TODO: Switch away from integer error codes and to enums,
- // or throw exceptions when possible.
- struct switchstack_result_t
- {
- int status;
- Greenlet* the_new_current_greenlet;
- OwnedGreenlet origin_greenlet;
-
- switchstack_result_t()
- : status(0),
- the_new_current_greenlet(nullptr)
- {}
-
- switchstack_result_t(int err)
- : status(err),
- the_new_current_greenlet(nullptr)
- {}
-
- switchstack_result_t(int err, Greenlet* state, OwnedGreenlet& origin)
- : status(err),
- the_new_current_greenlet(state),
- origin_greenlet(origin)
- {
- }
-
- switchstack_result_t(int err, Greenlet* state, const BorrowedGreenlet& origin)
- : status(err),
- the_new_current_greenlet(state),
- origin_greenlet(origin)
- {
- }
-
- switchstack_result_t(const switchstack_result_t& other)
- : status(other.status),
- the_new_current_greenlet(other.the_new_current_greenlet),
- origin_greenlet(other.origin_greenlet)
- {}
-
- switchstack_result_t& operator=(const switchstack_result_t& other)
- {
- this->status = other.status;
- this->the_new_current_greenlet = other.the_new_current_greenlet;
- this->origin_greenlet = other.origin_greenlet;
- return *this;
- }
- };
-
- OwnedObject on_switchstack_or_initialstub_failure(
- Greenlet* target,
- const switchstack_result_t& err,
- const bool target_was_me=false,
- const bool was_initial_stub=false);
-
- // Returns the previous greenlet we just switched away from.
- virtual OwnedGreenlet g_switchstack_success() noexcept;
-
-
- // Check the preconditions for switching to this greenlet; if they
- // aren't met, throws PyErrOccurred. Most callers will want to
- // catch this and clear the arguments
- inline void check_switch_allowed() const;
- class GreenletStartedWhileInPython : public std::runtime_error
- {
- public:
- GreenletStartedWhileInPython() : std::runtime_error("")
- {}
- };
-
- protected:
-
-
- /**
- Perform a stack switch into this greenlet.
-
- This temporarily sets the global variable
- ``switching_thread_state`` to this greenlet; as soon as the
- call to ``slp_switch`` completes, this is reset to NULL.
- Consequently, this depends on the GIL.
-
- TODO: Adopt the stackman model and pass ``slp_switch`` a
- callback function and context pointer; this eliminates the
- need for global variables altogether.
-
- Because the stack switch happens in this function, this
- function can't use its own stack (local) variables, set
- before the switch, and then accessed after the switch.
-
- Further, you con't even access ``g_thread_state_global``
- before and after the switch from the global variable.
- Because it is thread local some compilers cache it in a
- register/on the stack, notably new versions of MSVC; this
- breaks with strange crashes sometime later, because writing
- to anything in ``g_thread_state_global`` after the switch
- is actually writing to random memory. For this reason, we
- call a non-inlined function to finish the operation. (XXX:
- The ``/GT`` MSVC compiler argument probably fixes that.)
-
- It is very important that stack switch is 'atomic', i.e. no
- calls into other Python code allowed (except very few that
- are safe), because global variables are very fragile. (This
- should no longer be the case with thread-local variables.)
-
- */
- // Made virtual to facilitate subclassing UserGreenlet for testing.
- virtual switchstack_result_t g_switchstack(void);
-
-class TracingGuard
-{
-private:
- PyThreadState* tstate;
-public:
- TracingGuard()
- : tstate(PyThreadState_GET())
- {
- PyThreadState_EnterTracing(this->tstate);
- }
-
- ~TracingGuard()
- {
- PyThreadState_LeaveTracing(this->tstate);
- this->tstate = nullptr;
- }
-
- inline void CallTraceFunction(const OwnedObject& tracefunc,
- const greenlet::refs::ImmortalEventName& event,
- const BorrowedGreenlet& origin,
- const BorrowedGreenlet& target)
- {
- // TODO: This calls tracefunc(event, (origin, target)). Add a shortcut
- // function for that that's specialized to avoid the Py_BuildValue
- // string parsing, or start with just using "ON" format with PyTuple_Pack(2,
- // origin, target). That seems like what the N format is meant
- // for.
- // XXX: Why does event not automatically cast back to a PyObject?
- // It tries to call the "deleted constructor ImmortalEventName
- // const" instead.
- assert(tracefunc);
- assert(event);
- assert(origin);
- assert(target);
- greenlet::refs::NewReference retval(
- PyObject_CallFunction(
- tracefunc.borrow(),
- "O(OO)",
- event.borrow(),
- origin.borrow(),
- target.borrow()
- ));
- if (!retval) {
- throw PyErrOccurred::from_current();
- }
- }
-};
-
- static void
- g_calltrace(const OwnedObject& tracefunc,
- const greenlet::refs::ImmortalEventName& event,
- const greenlet::refs::BorrowedGreenlet& origin,
- const BorrowedGreenlet& target);
- private:
- OwnedObject g_switch_finish(const switchstack_result_t& err);
-
- };
-
- class UserGreenlet : public Greenlet
- {
- private:
- static greenlet::PythonAllocator<UserGreenlet> allocator;
- BorrowedGreenlet _self;
- OwnedMainGreenlet _main_greenlet;
- OwnedObject _run_callable;
- OwnedGreenlet _parent;
- public:
- static void* operator new(size_t UNUSED(count));
- static void operator delete(void* ptr);
-
- UserGreenlet(PyGreenlet* p, BorrowedGreenlet the_parent);
- virtual ~UserGreenlet();
-
- virtual refs::BorrowedMainGreenlet find_main_greenlet_in_lineage() const;
- virtual bool was_running_in_dead_thread() const noexcept;
- virtual ThreadState* thread_state() const noexcept;
- virtual OwnedObject g_switch();
- virtual const OwnedObject& run() const
- {
- if (this->started() || !this->_run_callable) {
- throw AttributeError("run");
- }
- return this->_run_callable;
- }
- virtual void run(const refs::BorrowedObject nrun);
-
- virtual const OwnedGreenlet parent() const;
- virtual void parent(const refs::BorrowedObject new_parent);
-
- virtual const refs::BorrowedMainGreenlet main_greenlet() const;
-
- virtual BorrowedGreenlet self() const noexcept;
- virtual void murder_in_place();
- virtual bool belongs_to_thread(const ThreadState* state) const;
- virtual int tp_traverse(visitproc visit, void* arg);
- virtual int tp_clear();
- class ParentIsCurrentGuard
- {
- private:
- OwnedGreenlet oldparent;
- UserGreenlet* greenlet;
- G_NO_COPIES_OF_CLS(ParentIsCurrentGuard);
- public:
- ParentIsCurrentGuard(UserGreenlet* p, const ThreadState& thread_state);
- ~ParentIsCurrentGuard();
- };
- virtual OwnedObject throw_GreenletExit_during_dealloc(const ThreadState& current_thread_state);
- protected:
- virtual switchstack_result_t g_initialstub(void* mark);
- private:
- // This function isn't meant to return.
- // This accepts raw pointers and the ownership of them at the
- // same time. The caller should use ``inner_bootstrap(origin.relinquish_ownership())``.
- void inner_bootstrap(PyGreenlet* origin_greenlet, PyObject* run);
- };
-
- class BrokenGreenlet : public UserGreenlet
- {
- private:
- static greenlet::PythonAllocator<BrokenGreenlet> allocator;
- public:
- bool _force_switch_error = false;
- bool _force_slp_switch_error = false;
-
- static void* operator new(size_t UNUSED(count));
- static void operator delete(void* ptr);
- BrokenGreenlet(PyGreenlet* p, BorrowedGreenlet the_parent)
- : UserGreenlet(p, the_parent)
- {}
- virtual ~BrokenGreenlet()
- {}
-
- virtual switchstack_result_t g_switchstack(void);
- virtual bool force_slp_switch_error() const noexcept;
-
- };
-
- class MainGreenlet : public Greenlet
- {
- private:
- static greenlet::PythonAllocator<MainGreenlet> allocator;
- refs::BorrowedMainGreenlet _self;
- ThreadState* _thread_state;
- G_NO_COPIES_OF_CLS(MainGreenlet);
- public:
- static void* operator new(size_t UNUSED(count));
- static void operator delete(void* ptr);
-
- MainGreenlet(refs::BorrowedMainGreenlet::PyType*, ThreadState*);
- virtual ~MainGreenlet();
-
-
- virtual const OwnedObject& run() const;
- virtual void run(const refs::BorrowedObject nrun);
-
- virtual const OwnedGreenlet parent() const;
- virtual void parent(const refs::BorrowedObject new_parent);
-
- virtual const refs::BorrowedMainGreenlet main_greenlet() const;
-
- virtual refs::BorrowedMainGreenlet find_main_greenlet_in_lineage() const;
- virtual bool was_running_in_dead_thread() const noexcept;
- virtual ThreadState* thread_state() const noexcept;
- void thread_state(ThreadState*) noexcept;
- virtual OwnedObject g_switch();
- virtual BorrowedGreenlet self() const noexcept;
- virtual int tp_traverse(visitproc visit, void* arg);
- };
-
- // Instantiate one on the stack to save the GC state,
- // and then disable GC. When it goes out of scope, GC will be
- // restored to its original state. Sadly, these APIs are only
- // available on 3.10+; luckily, we only need them on 3.11+.
-#if GREENLET_PY310
- class GCDisabledGuard
- {
- private:
- int was_enabled = 0;
- public:
- GCDisabledGuard()
- : was_enabled(PyGC_IsEnabled())
- {
- PyGC_Disable();
- }
-
- ~GCDisabledGuard()
- {
- if (this->was_enabled) {
- PyGC_Enable();
- }
- }
- };
-#endif
-
- OwnedObject& operator<<=(OwnedObject& lhs, greenlet::SwitchingArgs& rhs) noexcept;
-
- //TODO: Greenlet::g_switch() should call this automatically on its
- //return value. As it is, the module code is calling it.
- static inline OwnedObject
- single_result(const OwnedObject& results)
- {
- if (results
- && PyTuple_Check(results.borrow())
- && PyTuple_GET_SIZE(results.borrow()) == 1) {
- PyObject* result = PyTuple_GET_ITEM(results.borrow(), 0);
- assert(result);
- return OwnedObject::owning(result);
- }
- return results;
- }
-
-
- static OwnedObject
- g_handle_exit(const OwnedObject& greenlet_result);
-
-
- template<typename T>
- void operator<<(const PyThreadState *const lhs, T& rhs)
- {
- rhs.operator<<(lhs);
- }
-
-} // namespace greenlet ;
-
-#endif
diff --git a/venv/lib/python3.11/site-packages/greenlet/greenlet_internal.hpp b/venv/lib/python3.11/site-packages/greenlet/greenlet_internal.hpp
deleted file mode 100644
index c8e3849..0000000
--- a/venv/lib/python3.11/site-packages/greenlet/greenlet_internal.hpp
+++ /dev/null
@@ -1,106 +0,0 @@
-/* -*- indent-tabs-mode: nil; tab-width: 4; -*- */
-#ifndef GREENLET_INTERNAL_H
-#define GREENLET_INTERNAL_H
-#ifdef __clang__
-# pragma clang diagnostic push
-# pragma clang diagnostic ignored "-Wunused-function"
-# pragma clang diagnostic ignored "-Wmissing-field-initializers"
-# pragma clang diagnostic ignored "-Wunused-variable"
-#endif
-
-/**
- * Implementation helpers.
- *
- * C++ templates and inline functions should go here.
- */
-#define PY_SSIZE_T_CLEAN
-#include "greenlet_compiler_compat.hpp"
-#include "greenlet_cpython_compat.hpp"
-#include "greenlet_exceptions.hpp"
-#include "greenlet_greenlet.hpp"
-#include "greenlet_allocator.hpp"
-
-#include <vector>
-#include <string>
-
-#define GREENLET_MODULE
-struct _greenlet;
-typedef struct _greenlet PyGreenlet;
-namespace greenlet {
-
- class ThreadState;
-
-};
-
-
-#define implementation_ptr_t greenlet::Greenlet*
-
-
-#include "greenlet.h"
-
-G_FP_TMPL_STATIC inline void
-greenlet::refs::MainGreenletExactChecker(void *p)
-{
- if (!p) {
- return;
- }
- // We control the class of the main greenlet exactly.
- if (Py_TYPE(p) != &PyGreenlet_Type) {
- std::string err("MainGreenlet: Expected exactly a greenlet, not a ");
- err += Py_TYPE(p)->tp_name;
- throw greenlet::TypeError(err);
- }
-
- // Greenlets from dead threads no longer respond to main() with a
- // true value; so in that case we need to perform an additional
- // check.
- Greenlet* g = ((PyGreenlet*)p)->pimpl;
- if (g->main()) {
- return;
- }
- if (!dynamic_cast<MainGreenlet*>(g)) {
- std::string err("MainGreenlet: Expected exactly a main greenlet, not a ");
- err += Py_TYPE(p)->tp_name;
- throw greenlet::TypeError(err);
- }
-}
-
-
-
-template <typename T, greenlet::refs::TypeChecker TC>
-inline greenlet::Greenlet* greenlet::refs::_OwnedGreenlet<T, TC>::operator->() const noexcept
-{
- return reinterpret_cast<PyGreenlet*>(this->p)->pimpl;
-}
-
-template <typename T, greenlet::refs::TypeChecker TC>
-inline greenlet::Greenlet* greenlet::refs::_BorrowedGreenlet<T, TC>::operator->() const noexcept
-{
- return reinterpret_cast<PyGreenlet*>(this->p)->pimpl;
-}
-
-#include <memory>
-#include <stdexcept>
-
-
-extern PyTypeObject PyGreenlet_Type;
-
-
-
-/**
- * Forward declarations needed in multiple files.
- */
-static PyGreenlet* green_create_main(greenlet::ThreadState*);
-static PyObject* green_switch(PyGreenlet* self, PyObject* args, PyObject* kwargs);
-static int green_is_gc(BorrowedGreenlet self);
-
-#ifdef __clang__
-# pragma clang diagnostic pop
-#endif
-
-
-#endif
-
-// Local Variables:
-// flycheck-clang-include-path: ("../../include" "/opt/local/Library/Frameworks/Python.framework/Versions/3.10/include/python3.10")
-// End:
diff --git a/venv/lib/python3.11/site-packages/greenlet/greenlet_refs.hpp b/venv/lib/python3.11/site-packages/greenlet/greenlet_refs.hpp
deleted file mode 100644
index 72ee68b..0000000
--- a/venv/lib/python3.11/site-packages/greenlet/greenlet_refs.hpp
+++ /dev/null
@@ -1,1100 +0,0 @@
-#ifndef GREENLET_REFS_HPP
-#define GREENLET_REFS_HPP
-
-#define PY_SSIZE_T_CLEAN
-#include <Python.h>
-//#include "greenlet_internal.hpp"
-#include "greenlet_compiler_compat.hpp"
-#include "greenlet_cpython_compat.hpp"
-#include "greenlet_exceptions.hpp"
-
-struct _greenlet;
-struct _PyMainGreenlet;
-
-typedef struct _greenlet PyGreenlet;
-extern PyTypeObject PyGreenlet_Type;
-
-
-#ifdef GREENLET_USE_STDIO
-#include <iostream>
-using std::cerr;
-using std::endl;
-#endif
-
-namespace greenlet
-{
- class Greenlet;
-
- namespace refs
- {
- // Type checkers throw a TypeError if the argument is not
- // null, and isn't of the required Python type.
- // (We can't use most of the defined type checkers
- // like PyList_Check, etc, directly, because they are
- // implemented as macros.)
- typedef void (*TypeChecker)(void*);
-
- G_FP_TMPL_STATIC inline void
- NoOpChecker(void*)
- {
- return;
- }
-
- G_FP_TMPL_STATIC inline void
- GreenletChecker(void *p)
- {
- if (!p) {
- return;
- }
-
- PyTypeObject* typ = Py_TYPE(p);
- // fast, common path. (PyObject_TypeCheck is a macro or
- // static inline function, and it also does a
- // direct comparison of the type pointers, but its fast
- // path only handles one type)
- if (typ == &PyGreenlet_Type) {
- return;
- }
-
- if (!PyObject_TypeCheck(p, &PyGreenlet_Type)) {
- std::string err("GreenletChecker: Expected any type of greenlet, not ");
- err += Py_TYPE(p)->tp_name;
- throw TypeError(err);
- }
- }
-
- G_FP_TMPL_STATIC inline void
- MainGreenletExactChecker(void *p);
-
- template <typename T, TypeChecker>
- class PyObjectPointer;
-
- template<typename T, TypeChecker>
- class OwnedReference;
-
-
- template<typename T, TypeChecker>
- class BorrowedReference;
-
- typedef BorrowedReference<PyObject, NoOpChecker> BorrowedObject;
- typedef OwnedReference<PyObject, NoOpChecker> OwnedObject;
-
- class ImmortalObject;
- class ImmortalString;
-
- template<typename T, TypeChecker TC>
- class _OwnedGreenlet;
-
- typedef _OwnedGreenlet<PyGreenlet, GreenletChecker> OwnedGreenlet;
- typedef _OwnedGreenlet<PyGreenlet, MainGreenletExactChecker> OwnedMainGreenlet;
-
- template<typename T, TypeChecker TC>
- class _BorrowedGreenlet;
-
- typedef _BorrowedGreenlet<PyGreenlet, GreenletChecker> BorrowedGreenlet;
-
- G_FP_TMPL_STATIC inline void
- ContextExactChecker(void *p)
- {
- if (!p) {
- return;
- }
- if (!PyContext_CheckExact(p)) {
- throw TypeError(
- "greenlet context must be a contextvars.Context or None"
- );
- }
- }
-
- typedef OwnedReference<PyObject, ContextExactChecker> OwnedContext;
- }
-}
-
-namespace greenlet {
-
-
- namespace refs {
- // A set of classes to make reference counting rules in python
- // code explicit.
- //
- // Rules of use:
- // (1) Functions returning a new reference that the caller of the
- // function is expected to dispose of should return a
- // ``OwnedObject`` object. This object automatically releases its
- // reference when it goes out of scope. It works like a ``std::shared_ptr``
- // and can be copied or used as a function parameter (but don't do
- // that). Note that constructing a ``OwnedObject`` from a
- // PyObject* steals the reference.
- // (2) Parameters to functions should be either a
- // ``OwnedObject&``, or, more generally, a ``PyObjectPointer&``.
- // If the function needs to create its own new reference, it can
- // do so by copying to a local ``OwnedObject``.
- // (3) Functions returning an existing pointer that is NOT
- // incref'd, and which the caller MUST NOT decref,
- // should return a ``BorrowedObject``.
-
- //
- // For a class with a single pointer member, whose constructor
- // does nothing but copy a pointer parameter into the member, and
- // which can then be converted back to the pointer type, compilers
- // generate code that's the same as just passing the pointer.
- // That is, func(BorrowedObject x) called like ``PyObject* p =
- // ...; f(p)`` has 0 overhead. Similarly, they "unpack" to the
- // pointer type with 0 overhead.
- //
- // If there are no virtual functions, no complex inheritance (maybe?) and
- // no destructor, these can be directly used as parameters in
- // Python callbacks like tp_init: the layout is the same as a
- // single pointer. Only subclasses with trivial constructors that
- // do nothing but set the single pointer member are safe to use
- // that way.
-
-
- // This is the base class for things that can be done with a
- // PyObject pointer. It assumes nothing about memory management.
- // NOTE: Nothing is virtual, so subclasses shouldn't add new
- // storage fields or try to override these methods.
- template <typename T=PyObject, TypeChecker TC=NoOpChecker>
- class PyObjectPointer
- {
- public:
- typedef T PyType;
- protected:
- T* p;
- public:
- explicit PyObjectPointer(T* it=nullptr) : p(it)
- {
- TC(p);
- }
-
- // We don't allow automatic casting to PyObject* at this
- // level, because then we could be passed to Py_DECREF/INCREF,
- // but we want nothing to do with memory management. If you
- // know better, then you can use the get() method, like on a
- // std::shared_ptr. Except we name it borrow() to clarify that
- // if this is a reference-tracked object, the pointer you get
- // back will go away when the object does.
- // TODO: This should probably not exist here, but be moved
- // down to relevant sub-types.
-
- inline T* borrow() const noexcept
- {
- return this->p;
- }
-
- PyObject* borrow_o() const noexcept
- {
- return reinterpret_cast<PyObject*>(this->p);
- }
-
- inline T* operator->() const noexcept
- {
- return this->p;
- }
-
- bool is_None() const noexcept
- {
- return this->p == Py_None;
- }
-
- inline PyObject* acquire_or_None() const noexcept
- {
- PyObject* result = this->p ? reinterpret_cast<PyObject*>(this->p) : Py_None;
- Py_INCREF(result);
- return result;
- }
-
- explicit operator bool() const noexcept
- {
- return p != nullptr;
- }
-
- inline Py_ssize_t REFCNT() const noexcept
- {
- return p ? Py_REFCNT(p) : -42;
- }
-
- inline PyTypeObject* TYPE() const noexcept
- {
- return p ? Py_TYPE(p) : nullptr;
- }
-
- inline OwnedObject PyStr() const noexcept;
- inline const std::string as_str() const noexcept;
- inline OwnedObject PyGetAttr(const ImmortalObject& name) const noexcept;
- inline OwnedObject PyRequireAttr(const char* const name) const;
- inline OwnedObject PyRequireAttr(const ImmortalString& name) const;
- inline OwnedObject PyCall(const BorrowedObject& arg) const;
- inline OwnedObject PyCall(PyGreenlet* arg) const ;
- inline OwnedObject PyCall(PyObject* arg) const ;
- // PyObject_Call(this, args, kwargs);
- inline OwnedObject PyCall(const BorrowedObject args,
- const BorrowedObject kwargs) const;
- inline OwnedObject PyCall(const OwnedObject& args,
- const OwnedObject& kwargs) const;
-
- protected:
- void _set_raw_pointer(void* t)
- {
- TC(t);
- p = reinterpret_cast<T*>(t);
- }
- void* _get_raw_pointer() const
- {
- return p;
- }
- };
-
-#ifdef GREENLET_USE_STDIO
- template<typename T, TypeChecker TC>
- std::ostream& operator<<(std::ostream& os, const PyObjectPointer<T, TC>& s)
- {
- const std::type_info& t = typeid(s);
- os << t.name()
- << "(addr=" << s.borrow()
- << ", refcnt=" << s.REFCNT()
- << ", value=" << s.as_str()
- << ")";
-
- return os;
- }
-#endif
-
- template<typename T, TypeChecker TC>
- inline bool operator==(const PyObjectPointer<T, TC>& lhs, const void* const rhs) noexcept
- {
- return lhs.borrow_o() == rhs;
- }
-
- template<typename T, TypeChecker TC, typename X, TypeChecker XC>
- inline bool operator==(const PyObjectPointer<T, TC>& lhs, const PyObjectPointer<X, XC>& rhs) noexcept
- {
- return lhs.borrow_o() == rhs.borrow_o();
- }
-
- template<typename T, TypeChecker TC, typename X, TypeChecker XC>
- inline bool operator!=(const PyObjectPointer<T, TC>& lhs,
- const PyObjectPointer<X, XC>& rhs) noexcept
- {
- return lhs.borrow_o() != rhs.borrow_o();
- }
-
- template<typename T=PyObject, TypeChecker TC=NoOpChecker>
- class OwnedReference : public PyObjectPointer<T, TC>
- {
- private:
- friend class OwnedList;
-
- protected:
- explicit OwnedReference(T* it) : PyObjectPointer<T, TC>(it)
- {
- }
-
- public:
-
- // Constructors
-
- static OwnedReference<T, TC> consuming(PyObject* p)
- {
- return OwnedReference<T, TC>(reinterpret_cast<T*>(p));
- }
-
- static OwnedReference<T, TC> owning(T* p)
- {
- OwnedReference<T, TC> result(p);
- Py_XINCREF(result.p);
- return result;
- }
-
- OwnedReference() : PyObjectPointer<T, TC>(nullptr)
- {}
-
- explicit OwnedReference(const PyObjectPointer<>& other)
- : PyObjectPointer<T, TC>(nullptr)
- {
- T* op = other.borrow();
- TC(op);
- this->p = other.borrow();
- Py_XINCREF(this->p);
- }
-
- // It would be good to make use of the C++11 distinction
- // between move and copy operations, e.g., constructing from a
- // pointer should be a move operation.
- // In the common case of ``OwnedObject x = Py_SomeFunction()``,
- // the call to the copy constructor will be elided completely.
- OwnedReference(const OwnedReference<T, TC>& other)
- : PyObjectPointer<T, TC>(other.p)
- {
- Py_XINCREF(this->p);
- }
-
- static OwnedReference<PyObject> None()
- {
- Py_INCREF(Py_None);
- return OwnedReference<PyObject>(Py_None);
- }
-
- // We can assign from exactly our type without any extra checking
- OwnedReference<T, TC>& operator=(const OwnedReference<T, TC>& other)
- {
- Py_XINCREF(other.p);
- const T* tmp = this->p;
- this->p = other.p;
- Py_XDECREF(tmp);
- return *this;
- }
-
- OwnedReference<T, TC>& operator=(const BorrowedReference<T, TC> other)
- {
- return this->operator=(other.borrow());
- }
-
- OwnedReference<T, TC>& operator=(T* const other)
- {
- TC(other);
- Py_XINCREF(other);
- T* tmp = this->p;
- this->p = other;
- Py_XDECREF(tmp);
- return *this;
- }
-
- // We can assign from an arbitrary reference type
- // if it passes our check.
- template<typename X, TypeChecker XC>
- OwnedReference<T, TC>& operator=(const OwnedReference<X, XC>& other)
- {
- X* op = other.borrow();
- TC(op);
- return this->operator=(reinterpret_cast<T*>(op));
- }
-
- inline void steal(T* other)
- {
- assert(this->p == nullptr);
- TC(other);
- this->p = other;
- }
-
- T* relinquish_ownership()
- {
- T* result = this->p;
- this->p = nullptr;
- return result;
- }
-
- T* acquire() const
- {
- // Return a new reference.
- // TODO: This may go away when we have reference objects
- // throughout the code.
- Py_XINCREF(this->p);
- return this->p;
- }
-
- // Nothing else declares a destructor, we're the leaf, so we
- // should be able to get away without virtual.
- ~OwnedReference()
- {
- Py_CLEAR(this->p);
- }
-
- void CLEAR()
- {
- Py_CLEAR(this->p);
- assert(this->p == nullptr);
- }
- };
-
- static inline
- void operator<<=(PyObject*& target, OwnedObject& o)
- {
- target = o.relinquish_ownership();
- }
-
- class NewReference : public OwnedObject
- {
- private:
- G_NO_COPIES_OF_CLS(NewReference);
- public:
- // Consumes the reference. Only use this
- // for API return values.
- NewReference(PyObject* it) : OwnedObject(it)
- {
- }
- };
-
- class NewDictReference : public NewReference
- {
- private:
- G_NO_COPIES_OF_CLS(NewDictReference);
- public:
- NewDictReference() : NewReference(PyDict_New())
- {
- if (!this->p) {
- throw PyErrOccurred();
- }
- }
-
- void SetItem(const char* const key, PyObject* value)
- {
- Require(PyDict_SetItemString(this->p, key, value));
- }
-
- void SetItem(const PyObjectPointer<>& key, PyObject* value)
- {
- Require(PyDict_SetItem(this->p, key.borrow_o(), value));
- }
- };
-
- template<typename T=PyGreenlet, TypeChecker TC=GreenletChecker>
- class _OwnedGreenlet: public OwnedReference<T, TC>
- {
- private:
- protected:
- _OwnedGreenlet(T* it) : OwnedReference<T, TC>(it)
- {}
-
- public:
- _OwnedGreenlet() : OwnedReference<T, TC>()
- {}
-
- _OwnedGreenlet(const _OwnedGreenlet<T, TC>& other) : OwnedReference<T, TC>(other)
- {
- }
- _OwnedGreenlet(OwnedMainGreenlet& other) :
- OwnedReference<T, TC>(reinterpret_cast<T*>(other.acquire()))
- {
- }
- _OwnedGreenlet(const BorrowedGreenlet& other);
- // Steals a reference.
- static _OwnedGreenlet<T, TC> consuming(PyGreenlet* it)
- {
- return _OwnedGreenlet<T, TC>(reinterpret_cast<T*>(it));
- }
-
- inline _OwnedGreenlet<T, TC>& operator=(const OwnedGreenlet& other)
- {
- return this->operator=(other.borrow());
- }
-
- inline _OwnedGreenlet<T, TC>& operator=(const BorrowedGreenlet& other);
-
- _OwnedGreenlet<T, TC>& operator=(const OwnedMainGreenlet& other)
- {
- PyGreenlet* owned = other.acquire();
- Py_XDECREF(this->p);
- this->p = reinterpret_cast<T*>(owned);
- return *this;
- }
-
- _OwnedGreenlet<T, TC>& operator=(T* const other)
- {
- OwnedReference<T, TC>::operator=(other);
- return *this;
- }
-
- T* relinquish_ownership()
- {
- T* result = this->p;
- this->p = nullptr;
- return result;
- }
-
- PyObject* relinquish_ownership_o()
- {
- return reinterpret_cast<PyObject*>(relinquish_ownership());
- }
-
- inline Greenlet* operator->() const noexcept;
- inline operator Greenlet*() const noexcept;
- };
-
- template <typename T=PyObject, TypeChecker TC=NoOpChecker>
- class BorrowedReference : public PyObjectPointer<T, TC>
- {
- public:
- // Allow implicit creation from PyObject* pointers as we
- // transition to using these classes. Also allow automatic
- // conversion to PyObject* for passing to C API calls and even
- // for Py_INCREF/DECREF, because we ourselves do no memory management.
- BorrowedReference(T* it) : PyObjectPointer<T, TC>(it)
- {}
-
- BorrowedReference(const PyObjectPointer<T>& ref) : PyObjectPointer<T, TC>(ref.borrow())
- {}
-
- BorrowedReference() : PyObjectPointer<T, TC>(nullptr)
- {}
-
- operator T*() const
- {
- return this->p;
- }
- };
-
- typedef BorrowedReference<PyObject> BorrowedObject;
- //typedef BorrowedReference<PyGreenlet> BorrowedGreenlet;
-
- template<typename T=PyGreenlet, TypeChecker TC=GreenletChecker>
- class _BorrowedGreenlet : public BorrowedReference<T, TC>
- {
- public:
- _BorrowedGreenlet() :
- BorrowedReference<T, TC>(nullptr)
- {}
-
- _BorrowedGreenlet(T* it) :
- BorrowedReference<T, TC>(it)
- {}
-
- _BorrowedGreenlet(const BorrowedObject& it);
-
- _BorrowedGreenlet(const OwnedGreenlet& it) :
- BorrowedReference<T, TC>(it.borrow())
- {}
-
- _BorrowedGreenlet<T, TC>& operator=(const BorrowedObject& other);
-
- // We get one of these for PyGreenlet, but one for PyObject
- // is handy as well
- operator PyObject*() const
- {
- return reinterpret_cast<PyObject*>(this->p);
- }
- inline Greenlet* operator->() const noexcept;
- inline operator Greenlet*() const noexcept;
- };
-
- typedef _BorrowedGreenlet<PyGreenlet> BorrowedGreenlet;
-
- template<typename T, TypeChecker TC>
- _OwnedGreenlet<T, TC>::_OwnedGreenlet(const BorrowedGreenlet& other)
- : OwnedReference<T, TC>(reinterpret_cast<T*>(other.borrow()))
- {
- Py_XINCREF(this->p);
- }
-
-
- class BorrowedMainGreenlet
- : public _BorrowedGreenlet<PyGreenlet, MainGreenletExactChecker>
- {
- public:
- BorrowedMainGreenlet(const OwnedMainGreenlet& it) :
- _BorrowedGreenlet<PyGreenlet, MainGreenletExactChecker>(it.borrow())
- {}
- BorrowedMainGreenlet(PyGreenlet* it=nullptr)
- : _BorrowedGreenlet<PyGreenlet, MainGreenletExactChecker>(it)
- {}
- };
-
- template<typename T, TypeChecker TC>
- _OwnedGreenlet<T, TC>& _OwnedGreenlet<T, TC>::operator=(const BorrowedGreenlet& other)
- {
- return this->operator=(other.borrow());
- }
-
-
- class ImmortalObject : public PyObjectPointer<>
- {
- private:
- G_NO_ASSIGNMENT_OF_CLS(ImmortalObject);
- public:
- explicit ImmortalObject(PyObject* it) : PyObjectPointer<>(it)
- {
- }
-
- ImmortalObject(const ImmortalObject& other)
- : PyObjectPointer<>(other.p)
- {
-
- }
-
- /**
- * Become the new owner of the object. Does not change the
- * reference count.
- */
- ImmortalObject& operator=(PyObject* it)
- {
- assert(this->p == nullptr);
- this->p = it;
- return *this;
- }
-
- static ImmortalObject consuming(PyObject* it)
- {
- return ImmortalObject(it);
- }
-
- inline operator PyObject*() const
- {
- return this->p;
- }
- };
-
- class ImmortalString : public ImmortalObject
- {
- private:
- G_NO_COPIES_OF_CLS(ImmortalString);
- const char* str;
- public:
- ImmortalString(const char* const str) :
- ImmortalObject(str ? Require(PyUnicode_InternFromString(str)) : nullptr)
- {
- this->str = str;
- }
-
- inline ImmortalString& operator=(const char* const str)
- {
- if (!this->p) {
- this->p = Require(PyUnicode_InternFromString(str));
- this->str = str;
- }
- else {
- assert(this->str == str);
- }
- return *this;
- }
-
- inline operator std::string() const
- {
- return this->str;
- }
-
- };
-
- class ImmortalEventName : public ImmortalString
- {
- private:
- G_NO_COPIES_OF_CLS(ImmortalEventName);
- public:
- ImmortalEventName(const char* const str) : ImmortalString(str)
- {}
- };
-
- class ImmortalException : public ImmortalObject
- {
- private:
- G_NO_COPIES_OF_CLS(ImmortalException);
- public:
- ImmortalException(const char* const name, PyObject* base=nullptr) :
- ImmortalObject(name
- // Python 2.7 isn't const correct
- ? Require(PyErr_NewException((char*)name, base, nullptr))
- : nullptr)
- {}
-
- inline bool PyExceptionMatches() const
- {
- return PyErr_ExceptionMatches(this->p) > 0;
- }
-
- };
-
- template<typename T, TypeChecker TC>
- inline OwnedObject PyObjectPointer<T, TC>::PyStr() const noexcept
- {
- if (!this->p) {
- return OwnedObject();
- }
- return OwnedObject::consuming(PyObject_Str(reinterpret_cast<PyObject*>(this->p)));
- }
-
- template<typename T, TypeChecker TC>
- inline const std::string PyObjectPointer<T, TC>::as_str() const noexcept
- {
- // NOTE: This is not Python exception safe.
- if (this->p) {
- // The Python APIs return a cached char* value that's only valid
- // as long as the original object stays around, and we're
- // about to (probably) toss it. Hence the copy to std::string.
- OwnedObject py_str = this->PyStr();
- if (!py_str) {
- return "(nil)";
- }
- return PyUnicode_AsUTF8(py_str.borrow());
- }
- return "(nil)";
- }
-
- template<typename T, TypeChecker TC>
- inline OwnedObject PyObjectPointer<T, TC>::PyGetAttr(const ImmortalObject& name) const noexcept
- {
- assert(this->p);
- return OwnedObject::consuming(PyObject_GetAttr(reinterpret_cast<PyObject*>(this->p), name));
- }
-
- template<typename T, TypeChecker TC>
- inline OwnedObject PyObjectPointer<T, TC>::PyRequireAttr(const char* const name) const
- {
- assert(this->p);
- return OwnedObject::consuming(Require(PyObject_GetAttrString(this->p, name), name));
- }
-
- template<typename T, TypeChecker TC>
- inline OwnedObject PyObjectPointer<T, TC>::PyRequireAttr(const ImmortalString& name) const
- {
- assert(this->p);
- return OwnedObject::consuming(Require(
- PyObject_GetAttr(
- reinterpret_cast<PyObject*>(this->p),
- name
- ),
- name
- ));
- }
-
- template<typename T, TypeChecker TC>
- inline OwnedObject PyObjectPointer<T, TC>::PyCall(const BorrowedObject& arg) const
- {
- return this->PyCall(arg.borrow());
- }
-
- template<typename T, TypeChecker TC>
- inline OwnedObject PyObjectPointer<T, TC>::PyCall(PyGreenlet* arg) const
- {
- return this->PyCall(reinterpret_cast<PyObject*>(arg));
- }
-
- template<typename T, TypeChecker TC>
- inline OwnedObject PyObjectPointer<T, TC>::PyCall(PyObject* arg) const
- {
- assert(this->p);
- return OwnedObject::consuming(PyObject_CallFunctionObjArgs(this->p, arg, NULL));
- }
-
- template<typename T, TypeChecker TC>
- inline OwnedObject PyObjectPointer<T, TC>::PyCall(const BorrowedObject args,
- const BorrowedObject kwargs) const
- {
- assert(this->p);
- return OwnedObject::consuming(PyObject_Call(this->p, args, kwargs));
- }
-
- template<typename T, TypeChecker TC>
- inline OwnedObject PyObjectPointer<T, TC>::PyCall(const OwnedObject& args,
- const OwnedObject& kwargs) const
- {
- assert(this->p);
- return OwnedObject::consuming(PyObject_Call(this->p, args.borrow(), kwargs.borrow()));
- }
-
- G_FP_TMPL_STATIC inline void
- ListChecker(void * p)
- {
- if (!p) {
- return;
- }
- if (!PyList_Check(p)) {
- throw TypeError("Expected a list");
- }
- }
-
- class OwnedList : public OwnedReference<PyObject, ListChecker>
- {
- private:
- G_NO_ASSIGNMENT_OF_CLS(OwnedList);
- public:
- // TODO: Would like to use move.
- explicit OwnedList(const OwnedObject& other)
- : OwnedReference<PyObject, ListChecker>(other)
- {
- }
-
- OwnedList& operator=(const OwnedObject& other)
- {
- if (other && PyList_Check(other.p)) {
- // Valid list. Own a new reference to it, discard the
- // reference to what we did own.
- PyObject* new_ptr = other.p;
- Py_INCREF(new_ptr);
- Py_XDECREF(this->p);
- this->p = new_ptr;
- }
- else {
- // Either the other object was NULL (an error) or it
- // wasn't a list. Either way, we're now invalidated.
- Py_XDECREF(this->p);
- this->p = nullptr;
- }
- return *this;
- }
-
- inline bool empty() const
- {
- return PyList_GET_SIZE(p) == 0;
- }
-
- inline Py_ssize_t size() const
- {
- return PyList_GET_SIZE(p);
- }
-
- inline BorrowedObject at(const Py_ssize_t index) const
- {
- return PyList_GET_ITEM(p, index);
- }
-
- inline void clear()
- {
- PyList_SetSlice(p, 0, PyList_GET_SIZE(p), NULL);
- }
- };
-
- // Use this to represent the module object used at module init
- // time.
- // This could either be a borrowed (Py2) or new (Py3) reference;
- // either way, we don't want to do any memory management
- // on it here, Python itself will handle that.
- // XXX: Actually, that's not quite right. On Python 3, if an
- // exception occurs before we return to the interpreter, this will
- // leak; but all previous versions also had that problem.
- class CreatedModule : public PyObjectPointer<>
- {
- private:
- G_NO_COPIES_OF_CLS(CreatedModule);
- public:
- CreatedModule(PyModuleDef& mod_def) : PyObjectPointer<>(
- Require(PyModule_Create(&mod_def)))
- {
- }
-
- // PyAddObject(): Add a reference to the object to the module.
- // On return, the reference count of the object is unchanged.
- //
- // The docs warn that PyModule_AddObject only steals the
- // reference on success, so if it fails after we've incref'd
- // or allocated, we're responsible for the decref.
- void PyAddObject(const char* name, const long new_bool)
- {
- OwnedObject p = OwnedObject::consuming(Require(PyBool_FromLong(new_bool)));
- this->PyAddObject(name, p);
- }
-
- void PyAddObject(const char* name, const OwnedObject& new_object)
- {
- // The caller already owns a reference they will decref
- // when their variable goes out of scope, we still need to
- // incref/decref.
- this->PyAddObject(name, new_object.borrow());
- }
-
- void PyAddObject(const char* name, const ImmortalObject& new_object)
- {
- this->PyAddObject(name, new_object.borrow());
- }
-
- void PyAddObject(const char* name, PyTypeObject& type)
- {
- this->PyAddObject(name, reinterpret_cast<PyObject*>(&type));
- }
-
- void PyAddObject(const char* name, PyObject* new_object)
- {
- Py_INCREF(new_object);
- try {
- Require(PyModule_AddObject(this->p, name, new_object));
- }
- catch (const PyErrOccurred&) {
- Py_DECREF(p);
- throw;
- }
- }
- };
-
- class PyErrFetchParam : public PyObjectPointer<>
- {
- // Not an owned object, because we can't be initialized with
- // one, and we only sometimes acquire ownership.
- private:
- G_NO_COPIES_OF_CLS(PyErrFetchParam);
- public:
- // To allow declaring these and passing them to
- // PyErr_Fetch we implement the empty constructor,
- // and the address operator.
- PyErrFetchParam() : PyObjectPointer<>(nullptr)
- {
- }
-
- PyObject** operator&()
- {
- return &this->p;
- }
-
- // This allows us to pass one directly without the &,
- // BUT it has higher precedence than the bool operator
- // if it's not explicit.
- operator PyObject**()
- {
- return &this->p;
- }
-
- // We don't want to be able to pass these to Py_DECREF and
- // such so we don't have the implicit PyObject* conversion.
-
- inline PyObject* relinquish_ownership()
- {
- PyObject* result = this->p;
- this->p = nullptr;
- return result;
- }
-
- ~PyErrFetchParam()
- {
- Py_XDECREF(p);
- }
- };
-
- class OwnedErrPiece : public OwnedObject
- {
- private:
-
- public:
- // Unlike OwnedObject, this increments the refcount.
- OwnedErrPiece(PyObject* p=nullptr) : OwnedObject(p)
- {
- this->acquire();
- }
-
- PyObject** operator&()
- {
- return &this->p;
- }
-
- inline operator PyObject*() const
- {
- return this->p;
- }
-
- operator PyTypeObject*() const
- {
- return reinterpret_cast<PyTypeObject*>(this->p);
- }
- };
-
- class PyErrPieces
- {
- private:
- OwnedErrPiece type;
- OwnedErrPiece instance;
- OwnedErrPiece traceback;
- bool restored;
- public:
- // Takes new references; if we're destroyed before
- // restoring the error, we drop the references.
- PyErrPieces(PyObject* t, PyObject* v, PyObject* tb) :
- type(t),
- instance(v),
- traceback(tb),
- restored(0)
- {
- this->normalize();
- }
-
- PyErrPieces() :
- restored(0)
- {
- // PyErr_Fetch transfers ownership to us, so
- // we don't actually need to INCREF; but we *do*
- // need to DECREF if we're not restored.
- PyErrFetchParam t, v, tb;
- PyErr_Fetch(&t, &v, &tb);
- type.steal(t.relinquish_ownership());
- instance.steal(v.relinquish_ownership());
- traceback.steal(tb.relinquish_ownership());
- }
-
- void PyErrRestore()
- {
- // can only do this once
- assert(!this->restored);
- this->restored = true;
- PyErr_Restore(
- this->type.relinquish_ownership(),
- this->instance.relinquish_ownership(),
- this->traceback.relinquish_ownership());
- assert(!this->type && !this->instance && !this->traceback);
- }
-
- private:
- void normalize()
- {
- // First, check the traceback argument, replacing None,
- // with NULL
- if (traceback.is_None()) {
- traceback = nullptr;
- }
-
- if (traceback && !PyTraceBack_Check(traceback.borrow())) {
- throw PyErrOccurred(PyExc_TypeError,
- "throw() third argument must be a traceback object");
- }
-
- if (PyExceptionClass_Check(type)) {
- // If we just had a type, we'll now have a type and
- // instance.
- // The type's refcount will have gone up by one
- // because of the instance and the instance will have
- // a refcount of one. Either way, we owned, and still
- // do own, exactly one reference.
- PyErr_NormalizeException(&type, &instance, &traceback);
-
- }
- else if (PyExceptionInstance_Check(type)) {
- /* Raising an instance --- usually that means an
- object that is a subclass of BaseException, but on
- Python 2, that can also mean an arbitrary old-style
- object. The value should be a dummy. */
- if (instance && !instance.is_None()) {
- throw PyErrOccurred(
- PyExc_TypeError,
- "instance exception may not have a separate value");
- }
- /* Normalize to raise <class>, <instance> */
- this->instance = this->type;
- this->type = PyExceptionInstance_Class(instance.borrow());
-
- /*
- It would be tempting to do this:
-
- Py_ssize_t type_count = Py_REFCNT(Py_TYPE(instance.borrow()));
- this->type = PyExceptionInstance_Class(instance.borrow());
- assert(this->type.REFCNT() == type_count + 1);
-
- But that doesn't work on Python 2 in the case of
- old-style instances: The result of Py_TYPE is going to
- be the global shared <type instance> that all
- old-style classes have, while the return of Instance_Class()
- will be the Python-level class object. The two are unrelated.
- */
- }
- else {
- /* Not something you can raise. throw() fails. */
- PyErr_Format(PyExc_TypeError,
- "exceptions must be classes, or instances, not %s",
- Py_TYPE(type.borrow())->tp_name);
- throw PyErrOccurred();
- }
- }
- };
-
- // PyArg_Parse's O argument returns a borrowed reference.
- class PyArgParseParam : public BorrowedObject
- {
- private:
- G_NO_COPIES_OF_CLS(PyArgParseParam);
- public:
- explicit PyArgParseParam(PyObject* p=nullptr) : BorrowedObject(p)
- {
- }
-
- inline PyObject** operator&()
- {
- return &this->p;
- }
- };
-
-};};
-
-#endif
diff --git a/venv/lib/python3.11/site-packages/greenlet/greenlet_slp_switch.hpp b/venv/lib/python3.11/site-packages/greenlet/greenlet_slp_switch.hpp
deleted file mode 100644
index bd4b7ae..0000000
--- a/venv/lib/python3.11/site-packages/greenlet/greenlet_slp_switch.hpp
+++ /dev/null
@@ -1,99 +0,0 @@
-#ifndef GREENLET_SLP_SWITCH_HPP
-#define GREENLET_SLP_SWITCH_HPP
-
-#include "greenlet_compiler_compat.hpp"
-#include "greenlet_refs.hpp"
-
-/*
- * the following macros are spliced into the OS/compiler
- * specific code, in order to simplify maintenance.
- */
-// We can save about 10% of the time it takes to switch greenlets if
-// we thread the thread state through the slp_save_state() and the
-// following slp_restore_state() calls from
-// slp_switch()->g_switchstack() (which already needs to access it).
-//
-// However:
-//
-// that requires changing the prototypes and implementations of the
-// switching functions. If we just change the prototype of
-// slp_switch() to accept the argument and update the macros, without
-// changing the implementation of slp_switch(), we get crashes on
-// 64-bit Linux and 32-bit x86 (for reasons that aren't 100% clear);
-// on the other hand, 64-bit macOS seems to be fine. Also, 64-bit
-// windows is an issue because slp_switch is written fully in assembly
-// and currently ignores its argument so some code would have to be
-// adjusted there to pass the argument on to the
-// ``slp_save_state_asm()`` function (but interestingly, because of
-// the calling convention, the extra argument is just ignored and
-// things function fine, albeit slower, if we just modify
-// ``slp_save_state_asm`()` to fetch the pointer to pass to the
-// macro.)
-//
-// Our compromise is to use a *glabal*, untracked, weak, pointer
-// to the necessary thread state during the process of switching only.
-// This is safe because we're protected by the GIL, and if we're
-// running this code, the thread isn't exiting. This also nets us a
-// 10-12% speed improvement.
-
-static greenlet::Greenlet* volatile switching_thread_state = nullptr;
-
-
-extern "C" {
-static int GREENLET_NOINLINE(slp_save_state_trampoline)(char* stackref);
-static void GREENLET_NOINLINE(slp_restore_state_trampoline)();
-}
-
-
-#define SLP_SAVE_STATE(stackref, stsizediff) \
-do { \
- assert(switching_thread_state); \
- stackref += STACK_MAGIC; \
- if (slp_save_state_trampoline((char*)stackref)) \
- return -1; \
- if (!switching_thread_state->active()) \
- return 1; \
- stsizediff = switching_thread_state->stack_start() - (char*)stackref; \
-} while (0)
-
-#define SLP_RESTORE_STATE() slp_restore_state_trampoline()
-
-#define SLP_EVAL
-extern "C" {
-#define slp_switch GREENLET_NOINLINE(slp_switch)
-#include "slp_platformselect.h"
-}
-#undef slp_switch
-
-#ifndef STACK_MAGIC
-# error \
- "greenlet needs to be ported to this platform, or taught how to detect your compiler properly."
-#endif /* !STACK_MAGIC */
-
-
-
-#ifdef EXTERNAL_ASM
-/* CCP addition: Make these functions, to be called from assembler.
- * The token include file for the given platform should enable the
- * EXTERNAL_ASM define so that this is included.
- */
-extern "C" {
-intptr_t
-slp_save_state_asm(intptr_t* ref)
-{
- intptr_t diff;
- SLP_SAVE_STATE(ref, diff);
- return diff;
-}
-
-void
-slp_restore_state_asm(void)
-{
- SLP_RESTORE_STATE();
-}
-
-extern int slp_switch(void);
-};
-#endif
-
-#endif
diff --git a/venv/lib/python3.11/site-packages/greenlet/greenlet_thread_state.hpp b/venv/lib/python3.11/site-packages/greenlet/greenlet_thread_state.hpp
deleted file mode 100644
index 045371f..0000000
--- a/venv/lib/python3.11/site-packages/greenlet/greenlet_thread_state.hpp
+++ /dev/null
@@ -1,543 +0,0 @@
-#ifndef GREENLET_THREAD_STATE_HPP
-#define GREENLET_THREAD_STATE_HPP
-
-#include <ctime>
-#include <stdexcept>
-
-#include "greenlet_internal.hpp"
-#include "greenlet_refs.hpp"
-#include "greenlet_thread_support.hpp"
-
-using greenlet::refs::BorrowedObject;
-using greenlet::refs::BorrowedGreenlet;
-using greenlet::refs::BorrowedMainGreenlet;
-using greenlet::refs::OwnedMainGreenlet;
-using greenlet::refs::OwnedObject;
-using greenlet::refs::OwnedGreenlet;
-using greenlet::refs::OwnedList;
-using greenlet::refs::PyErrFetchParam;
-using greenlet::refs::PyArgParseParam;
-using greenlet::refs::ImmortalString;
-using greenlet::refs::CreatedModule;
-using greenlet::refs::PyErrPieces;
-using greenlet::refs::NewReference;
-
-namespace greenlet {
-/**
- * Thread-local state of greenlets.
- *
- * Each native thread will get exactly one of these objects,
- * automatically accessed through the best available thread-local
- * mechanism the compiler supports (``thread_local`` for C++11
- * compilers or ``__thread``/``declspec(thread)`` for older GCC/clang
- * or MSVC, respectively.)
- *
- * Previously, we kept thread-local state mostly in a bunch of
- * ``static volatile`` variables in the main greenlet file.. This had
- * the problem of requiring extra checks, loops, and great care
- * accessing these variables if we potentially invoked any Python code
- * that could release the GIL, because the state could change out from
- * under us. Making the variables thread-local solves this problem.
- *
- * When we detected that a greenlet API accessing the current greenlet
- * was invoked from a different thread than the greenlet belonged to,
- * we stored a reference to the greenlet in the Python thread
- * dictionary for the thread the greenlet belonged to. This could lead
- * to memory leaks if the thread then exited (because of a reference
- * cycle, as greenlets referred to the thread dictionary, and deleting
- * non-current greenlets leaked their frame plus perhaps arguments on
- * the C stack). If a thread exited while still having running
- * greenlet objects (perhaps that had just switched back to the main
- * greenlet), and did not invoke one of the greenlet APIs *in that
- * thread, immediately before it exited, without some other thread
- * then being invoked*, such a leak was guaranteed.
- *
- * This can be partly solved by using compiler thread-local variables
- * instead of the Python thread dictionary, thus avoiding a cycle.
- *
- * To fully solve this problem, we need a reliable way to know that a
- * thread is done and we should clean up the main greenlet. On POSIX,
- * we can use the destructor function of ``pthread_key_create``, but
- * there's nothing similar on Windows; a C++11 thread local object
- * reliably invokes its destructor when the thread it belongs to exits
- * (non-C++11 compilers offer ``__thread`` or ``declspec(thread)`` to
- * create thread-local variables, but they can't hold C++ objects that
- * invoke destructors; the C++11 version is the most portable solution
- * I found). When the thread exits, we can drop references and
- * otherwise manipulate greenlets and frames that we know can no
- * longer be switched to. For compilers that don't support C++11
- * thread locals, we have a solution that uses the python thread
- * dictionary, though it may not collect everything as promptly as
- * other compilers do, if some other library is using the thread
- * dictionary and has a cycle or extra reference.
- *
- * There are two small wrinkles. The first is that when the thread
- * exits, it is too late to actually invoke Python APIs: the Python
- * thread state is gone, and the GIL is released. To solve *this*
- * problem, our destructor uses ``Py_AddPendingCall`` to transfer the
- * destruction work to the main thread. (This is not an issue for the
- * dictionary solution.)
- *
- * The second is that once the thread exits, the thread local object
- * is invalid and we can't even access a pointer to it, so we can't
- * pass it to ``Py_AddPendingCall``. This is handled by actually using
- * a second object that's thread local (ThreadStateCreator) and having
- * it dynamically allocate this object so it can live until the
- * pending call runs.
- */
-
-
-
-class ThreadState {
-private:
- // As of commit 08ad1dd7012b101db953f492e0021fb08634afad
- // this class needed 56 bytes in o Py_DEBUG build
- // on 64-bit macOS 11.
- // Adding the vector takes us up to 80 bytes ()
-
- /* Strong reference to the main greenlet */
- OwnedMainGreenlet main_greenlet;
-
- /* Strong reference to the current greenlet. */
- OwnedGreenlet current_greenlet;
-
- /* Strong reference to the trace function, if any. */
- OwnedObject tracefunc;
-
- typedef std::vector<PyGreenlet*, PythonAllocator<PyGreenlet*> > deleteme_t;
- /* A vector of raw PyGreenlet pointers representing things that need
- deleted when this thread is running. The vector owns the
- references, but you need to manually INCREF/DECREF as you use
- them. We don't use a vector<refs::OwnedGreenlet> because we
- make copy of this vector, and that would become O(n) as all the
- refcounts are incremented in the copy.
- */
- deleteme_t deleteme;
-
-#ifdef GREENLET_NEEDS_EXCEPTION_STATE_SAVED
- void* exception_state;
-#endif
-
- static std::clock_t _clocks_used_doing_gc;
- static ImmortalString get_referrers_name;
- static PythonAllocator<ThreadState> allocator;
-
- G_NO_COPIES_OF_CLS(ThreadState);
-
-public:
- static void* operator new(size_t UNUSED(count))
- {
- return ThreadState::allocator.allocate(1);
- }
-
- static void operator delete(void* ptr)
- {
- return ThreadState::allocator.deallocate(static_cast<ThreadState*>(ptr),
- 1);
- }
-
- static void init()
- {
- ThreadState::get_referrers_name = "get_referrers";
- ThreadState::_clocks_used_doing_gc = 0;
- }
-
- ThreadState()
- : main_greenlet(OwnedMainGreenlet::consuming(green_create_main(this))),
- current_greenlet(main_greenlet)
- {
- if (!this->main_greenlet) {
- // We failed to create the main greenlet. That's bad.
- throw PyFatalError("Failed to create main greenlet");
- }
- // The main greenlet starts with 1 refs: The returned one. We
- // then copied it to the current greenlet.
- assert(this->main_greenlet.REFCNT() == 2);
-
-#ifdef GREENLET_NEEDS_EXCEPTION_STATE_SAVED
- this->exception_state = slp_get_exception_state();
-#endif
- }
-
- inline void restore_exception_state()
- {
-#ifdef GREENLET_NEEDS_EXCEPTION_STATE_SAVED
- // It's probably important this be inlined and only call C
- // functions to avoid adding an SEH frame.
- slp_set_exception_state(this->exception_state);
-#endif
- }
-
- inline bool has_main_greenlet()
- {
- return !!this->main_greenlet;
- }
-
- // Called from the ThreadStateCreator when we're in non-standard
- // threading mode. In that case, there is an object in the Python
- // thread state dictionary that points to us. The main greenlet
- // also traverses into us, in which case it's crucial not to
- // traverse back into the main greenlet.
- int tp_traverse(visitproc visit, void* arg, bool traverse_main=true)
- {
- if (traverse_main) {
- Py_VISIT(main_greenlet.borrow_o());
- }
- if (traverse_main || current_greenlet != main_greenlet) {
- Py_VISIT(current_greenlet.borrow_o());
- }
- Py_VISIT(tracefunc.borrow());
- return 0;
- }
-
- inline BorrowedMainGreenlet borrow_main_greenlet() const
- {
- assert(this->main_greenlet);
- assert(this->main_greenlet.REFCNT() >= 2);
- return this->main_greenlet;
- };
-
- inline OwnedMainGreenlet get_main_greenlet()
- {
- return this->main_greenlet;
- }
-
- /**
- * In addition to returning a new reference to the currunt
- * greenlet, this performs any maintenance needed.
- */
- inline OwnedGreenlet get_current()
- {
- /* green_dealloc() cannot delete greenlets from other threads, so
- it stores them in the thread dict; delete them now. */
- this->clear_deleteme_list();
- //assert(this->current_greenlet->main_greenlet == this->main_greenlet);
- //assert(this->main_greenlet->main_greenlet == this->main_greenlet);
- return this->current_greenlet;
- }
-
- /**
- * As for non-const get_current();
- */
- inline BorrowedGreenlet borrow_current()
- {
- this->clear_deleteme_list();
- return this->current_greenlet;
- }
-
- /**
- * Does no maintenance.
- */
- inline OwnedGreenlet get_current() const
- {
- return this->current_greenlet;
- }
-
- template<typename T, refs::TypeChecker TC>
- inline bool is_current(const refs::PyObjectPointer<T, TC>& obj) const
- {
- return this->current_greenlet.borrow_o() == obj.borrow_o();
- }
-
- inline void set_current(const OwnedGreenlet& target)
- {
- this->current_greenlet = target;
- }
-
-private:
- /**
- * Deref and remove the greenlets from the deleteme list. Must be
- * holding the GIL.
- *
- * If *murder* is true, then we must be called from a different
- * thread than the one that these greenlets were running in.
- * In that case, if the greenlet was actually running, we destroy
- * the frame reference and otherwise make it appear dead before
- * proceeding; otherwise, we would try (and fail) to raise an
- * exception in it and wind up right back in this list.
- */
- inline void clear_deleteme_list(const bool murder=false)
- {
- if (!this->deleteme.empty()) {
- // It's possible we could add items to this list while
- // running Python code if there's a thread switch, so we
- // need to defensively copy it before that can happen.
- deleteme_t copy = this->deleteme;
- this->deleteme.clear(); // in case things come back on the list
- for(deleteme_t::iterator it = copy.begin(), end = copy.end();
- it != end;
- ++it ) {
- PyGreenlet* to_del = *it;
- if (murder) {
- // Force each greenlet to appear dead; we can't raise an
- // exception into it anymore anyway.
- to_del->pimpl->murder_in_place();
- }
-
- // The only reference to these greenlets should be in
- // this list, decreffing them should let them be
- // deleted again, triggering calls to green_dealloc()
- // in the correct thread (if we're not murdering).
- // This may run arbitrary Python code and switch
- // threads or greenlets!
- Py_DECREF(to_del);
- if (PyErr_Occurred()) {
- PyErr_WriteUnraisable(nullptr);
- PyErr_Clear();
- }
- }
- }
- }
-
-public:
-
- /**
- * Returns a new reference, or a false object.
- */
- inline OwnedObject get_tracefunc() const
- {
- return tracefunc;
- };
-
-
- inline void set_tracefunc(BorrowedObject tracefunc)
- {
- assert(tracefunc);
- if (tracefunc == BorrowedObject(Py_None)) {
- this->tracefunc.CLEAR();
- }
- else {
- this->tracefunc = tracefunc;
- }
- }
-
- /**
- * Given a reference to a greenlet that some other thread
- * attempted to delete (has a refcount of 0) store it for later
- * deletion when the thread this state belongs to is current.
- */
- inline void delete_when_thread_running(PyGreenlet* to_del)
- {
- Py_INCREF(to_del);
- this->deleteme.push_back(to_del);
- }
-
- /**
- * Set to std::clock_t(-1) to disable.
- */
- inline static std::clock_t& clocks_used_doing_gc()
- {
- return ThreadState::_clocks_used_doing_gc;
- }
-
- ~ThreadState()
- {
- if (!PyInterpreterState_Head()) {
- // We shouldn't get here (our callers protect us)
- // but if we do, all we can do is bail early.
- return;
- }
-
- // We should not have an "origin" greenlet; that only exists
- // for the temporary time during a switch, which should not
- // be in progress as the thread dies.
- //assert(!this->switching_state.origin);
-
- this->tracefunc.CLEAR();
-
- // Forcibly GC as much as we can.
- this->clear_deleteme_list(true);
-
- // The pending call did this.
- assert(this->main_greenlet->thread_state() == nullptr);
-
- // If the main greenlet is the current greenlet,
- // then we "fell off the end" and the thread died.
- // It's possible that there is some other greenlet that
- // switched to us, leaving a reference to the main greenlet
- // on the stack, somewhere uncollectible. Try to detect that.
- if (this->current_greenlet == this->main_greenlet && this->current_greenlet) {
- assert(this->current_greenlet->is_currently_running_in_some_thread());
- // Drop one reference we hold.
- this->current_greenlet.CLEAR();
- assert(!this->current_greenlet);
- // Only our reference to the main greenlet should be left,
- // But hold onto the pointer in case we need to do extra cleanup.
- PyGreenlet* old_main_greenlet = this->main_greenlet.borrow();
- Py_ssize_t cnt = this->main_greenlet.REFCNT();
- this->main_greenlet.CLEAR();
- if (ThreadState::_clocks_used_doing_gc != std::clock_t(-1)
- && cnt == 2 && Py_REFCNT(old_main_greenlet) == 1) {
- // Highly likely that the reference is somewhere on
- // the stack, not reachable by GC. Verify.
- // XXX: This is O(n) in the total number of objects.
- // TODO: Add a way to disable this at runtime, and
- // another way to report on it.
- std::clock_t begin = std::clock();
- NewReference gc(PyImport_ImportModule("gc"));
- if (gc) {
- OwnedObject get_referrers = gc.PyRequireAttr(ThreadState::get_referrers_name);
- OwnedList refs(get_referrers.PyCall(old_main_greenlet));
- if (refs && refs.empty()) {
- assert(refs.REFCNT() == 1);
- // We found nothing! So we left a dangling
- // reference: Probably the last thing some
- // other greenlet did was call
- // 'getcurrent().parent.switch()' to switch
- // back to us. Clean it up. This will be the
- // case on CPython 3.7 and newer, as they use
- // an internal calling conversion that avoids
- // creating method objects and storing them on
- // the stack.
- Py_DECREF(old_main_greenlet);
- }
- else if (refs
- && refs.size() == 1
- && PyCFunction_Check(refs.at(0))
- && Py_REFCNT(refs.at(0)) == 2) {
- assert(refs.REFCNT() == 1);
- // Ok, we found a C method that refers to the
- // main greenlet, and its only referenced
- // twice, once in the list we just created,
- // once from...somewhere else. If we can't
- // find where else, then this is a leak.
- // This happens in older versions of CPython
- // that create a bound method object somewhere
- // on the stack that we'll never get back to.
- if (PyCFunction_GetFunction(refs.at(0).borrow()) == (PyCFunction)green_switch) {
- BorrowedObject function_w = refs.at(0);
- refs.clear(); // destroy the reference
- // from the list.
- // back to one reference. Can *it* be
- // found?
- assert(function_w.REFCNT() == 1);
- refs = get_referrers.PyCall(function_w);
- if (refs && refs.empty()) {
- // Nope, it can't be found so it won't
- // ever be GC'd. Drop it.
- Py_CLEAR(function_w);
- }
- }
- }
- std::clock_t end = std::clock();
- ThreadState::_clocks_used_doing_gc += (end - begin);
- }
- }
- }
-
- // We need to make sure this greenlet appears to be dead,
- // because otherwise deallocing it would fail to raise an
- // exception in it (the thread is dead) and put it back in our
- // deleteme list.
- if (this->current_greenlet) {
- this->current_greenlet->murder_in_place();
- this->current_greenlet.CLEAR();
- }
-
- if (this->main_greenlet) {
- // Couldn't have been the main greenlet that was running
- // when the thread exited (because we already cleared this
- // pointer if it was). This shouldn't be possible?
-
- // If the main greenlet was current when the thread died (it
- // should be, right?) then we cleared its self pointer above
- // when we cleared the current greenlet's main greenlet pointer.
- // assert(this->main_greenlet->main_greenlet == this->main_greenlet
- // || !this->main_greenlet->main_greenlet);
- // // self reference, probably gone
- // this->main_greenlet->main_greenlet.CLEAR();
-
- // This will actually go away when the ivar is destructed.
- this->main_greenlet.CLEAR();
- }
-
- if (PyErr_Occurred()) {
- PyErr_WriteUnraisable(NULL);
- PyErr_Clear();
- }
-
- }
-
-};
-
-ImmortalString ThreadState::get_referrers_name(nullptr);
-PythonAllocator<ThreadState> ThreadState::allocator;
-std::clock_t ThreadState::_clocks_used_doing_gc(0);
-
-template<typename Destructor>
-class ThreadStateCreator
-{
-private:
- // Initialized to 1, and, if still 1, created on access.
- // Set to 0 on destruction.
- ThreadState* _state;
- G_NO_COPIES_OF_CLS(ThreadStateCreator);
-public:
-
- // Only one of these, auto created per thread
- ThreadStateCreator() :
- _state((ThreadState*)1)
- {
- }
-
- ~ThreadStateCreator()
- {
- ThreadState* tmp = this->_state;
- this->_state = nullptr;
- if (tmp && tmp != (ThreadState*)1) {
- Destructor x(tmp);
- }
- }
-
- inline ThreadState& state()
- {
- // The main greenlet will own this pointer when it is created,
- // which will be right after this. The plan is to give every
- // greenlet a pointer to the main greenlet for the thread it
- // runs in; if we are doing something cross-thread, we need to
- // access the pointer from the main greenlet. Deleting the
- // thread, and hence the thread-local storage, will delete the
- // state pointer in the main greenlet.
- if (this->_state == (ThreadState*)1) {
- // XXX: Assuming allocation never fails
- this->_state = new ThreadState;
- // For non-standard threading, we need to store an object
- // in the Python thread state dictionary so that it can be
- // DECREF'd when the thread ends (ideally; the dict could
- // last longer) and clean this object up.
- }
- if (!this->_state) {
- throw std::runtime_error("Accessing state after destruction.");
- }
- return *this->_state;
- }
-
- operator ThreadState&()
- {
- return this->state();
- }
-
- operator ThreadState*()
- {
- return &this->state();
- }
-
- inline int tp_traverse(visitproc visit, void* arg)
- {
- if (this->_state) {
- return this->_state->tp_traverse(visit, arg);
- }
- return 0;
- }
-
-};
-
-
-// We can't use the PythonAllocator for this, because we push to it
-// from the thread state destructor, which doesn't have the GIL,
-// and Python's allocators can only be called with the GIL.
-typedef std::vector<ThreadState*> cleanup_queue_t;
-
-}; // namespace greenlet
-
-#endif
diff --git a/venv/lib/python3.11/site-packages/greenlet/greenlet_thread_state_dict_cleanup.hpp b/venv/lib/python3.11/site-packages/greenlet/greenlet_thread_state_dict_cleanup.hpp
deleted file mode 100644
index acf39c8..0000000
--- a/venv/lib/python3.11/site-packages/greenlet/greenlet_thread_state_dict_cleanup.hpp
+++ /dev/null
@@ -1,118 +0,0 @@
-#ifndef GREENLET_THREAD_STATE_DICT_CLEANUP_HPP
-#define GREENLET_THREAD_STATE_DICT_CLEANUP_HPP
-
-#include "greenlet_internal.hpp"
-#include "greenlet_thread_state.hpp"
-
-#ifdef __clang__
-# pragma clang diagnostic push
-# pragma clang diagnostic ignored "-Wmissing-field-initializers"
-#endif
-
-#ifndef G_THREAD_STATE_DICT_CLEANUP_TYPE
-// shut the compiler up if it looks at this file in isolation
-#define ThreadStateCreator int
-#endif
-
-// Define a Python object that goes in the Python thread state dict
-// when the greenlet thread state is created, and which owns the
-// reference to the greenlet thread local state.
-// When the thread state dict is cleaned up, so too is the thread
-// state. This works best if we make sure there are no circular
-// references to the thread state.
-typedef struct _PyGreenletCleanup {
- PyObject_HEAD
- ThreadStateCreator* thread_state_creator;
-} PyGreenletCleanup;
-
-static void
-cleanup_do_dealloc(PyGreenletCleanup* self)
-{
- ThreadStateCreator* tmp = self->thread_state_creator;
- self->thread_state_creator = nullptr;
- if (tmp) {
- delete tmp;
- }
-}
-
-static void
-cleanup_dealloc(PyGreenletCleanup* self)
-{
- PyObject_GC_UnTrack(self);
- cleanup_do_dealloc(self);
-}
-
-static int
-cleanup_clear(PyGreenletCleanup* self)
-{
- // This method is never called by our test cases.
- cleanup_do_dealloc(self);
- return 0;
-}
-
-static int
-cleanup_traverse(PyGreenletCleanup* self, visitproc visit, void* arg)
-{
- if (self->thread_state_creator) {
- return self->thread_state_creator->tp_traverse(visit, arg);
- }
- return 0;
-}
-
-static int
-cleanup_is_gc(PyGreenlet* UNUSED(self))
-{
- return 1;
-}
-
-static PyTypeObject PyGreenletCleanup_Type = {
- PyVarObject_HEAD_INIT(NULL, 0)
- "greenlet._greenlet.ThreadStateCleanup",
- sizeof(struct _PyGreenletCleanup),
- 0, /* tp_itemsize */
- /* methods */
- (destructor)cleanup_dealloc, /* tp_dealloc */
- 0, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- 0, /* tp_compare */
- 0, /* tp_repr */
- 0, /* tp_as _number*/
- 0, /* tp_as _sequence*/
- 0, /* tp_as _mapping*/
- 0, /* tp_hash */
- 0, /* tp_call */
- 0, /* tp_str */
- 0, /* tp_getattro */
- 0, /* tp_setattro */
- 0, /* tp_as_buffer*/
- G_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
- "Internal use only", /* tp_doc */
- (traverseproc)cleanup_traverse, /* tp_traverse */
- (inquiry)cleanup_clear, /* tp_clear */
- 0, /* tp_richcompare */
- // XXX: Don't our flags promise a weakref?
- 0, /* tp_weaklistoffset */
- 0, /* tp_iter */
- 0, /* tp_iternext */
- 0, /* tp_methods */
- 0, /* tp_members */
- 0, /* tp_getset */
- 0, /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- 0, /* tp_dictoffset */
- 0, /* tp_init */
- PyType_GenericAlloc, /* tp_alloc */
- PyType_GenericNew, /* tp_new */
- PyObject_GC_Del, /* tp_free */
- (inquiry)cleanup_is_gc, /* tp_is_gc */
-};
-
-#ifdef __clang__
-# pragma clang diagnostic pop
-#endif
-
-
-#endif
diff --git a/venv/lib/python3.11/site-packages/greenlet/greenlet_thread_support.hpp b/venv/lib/python3.11/site-packages/greenlet/greenlet_thread_support.hpp
deleted file mode 100644
index 3ded7d2..0000000
--- a/venv/lib/python3.11/site-packages/greenlet/greenlet_thread_support.hpp
+++ /dev/null
@@ -1,31 +0,0 @@
-#ifndef GREENLET_THREAD_SUPPORT_HPP
-#define GREENLET_THREAD_SUPPORT_HPP
-
-/**
- * Defines various utility functions to help greenlet integrate well
- * with threads. This used to be needed when we supported Python
- * 2.7 on Windows, which used a very old compiler. We wrote an
- * alternative implementation using Python APIs and POSIX or Windows
- * APIs, but that's no longer needed. So this file is a shadow of its
- * former self --- but may be needed in the future.
- */
-
-#include <stdexcept>
-#include <thread>
-#include <mutex>
-
-#include "greenlet_compiler_compat.hpp"
-
-namespace greenlet {
- typedef std::mutex Mutex;
- typedef std::lock_guard<Mutex> LockGuard;
- class LockInitError : public std::runtime_error
- {
- public:
- LockInitError(const char* what) : std::runtime_error(what)
- {};
- };
-};
-
-
-#endif /* GREENLET_THREAD_SUPPORT_HPP */
diff --git a/venv/lib/python3.11/site-packages/greenlet/platform/__init__.py b/venv/lib/python3.11/site-packages/greenlet/platform/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/venv/lib/python3.11/site-packages/greenlet/platform/__init__.py
+++ /dev/null
diff --git a/venv/lib/python3.11/site-packages/greenlet/platform/__pycache__/__init__.cpython-311.pyc b/venv/lib/python3.11/site-packages/greenlet/platform/__pycache__/__init__.cpython-311.pyc
deleted file mode 100644
index a1a372f..0000000
--- a/venv/lib/python3.11/site-packages/greenlet/platform/__pycache__/__init__.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/greenlet/platform/setup_switch_x64_masm.cmd b/venv/lib/python3.11/site-packages/greenlet/platform/setup_switch_x64_masm.cmd
deleted file mode 100644
index 0928595..0000000
--- a/venv/lib/python3.11/site-packages/greenlet/platform/setup_switch_x64_masm.cmd
+++ /dev/null
@@ -1,2 +0,0 @@
-call "C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\vcvarsall.bat" amd64
-ml64 /nologo /c /Fo switch_x64_masm.obj switch_x64_masm.asm
diff --git a/venv/lib/python3.11/site-packages/greenlet/platform/switch_aarch64_gcc.h b/venv/lib/python3.11/site-packages/greenlet/platform/switch_aarch64_gcc.h
deleted file mode 100644
index 058617c..0000000
--- a/venv/lib/python3.11/site-packages/greenlet/platform/switch_aarch64_gcc.h
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * this is the internal transfer function.
- *
- * HISTORY
- * 07-Sep-16 Add clang support using x register naming. Fredrik Fornwall
- * 13-Apr-13 Add support for strange GCC caller-save decisions
- * 08-Apr-13 File creation. Michael Matz
- *
- * NOTES
- *
- * Simply save all callee saved registers
- *
- */
-
-#define STACK_REFPLUS 1
-
-#ifdef SLP_EVAL
-#define STACK_MAGIC 0
-#define REGS_TO_SAVE "x19", "x20", "x21", "x22", "x23", "x24", "x25", "x26", \
- "x27", "x28", "x30" /* aka lr */, \
- "v8", "v9", "v10", "v11", \
- "v12", "v13", "v14", "v15"
-
-/*
- * Recall:
- asm asm-qualifiers ( AssemblerTemplate
- : OutputOperands
- [ : InputOperands
- [ : Clobbers ] ])
-
- or (if asm-qualifiers contains 'goto')
-
- asm asm-qualifiers ( AssemblerTemplate
- : OutputOperands
- : InputOperands
- : Clobbers
- : GotoLabels)
-
- and OutputOperands are
-
- [ [asmSymbolicName] ] constraint (cvariablename)
-
- When a name is given, refer to it as ``%[the name]``.
- When not given, ``%i`` where ``i`` is the zero-based index.
-
- constraints starting with ``=`` means only writing; ``+`` means
- reading and writing.
-
- This is followed by ``r`` (must be register) or ``m`` (must be memory)
- and these can be combined.
-
- The ``cvariablename`` is actually an lvalue expression.
-
- In AArch65, 31 general purpose registers. If named X0... they are
- 64-bit. If named W0... they are the bottom 32 bits of the
- corresponding 64 bit register.
-
- XZR and WZR are hardcoded to 0, and ignore writes.
-
- Arguments are in X0..X7. C++ uses X0 for ``this``. X0 holds simple return
- values (?)
-
- Whenever a W register is written, the top half of the X register is zeroed.
- */
-
-static int
-slp_switch(void)
-{
- int err;
- void *fp;
- /* Windowz uses a 32-bit long on a 64-bit platform, unlike the rest of
- the world, and in theory we can be compiled with GCC/llvm on 64-bit
- windows. So we need a fixed-width type.
- */
- int64_t *stackref, stsizediff;
- __asm__ volatile ("" : : : REGS_TO_SAVE);
- __asm__ volatile ("str x29, %0" : "=m"(fp) : : );
- __asm__ ("mov %0, sp" : "=r" (stackref));
- {
- SLP_SAVE_STATE(stackref, stsizediff);
- __asm__ volatile (
- "add sp,sp,%0\n"
- "add x29,x29,%0\n"
- :
- : "r" (stsizediff)
- );
- SLP_RESTORE_STATE();
- /* SLP_SAVE_STATE macro contains some return statements
- (of -1 and 1). It falls through only when
- the return value of slp_save_state() is zero, which
- is placed in x0.
- In that case we (slp_switch) also want to return zero
- (also in x0 of course).
- Now, some GCC versions (seen with 4.8) think it's a
- good idea to save/restore x0 around the call to
- slp_restore_state(), instead of simply zeroing it
- at the return below. But slp_restore_state
- writes random values to the stack slot used for this
- save/restore (from when it once was saved above in
- SLP_SAVE_STATE, when it was still uninitialized), so
- "restoring" that precious zero actually makes us
- return random values. There are some ways to make
- GCC not use that zero value in the normal return path
- (e.g. making err volatile, but that costs a little
- stack space), and the simplest is to call a function
- that returns an unknown value (which happens to be zero),
- so the saved/restored value is unused.
-
- Thus, this line stores a 0 into the ``err`` variable
- (which must be held in a register for this instruction,
- of course). The ``w`` qualifier causes the instruction
- to use W0 instead of X0, otherwise we get a warning
- about a value size mismatch (because err is an int,
- and aarch64 platforms are LP64: 32-bit int, 64 bit long
- and pointer).
- */
- __asm__ volatile ("mov %w0, #0" : "=r" (err));
- }
- __asm__ volatile ("ldr x29, %0" : : "m" (fp) :);
- __asm__ volatile ("" : : : REGS_TO_SAVE);
- return err;
-}
-
-#endif
diff --git a/venv/lib/python3.11/site-packages/greenlet/platform/switch_alpha_unix.h b/venv/lib/python3.11/site-packages/greenlet/platform/switch_alpha_unix.h
deleted file mode 100644
index 7e07abf..0000000
--- a/venv/lib/python3.11/site-packages/greenlet/platform/switch_alpha_unix.h
+++ /dev/null
@@ -1,30 +0,0 @@
-#define STACK_REFPLUS 1
-
-#ifdef SLP_EVAL
-#define STACK_MAGIC 0
-
-#define REGS_TO_SAVE "$9", "$10", "$11", "$12", "$13", "$14", "$15", \
- "$f2", "$f3", "$f4", "$f5", "$f6", "$f7", "$f8", "$f9"
-
-static int
-slp_switch(void)
-{
- int ret;
- long *stackref, stsizediff;
- __asm__ volatile ("" : : : REGS_TO_SAVE);
- __asm__ volatile ("mov $30, %0" : "=r" (stackref) : );
- {
- SLP_SAVE_STATE(stackref, stsizediff);
- __asm__ volatile (
- "addq $30, %0, $30\n\t"
- : /* no outputs */
- : "r" (stsizediff)
- );
- SLP_RESTORE_STATE();
- }
- __asm__ volatile ("" : : : REGS_TO_SAVE);
- __asm__ volatile ("mov $31, %0" : "=r" (ret) : );
- return ret;
-}
-
-#endif
diff --git a/venv/lib/python3.11/site-packages/greenlet/platform/switch_amd64_unix.h b/venv/lib/python3.11/site-packages/greenlet/platform/switch_amd64_unix.h
deleted file mode 100644
index d470110..0000000
--- a/venv/lib/python3.11/site-packages/greenlet/platform/switch_amd64_unix.h
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * this is the internal transfer function.
- *
- * HISTORY
- * 3-May-13 Ralf Schmitt <ralf@systemexit.de>
- * Add support for strange GCC caller-save decisions
- * (ported from switch_aarch64_gcc.h)
- * 18-Aug-11 Alexey Borzenkov <snaury@gmail.com>
- * Correctly save rbp, csr and cw
- * 01-Apr-04 Hye-Shik Chang <perky@FreeBSD.org>
- * Ported from i386 to amd64.
- * 24-Nov-02 Christian Tismer <tismer@tismer.com>
- * needed to add another magic constant to insure
- * that f in slp_eval_frame(PyFrameObject *f)
- * STACK_REFPLUS will probably be 1 in most cases.
- * gets included into the saved stack area.
- * 17-Sep-02 Christian Tismer <tismer@tismer.com>
- * after virtualizing stack save/restore, the
- * stack size shrunk a bit. Needed to introduce
- * an adjustment STACK_MAGIC per platform.
- * 15-Sep-02 Gerd Woetzel <gerd.woetzel@GMD.DE>
- * slightly changed framework for spark
- * 31-Avr-02 Armin Rigo <arigo@ulb.ac.be>
- * Added ebx, esi and edi register-saves.
- * 01-Mar-02 Samual M. Rushing <rushing@ironport.com>
- * Ported from i386.
- */
-
-#define STACK_REFPLUS 1
-
-#ifdef SLP_EVAL
-
-/* #define STACK_MAGIC 3 */
-/* the above works fine with gcc 2.96, but 2.95.3 wants this */
-#define STACK_MAGIC 0
-
-#define REGS_TO_SAVE "r12", "r13", "r14", "r15"
-
-static int
-slp_switch(void)
-{
- int err;
- void* rbp;
- void* rbx;
- unsigned int csr;
- unsigned short cw;
- /* This used to be declared 'register', but that does nothing in
- modern compilers and is explicitly forbidden in some new
- standards. */
- long *stackref, stsizediff;
- __asm__ volatile ("" : : : REGS_TO_SAVE);
- __asm__ volatile ("fstcw %0" : "=m" (cw));
- __asm__ volatile ("stmxcsr %0" : "=m" (csr));
- __asm__ volatile ("movq %%rbp, %0" : "=m" (rbp));
- __asm__ volatile ("movq %%rbx, %0" : "=m" (rbx));
- __asm__ ("movq %%rsp, %0" : "=g" (stackref));
- {
- SLP_SAVE_STATE(stackref, stsizediff);
- __asm__ volatile (
- "addq %0, %%rsp\n"
- "addq %0, %%rbp\n"
- :
- : "r" (stsizediff)
- );
- SLP_RESTORE_STATE();
- __asm__ volatile ("xorq %%rax, %%rax" : "=a" (err));
- }
- __asm__ volatile ("movq %0, %%rbx" : : "m" (rbx));
- __asm__ volatile ("movq %0, %%rbp" : : "m" (rbp));
- __asm__ volatile ("ldmxcsr %0" : : "m" (csr));
- __asm__ volatile ("fldcw %0" : : "m" (cw));
- __asm__ volatile ("" : : : REGS_TO_SAVE);
- return err;
-}
-
-#endif
-
-/*
- * further self-processing support
- */
-
-/*
- * if you want to add self-inspection tools, place them
- * here. See the x86_msvc for the necessary defines.
- * These features are highly experimental und not
- * essential yet.
- */
diff --git a/venv/lib/python3.11/site-packages/greenlet/platform/switch_arm32_gcc.h b/venv/lib/python3.11/site-packages/greenlet/platform/switch_arm32_gcc.h
deleted file mode 100644
index 655003a..0000000
--- a/venv/lib/python3.11/site-packages/greenlet/platform/switch_arm32_gcc.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * this is the internal transfer function.
- *
- * HISTORY
- * 14-Aug-06 File creation. Ported from Arm Thumb. Sylvain Baro
- * 3-Sep-06 Commented out saving of r1-r3 (r4 already commented out) as I
- * read that these do not need to be saved. Also added notes and
- * errors related to the frame pointer. Richard Tew.
- *
- * NOTES
- *
- * It is not possible to detect if fp is used or not, so the supplied
- * switch function needs to support it, so that you can remove it if
- * it does not apply to you.
- *
- * POSSIBLE ERRORS
- *
- * "fp cannot be used in asm here"
- *
- * - Try commenting out "fp" in REGS_TO_SAVE.
- *
- */
-
-#define STACK_REFPLUS 1
-
-#ifdef SLP_EVAL
-#define STACK_MAGIC 0
-#define REG_SP "sp"
-#define REG_SPSP "sp,sp"
-#ifdef __thumb__
-#define REG_FP "r7"
-#define REG_FPFP "r7,r7"
-#define REGS_TO_SAVE_GENERAL "r4", "r5", "r6", "r8", "r9", "r10", "r11", "lr"
-#else
-#define REG_FP "fp"
-#define REG_FPFP "fp,fp"
-#define REGS_TO_SAVE_GENERAL "r4", "r5", "r6", "r7", "r8", "r9", "r10", "lr"
-#endif
-#if defined(__SOFTFP__)
-#define REGS_TO_SAVE REGS_TO_SAVE_GENERAL
-#elif defined(__VFP_FP__)
-#define REGS_TO_SAVE REGS_TO_SAVE_GENERAL, "d8", "d9", "d10", "d11", \
- "d12", "d13", "d14", "d15"
-#elif defined(__MAVERICK__)
-#define REGS_TO_SAVE REGS_TO_SAVE_GENERAL, "mvf4", "mvf5", "mvf6", "mvf7", \
- "mvf8", "mvf9", "mvf10", "mvf11", \
- "mvf12", "mvf13", "mvf14", "mvf15"
-#else
-#define REGS_TO_SAVE REGS_TO_SAVE_GENERAL, "f4", "f5", "f6", "f7"
-#endif
-
-static int
-#ifdef __GNUC__
-__attribute__((optimize("no-omit-frame-pointer")))
-#endif
-slp_switch(void)
-{
- void *fp;
- int *stackref, stsizediff;
- int result;
- __asm__ volatile ("" : : : REGS_TO_SAVE);
- __asm__ volatile ("mov r0," REG_FP "\n\tstr r0,%0" : "=m" (fp) : : "r0");
- __asm__ ("mov %0," REG_SP : "=r" (stackref));
- {
- SLP_SAVE_STATE(stackref, stsizediff);
- __asm__ volatile (
- "add " REG_SPSP ",%0\n"
- "add " REG_FPFP ",%0\n"
- :
- : "r" (stsizediff)
- );
- SLP_RESTORE_STATE();
- }
- __asm__ volatile ("ldr r0,%1\n\tmov " REG_FP ",r0\n\tmov %0, #0" : "=r" (result) : "m" (fp) : "r0");
- __asm__ volatile ("" : : : REGS_TO_SAVE);
- return result;
-}
-
-#endif
diff --git a/venv/lib/python3.11/site-packages/greenlet/platform/switch_arm32_ios.h b/venv/lib/python3.11/site-packages/greenlet/platform/switch_arm32_ios.h
deleted file mode 100644
index 9e640e1..0000000
--- a/venv/lib/python3.11/site-packages/greenlet/platform/switch_arm32_ios.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * this is the internal transfer function.
- *
- * HISTORY
- * 31-May-15 iOS support. Ported from arm32. Proton <feisuzhu@163.com>
- *
- * NOTES
- *
- * It is not possible to detect if fp is used or not, so the supplied
- * switch function needs to support it, so that you can remove it if
- * it does not apply to you.
- *
- * POSSIBLE ERRORS
- *
- * "fp cannot be used in asm here"
- *
- * - Try commenting out "fp" in REGS_TO_SAVE.
- *
- */
-
-#define STACK_REFPLUS 1
-
-#ifdef SLP_EVAL
-
-#define STACK_MAGIC 0
-#define REG_SP "sp"
-#define REG_SPSP "sp,sp"
-#define REG_FP "r7"
-#define REG_FPFP "r7,r7"
-#define REGS_TO_SAVE_GENERAL "r4", "r5", "r6", "r8", "r10", "r11", "lr"
-#define REGS_TO_SAVE REGS_TO_SAVE_GENERAL, "d8", "d9", "d10", "d11", \
- "d12", "d13", "d14", "d15"
-
-static int
-#ifdef __GNUC__
-__attribute__((optimize("no-omit-frame-pointer")))
-#endif
-slp_switch(void)
-{
- void *fp;
- int *stackref, stsizediff, result;
- __asm__ volatile ("" : : : REGS_TO_SAVE);
- __asm__ volatile ("str " REG_FP ",%0" : "=m" (fp));
- __asm__ ("mov %0," REG_SP : "=r" (stackref));
- {
- SLP_SAVE_STATE(stackref, stsizediff);
- __asm__ volatile (
- "add " REG_SPSP ",%0\n"
- "add " REG_FPFP ",%0\n"
- :
- : "r" (stsizediff)
- : REGS_TO_SAVE /* Clobber registers, force compiler to
- * recalculate address of void *fp from REG_SP or REG_FP */
- );
- SLP_RESTORE_STATE();
- }
- __asm__ volatile (
- "ldr " REG_FP ", %1\n\t"
- "mov %0, #0"
- : "=r" (result)
- : "m" (fp)
- : REGS_TO_SAVE /* Force compiler to restore saved registers after this */
- );
- return result;
-}
-
-#endif
diff --git a/venv/lib/python3.11/site-packages/greenlet/platform/switch_arm64_masm.asm b/venv/lib/python3.11/site-packages/greenlet/platform/switch_arm64_masm.asm
deleted file mode 100644
index 29f9c22..0000000
--- a/venv/lib/python3.11/site-packages/greenlet/platform/switch_arm64_masm.asm
+++ /dev/null
@@ -1,53 +0,0 @@
- AREA switch_arm64_masm, CODE, READONLY;
- GLOBAL slp_switch [FUNC]
- EXTERN slp_save_state_asm
- EXTERN slp_restore_state_asm
-
-slp_switch
- ; push callee saved registers to stack
- stp x19, x20, [sp, #-16]!
- stp x21, x22, [sp, #-16]!
- stp x23, x24, [sp, #-16]!
- stp x25, x26, [sp, #-16]!
- stp x27, x28, [sp, #-16]!
- stp x29, x30, [sp, #-16]!
- stp d8, d9, [sp, #-16]!
- stp d10, d11, [sp, #-16]!
- stp d12, d13, [sp, #-16]!
- stp d14, d15, [sp, #-16]!
-
- ; call slp_save_state_asm with stack pointer
- mov x0, sp
- bl slp_save_state_asm
-
- ; early return for return value of 1 and -1
- cmp x0, #-1
- b.eq RETURN
- cmp x0, #1
- b.eq RETURN
-
- ; increment stack and frame pointer
- add sp, sp, x0
- add x29, x29, x0
-
- bl slp_restore_state_asm
-
- ; store return value for successful completion of routine
- mov x0, #0
-
-RETURN
- ; pop registers from stack
- ldp d14, d15, [sp], #16
- ldp d12, d13, [sp], #16
- ldp d10, d11, [sp], #16
- ldp d8, d9, [sp], #16
- ldp x29, x30, [sp], #16
- ldp x27, x28, [sp], #16
- ldp x25, x26, [sp], #16
- ldp x23, x24, [sp], #16
- ldp x21, x22, [sp], #16
- ldp x19, x20, [sp], #16
-
- ret
-
- END
diff --git a/venv/lib/python3.11/site-packages/greenlet/platform/switch_arm64_masm.obj b/venv/lib/python3.11/site-packages/greenlet/platform/switch_arm64_masm.obj
deleted file mode 100644
index f6f220e..0000000
--- a/venv/lib/python3.11/site-packages/greenlet/platform/switch_arm64_masm.obj
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/greenlet/platform/switch_arm64_msvc.h b/venv/lib/python3.11/site-packages/greenlet/platform/switch_arm64_msvc.h
deleted file mode 100644
index 7ab7f45..0000000
--- a/venv/lib/python3.11/site-packages/greenlet/platform/switch_arm64_msvc.h
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- * this is the internal transfer function.
- *
- * HISTORY
- * 21-Oct-21 Niyas Sait <niyas.sait@linaro.org>
- * First version to enable win/arm64 support.
- */
-
-#define STACK_REFPLUS 1
-#define STACK_MAGIC 0
-
-/* Use the generic support for an external assembly language slp_switch function. */
-#define EXTERNAL_ASM
-
-#ifdef SLP_EVAL
-/* This always uses the external masm assembly file. */
-#endif \ No newline at end of file
diff --git a/venv/lib/python3.11/site-packages/greenlet/platform/switch_csky_gcc.h b/venv/lib/python3.11/site-packages/greenlet/platform/switch_csky_gcc.h
deleted file mode 100644
index ac469d3..0000000
--- a/venv/lib/python3.11/site-packages/greenlet/platform/switch_csky_gcc.h
+++ /dev/null
@@ -1,48 +0,0 @@
-#ifdef SLP_EVAL
-#define STACK_MAGIC 0
-#define REG_FP "r8"
-#ifdef __CSKYABIV2__
-#define REGS_TO_SAVE_GENERAL "r4", "r5", "r6", "r7", "r9", "r10", "r11", "r15",\
- "r16", "r17", "r18", "r19", "r20", "r21", "r22",\
- "r23", "r24", "r25"
-
-#if defined (__CSKY_HARD_FLOAT__) || (__CSKY_VDSP__)
-#define REGS_TO_SAVE REGS_TO_SAVE_GENERAL, "vr8", "vr9", "vr10", "vr11", "vr12",\
- "vr13", "vr14", "vr15"
-#else
-#define REGS_TO_SAVE REGS_TO_SAVE_GENERAL
-#endif
-#else
-#define REGS_TO_SAVE "r9", "r10", "r11", "r12", "r13", "r15"
-#endif
-
-
-static int
-#ifdef __GNUC__
-__attribute__((optimize("no-omit-frame-pointer")))
-#endif
-slp_switch(void)
-{
- int *stackref, stsizediff;
- int result;
-
- __asm__ volatile ("" : : : REGS_TO_SAVE);
- __asm__ ("mov %0, sp" : "=r" (stackref));
- {
- SLP_SAVE_STATE(stackref, stsizediff);
- __asm__ volatile (
- "addu sp,%0\n"
- "addu "REG_FP",%0\n"
- :
- : "r" (stsizediff)
- );
-
- SLP_RESTORE_STATE();
- }
- __asm__ volatile ("movi %0, 0" : "=r" (result));
- __asm__ volatile ("" : : : REGS_TO_SAVE);
-
- return result;
-}
-
-#endif
diff --git a/venv/lib/python3.11/site-packages/greenlet/platform/switch_loongarch64_linux.h b/venv/lib/python3.11/site-packages/greenlet/platform/switch_loongarch64_linux.h
deleted file mode 100644
index 9eaf34e..0000000
--- a/venv/lib/python3.11/site-packages/greenlet/platform/switch_loongarch64_linux.h
+++ /dev/null
@@ -1,31 +0,0 @@
-#define STACK_REFPLUS 1
-
-#ifdef SLP_EVAL
-#define STACK_MAGIC 0
-
-#define REGS_TO_SAVE "s0", "s1", "s2", "s3", "s4", "s5", \
- "s6", "s7", "s8", "fp", \
- "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31"
-
-static int
-slp_switch(void)
-{
- int ret;
- long *stackref, stsizediff;
- __asm__ volatile ("" : : : REGS_TO_SAVE);
- __asm__ volatile ("move %0, $sp" : "=r" (stackref) : );
- {
- SLP_SAVE_STATE(stackref, stsizediff);
- __asm__ volatile (
- "add.d $sp, $sp, %0\n\t"
- : /* no outputs */
- : "r" (stsizediff)
- );
- SLP_RESTORE_STATE();
- }
- __asm__ volatile ("" : : : REGS_TO_SAVE);
- __asm__ volatile ("move %0, $zero" : "=r" (ret) : );
- return ret;
-}
-
-#endif
diff --git a/venv/lib/python3.11/site-packages/greenlet/platform/switch_m68k_gcc.h b/venv/lib/python3.11/site-packages/greenlet/platform/switch_m68k_gcc.h
deleted file mode 100644
index da761c2..0000000
--- a/venv/lib/python3.11/site-packages/greenlet/platform/switch_m68k_gcc.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * this is the internal transfer function.
- *
- * HISTORY
- * 2014-01-06 Andreas Schwab <schwab@linux-m68k.org>
- * File created.
- */
-
-#ifdef SLP_EVAL
-
-#define STACK_MAGIC 0
-
-#define REGS_TO_SAVE "%d2", "%d3", "%d4", "%d5", "%d6", "%d7", \
- "%a2", "%a3", "%a4"
-
-static int
-slp_switch(void)
-{
- int err;
- int *stackref, stsizediff;
- void *fp, *a5;
- __asm__ volatile ("" : : : REGS_TO_SAVE);
- __asm__ volatile ("move.l %%fp, %0" : "=m"(fp));
- __asm__ volatile ("move.l %%a5, %0" : "=m"(a5));
- __asm__ ("move.l %%sp, %0" : "=r"(stackref));
- {
- SLP_SAVE_STATE(stackref, stsizediff);
- __asm__ volatile ("add.l %0, %%sp; add.l %0, %%fp" : : "r"(stsizediff));
- SLP_RESTORE_STATE();
- __asm__ volatile ("clr.l %0" : "=g" (err));
- }
- __asm__ volatile ("move.l %0, %%a5" : : "m"(a5));
- __asm__ volatile ("move.l %0, %%fp" : : "m"(fp));
- __asm__ volatile ("" : : : REGS_TO_SAVE);
- return err;
-}
-
-#endif
diff --git a/venv/lib/python3.11/site-packages/greenlet/platform/switch_mips_unix.h b/venv/lib/python3.11/site-packages/greenlet/platform/switch_mips_unix.h
deleted file mode 100644
index b9003e9..0000000
--- a/venv/lib/python3.11/site-packages/greenlet/platform/switch_mips_unix.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * this is the internal transfer function.
- *
- * HISTORY
- * 20-Sep-14 Matt Madison <madison@bliss-m.org>
- * Re-code the saving of the gp register for MIPS64.
- * 05-Jan-08 Thiemo Seufer <ths@debian.org>
- * Ported from ppc.
- */
-
-#define STACK_REFPLUS 1
-
-#ifdef SLP_EVAL
-
-#define STACK_MAGIC 0
-
-#define REGS_TO_SAVE "$16", "$17", "$18", "$19", "$20", "$21", "$22", \
- "$23", "$30"
-static int
-slp_switch(void)
-{
- int err;
- int *stackref, stsizediff;
-#ifdef __mips64
- uint64_t gpsave;
-#endif
- __asm__ __volatile__ ("" : : : REGS_TO_SAVE);
-#ifdef __mips64
- __asm__ __volatile__ ("sd $28,%0" : "=m" (gpsave) : : );
-#endif
- __asm__ ("move %0, $29" : "=r" (stackref) : );
- {
- SLP_SAVE_STATE(stackref, stsizediff);
- __asm__ __volatile__ (
-#ifdef __mips64
- "daddu $29, %0\n"
-#else
- "addu $29, %0\n"
-#endif
- : /* no outputs */
- : "r" (stsizediff)
- );
- SLP_RESTORE_STATE();
- }
-#ifdef __mips64
- __asm__ __volatile__ ("ld $28,%0" : : "m" (gpsave) : );
-#endif
- __asm__ __volatile__ ("" : : : REGS_TO_SAVE);
- __asm__ __volatile__ ("move %0, $0" : "=r" (err));
- return err;
-}
-
-#endif
-
-/*
- * further self-processing support
- */
-
-/*
- * if you want to add self-inspection tools, place them
- * here. See the x86_msvc for the necessary defines.
- * These features are highly experimental und not
- * essential yet.
- */
diff --git a/venv/lib/python3.11/site-packages/greenlet/platform/switch_ppc64_aix.h b/venv/lib/python3.11/site-packages/greenlet/platform/switch_ppc64_aix.h
deleted file mode 100644
index e7e0b87..0000000
--- a/venv/lib/python3.11/site-packages/greenlet/platform/switch_ppc64_aix.h
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * this is the internal transfer function.
- *
- * HISTORY
- * 16-Oct-20 Jesse Gorzinski <jgorzins@us.ibm.com>
- * Copied from Linux PPC64 implementation
- * 04-Sep-18 Alexey Borzenkov <snaury@gmail.com>
- * Workaround a gcc bug using manual save/restore of r30
- * 21-Mar-18 Tulio Magno Quites Machado Filho <tuliom@linux.vnet.ibm.com>
- * Added r30 to the list of saved registers in order to fully comply with
- * both ppc64 ELFv1 ABI and the ppc64le ELFv2 ABI, that classify this
- * register as a nonvolatile register used for local variables.
- * 21-Mar-18 Laszlo Boszormenyi <gcs@debian.org>
- * Save r2 (TOC pointer) manually.
- * 10-Dec-13 Ulrich Weigand <uweigand@de.ibm.com>
- * Support ELFv2 ABI. Save float/vector registers.
- * 09-Mar-12 Michael Ellerman <michael@ellerman.id.au>
- * 64-bit implementation, copied from 32-bit.
- * 07-Sep-05 (py-dev mailing list discussion)
- * removed 'r31' from the register-saved. !!!! WARNING !!!!
- * It means that this file can no longer be compiled statically!
- * It is now only suitable as part of a dynamic library!
- * 14-Jan-04 Bob Ippolito <bob@redivi.com>
- * added cr2-cr4 to the registers to be saved.
- * Open questions: Should we save FP registers?
- * What about vector registers?
- * Differences between darwin and unix?
- * 24-Nov-02 Christian Tismer <tismer@tismer.com>
- * needed to add another magic constant to insure
- * that f in slp_eval_frame(PyFrameObject *f)
- * STACK_REFPLUS will probably be 1 in most cases.
- * gets included into the saved stack area.
- * 04-Oct-02 Gustavo Niemeyer <niemeyer@conectiva.com>
- * Ported from MacOS version.
- * 17-Sep-02 Christian Tismer <tismer@tismer.com>
- * after virtualizing stack save/restore, the
- * stack size shrunk a bit. Needed to introduce
- * an adjustment STACK_MAGIC per platform.
- * 15-Sep-02 Gerd Woetzel <gerd.woetzel@GMD.DE>
- * slightly changed framework for sparc
- * 29-Jun-02 Christian Tismer <tismer@tismer.com>
- * Added register 13-29, 31 saves. The same way as
- * Armin Rigo did for the x86_unix version.
- * This seems to be now fully functional!
- * 04-Mar-02 Hye-Shik Chang <perky@fallin.lv>
- * Ported from i386.
- * 31-Jul-12 Trevor Bowen <trevorbowen@gmail.com>
- * Changed memory constraints to register only.
- */
-
-#define STACK_REFPLUS 1
-
-#ifdef SLP_EVAL
-
-#define STACK_MAGIC 6
-
-#if defined(__ALTIVEC__)
-#define ALTIVEC_REGS \
- "v20", "v21", "v22", "v23", "v24", "v25", "v26", "v27", \
- "v28", "v29", "v30", "v31",
-#else
-#define ALTIVEC_REGS
-#endif
-
-#define REGS_TO_SAVE "r14", "r15", "r16", "r17", "r18", "r19", "r20", \
- "r21", "r22", "r23", "r24", "r25", "r26", "r27", "r28", "r29", \
- "r31", \
- "fr14", "fr15", "fr16", "fr17", "fr18", "fr19", "fr20", "fr21", \
- "fr22", "fr23", "fr24", "fr25", "fr26", "fr27", "fr28", "fr29", \
- "fr30", "fr31", \
- ALTIVEC_REGS \
- "cr2", "cr3", "cr4"
-
-static int
-slp_switch(void)
-{
- int err;
- long *stackref, stsizediff;
- void * toc;
- void * r30;
- __asm__ volatile ("" : : : REGS_TO_SAVE);
- __asm__ volatile ("std 2, %0" : "=m" (toc));
- __asm__ volatile ("std 30, %0" : "=m" (r30));
- __asm__ ("mr %0, 1" : "=r" (stackref) : );
- {
- SLP_SAVE_STATE(stackref, stsizediff);
- __asm__ volatile (
- "mr 11, %0\n"
- "add 1, 1, 11\n"
- : /* no outputs */
- : "r" (stsizediff)
- : "11"
- );
- SLP_RESTORE_STATE();
- }
- __asm__ volatile ("ld 30, %0" : : "m" (r30));
- __asm__ volatile ("ld 2, %0" : : "m" (toc));
- __asm__ volatile ("" : : : REGS_TO_SAVE);
- __asm__ volatile ("li %0, 0" : "=r" (err));
- return err;
-}
-
-#endif
diff --git a/venv/lib/python3.11/site-packages/greenlet/platform/switch_ppc64_linux.h b/venv/lib/python3.11/site-packages/greenlet/platform/switch_ppc64_linux.h
deleted file mode 100644
index 3c324d0..0000000
--- a/venv/lib/python3.11/site-packages/greenlet/platform/switch_ppc64_linux.h
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * this is the internal transfer function.
- *
- * HISTORY
- * 04-Sep-18 Alexey Borzenkov <snaury@gmail.com>
- * Workaround a gcc bug using manual save/restore of r30
- * 21-Mar-18 Tulio Magno Quites Machado Filho <tuliom@linux.vnet.ibm.com>
- * Added r30 to the list of saved registers in order to fully comply with
- * both ppc64 ELFv1 ABI and the ppc64le ELFv2 ABI, that classify this
- * register as a nonvolatile register used for local variables.
- * 21-Mar-18 Laszlo Boszormenyi <gcs@debian.org>
- * Save r2 (TOC pointer) manually.
- * 10-Dec-13 Ulrich Weigand <uweigand@de.ibm.com>
- * Support ELFv2 ABI. Save float/vector registers.
- * 09-Mar-12 Michael Ellerman <michael@ellerman.id.au>
- * 64-bit implementation, copied from 32-bit.
- * 07-Sep-05 (py-dev mailing list discussion)
- * removed 'r31' from the register-saved. !!!! WARNING !!!!
- * It means that this file can no longer be compiled statically!
- * It is now only suitable as part of a dynamic library!
- * 14-Jan-04 Bob Ippolito <bob@redivi.com>
- * added cr2-cr4 to the registers to be saved.
- * Open questions: Should we save FP registers?
- * What about vector registers?
- * Differences between darwin and unix?
- * 24-Nov-02 Christian Tismer <tismer@tismer.com>
- * needed to add another magic constant to insure
- * that f in slp_eval_frame(PyFrameObject *f)
- * STACK_REFPLUS will probably be 1 in most cases.
- * gets included into the saved stack area.
- * 04-Oct-02 Gustavo Niemeyer <niemeyer@conectiva.com>
- * Ported from MacOS version.
- * 17-Sep-02 Christian Tismer <tismer@tismer.com>
- * after virtualizing stack save/restore, the
- * stack size shrunk a bit. Needed to introduce
- * an adjustment STACK_MAGIC per platform.
- * 15-Sep-02 Gerd Woetzel <gerd.woetzel@GMD.DE>
- * slightly changed framework for sparc
- * 29-Jun-02 Christian Tismer <tismer@tismer.com>
- * Added register 13-29, 31 saves. The same way as
- * Armin Rigo did for the x86_unix version.
- * This seems to be now fully functional!
- * 04-Mar-02 Hye-Shik Chang <perky@fallin.lv>
- * Ported from i386.
- * 31-Jul-12 Trevor Bowen <trevorbowen@gmail.com>
- * Changed memory constraints to register only.
- */
-
-#define STACK_REFPLUS 1
-
-#ifdef SLP_EVAL
-
-#if _CALL_ELF == 2
-#define STACK_MAGIC 4
-#else
-#define STACK_MAGIC 6
-#endif
-
-#if defined(__ALTIVEC__)
-#define ALTIVEC_REGS \
- "v20", "v21", "v22", "v23", "v24", "v25", "v26", "v27", \
- "v28", "v29", "v30", "v31",
-#else
-#define ALTIVEC_REGS
-#endif
-
-#define REGS_TO_SAVE "r14", "r15", "r16", "r17", "r18", "r19", "r20", \
- "r21", "r22", "r23", "r24", "r25", "r26", "r27", "r28", "r29", \
- "r31", \
- "fr14", "fr15", "fr16", "fr17", "fr18", "fr19", "fr20", "fr21", \
- "fr22", "fr23", "fr24", "fr25", "fr26", "fr27", "fr28", "fr29", \
- "fr30", "fr31", \
- ALTIVEC_REGS \
- "cr2", "cr3", "cr4"
-
-static int
-slp_switch(void)
-{
- int err;
- long *stackref, stsizediff;
- void * toc;
- void * r30;
- __asm__ volatile ("" : : : REGS_TO_SAVE);
- __asm__ volatile ("std 2, %0" : "=m" (toc));
- __asm__ volatile ("std 30, %0" : "=m" (r30));
- __asm__ ("mr %0, 1" : "=r" (stackref) : );
- {
- SLP_SAVE_STATE(stackref, stsizediff);
- __asm__ volatile (
- "mr 11, %0\n"
- "add 1, 1, 11\n"
- : /* no outputs */
- : "r" (stsizediff)
- : "11"
- );
- SLP_RESTORE_STATE();
- }
- __asm__ volatile ("ld 30, %0" : : "m" (r30));
- __asm__ volatile ("ld 2, %0" : : "m" (toc));
- __asm__ volatile ("" : : : REGS_TO_SAVE);
- __asm__ volatile ("li %0, 0" : "=r" (err));
- return err;
-}
-
-#endif
diff --git a/venv/lib/python3.11/site-packages/greenlet/platform/switch_ppc_aix.h b/venv/lib/python3.11/site-packages/greenlet/platform/switch_ppc_aix.h
deleted file mode 100644
index 6d93c13..0000000
--- a/venv/lib/python3.11/site-packages/greenlet/platform/switch_ppc_aix.h
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * this is the internal transfer function.
- *
- * HISTORY
- * 07-Mar-11 Floris Bruynooghe <flub@devork.be>
- * Do not add stsizediff to general purpose
- * register (GPR) 30 as this is a non-volatile and
- * unused by the PowerOpen Environment, therefore
- * this was modifying a user register instead of the
- * frame pointer (which does not seem to exist).
- * 07-Sep-05 (py-dev mailing list discussion)
- * removed 'r31' from the register-saved. !!!! WARNING !!!!
- * It means that this file can no longer be compiled statically!
- * It is now only suitable as part of a dynamic library!
- * 14-Jan-04 Bob Ippolito <bob@redivi.com>
- * added cr2-cr4 to the registers to be saved.
- * Open questions: Should we save FP registers?
- * What about vector registers?
- * Differences between darwin and unix?
- * 24-Nov-02 Christian Tismer <tismer@tismer.com>
- * needed to add another magic constant to insure
- * that f in slp_eval_frame(PyFrameObject *f)
- * STACK_REFPLUS will probably be 1 in most cases.
- * gets included into the saved stack area.
- * 04-Oct-02 Gustavo Niemeyer <niemeyer@conectiva.com>
- * Ported from MacOS version.
- * 17-Sep-02 Christian Tismer <tismer@tismer.com>
- * after virtualizing stack save/restore, the
- * stack size shrunk a bit. Needed to introduce
- * an adjustment STACK_MAGIC per platform.
- * 15-Sep-02 Gerd Woetzel <gerd.woetzel@GMD.DE>
- * slightly changed framework for sparc
- * 29-Jun-02 Christian Tismer <tismer@tismer.com>
- * Added register 13-29, 31 saves. The same way as
- * Armin Rigo did for the x86_unix version.
- * This seems to be now fully functional!
- * 04-Mar-02 Hye-Shik Chang <perky@fallin.lv>
- * Ported from i386.
- */
-
-#define STACK_REFPLUS 1
-
-#ifdef SLP_EVAL
-
-#define STACK_MAGIC 3
-
-/* !!!!WARNING!!!! need to add "r31" in the next line if this header file
- * is meant to be compiled non-dynamically!
- */
-#define REGS_TO_SAVE "r13", "r14", "r15", "r16", "r17", "r18", "r19", "r20", \
- "r21", "r22", "r23", "r24", "r25", "r26", "r27", "r28", "r29", \
- "cr2", "cr3", "cr4"
-static int
-slp_switch(void)
-{
- int err;
- int *stackref, stsizediff;
- __asm__ volatile ("" : : : REGS_TO_SAVE);
- __asm__ ("mr %0, 1" : "=r" (stackref) : );
- {
- SLP_SAVE_STATE(stackref, stsizediff);
- __asm__ volatile (
- "mr 11, %0\n"
- "add 1, 1, 11\n"
- : /* no outputs */
- : "r" (stsizediff)
- : "11"
- );
- SLP_RESTORE_STATE();
- }
- __asm__ volatile ("" : : : REGS_TO_SAVE);
- __asm__ volatile ("li %0, 0" : "=r" (err));
- return err;
-}
-
-#endif
-
-/*
- * further self-processing support
- */
-
-/*
- * if you want to add self-inspection tools, place them
- * here. See the x86_msvc for the necessary defines.
- * These features are highly experimental und not
- * essential yet.
- */
diff --git a/venv/lib/python3.11/site-packages/greenlet/platform/switch_ppc_linux.h b/venv/lib/python3.11/site-packages/greenlet/platform/switch_ppc_linux.h
deleted file mode 100644
index e83ad70..0000000
--- a/venv/lib/python3.11/site-packages/greenlet/platform/switch_ppc_linux.h
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * this is the internal transfer function.
- *
- * HISTORY
- * 07-Sep-05 (py-dev mailing list discussion)
- * removed 'r31' from the register-saved. !!!! WARNING !!!!
- * It means that this file can no longer be compiled statically!
- * It is now only suitable as part of a dynamic library!
- * 14-Jan-04 Bob Ippolito <bob@redivi.com>
- * added cr2-cr4 to the registers to be saved.
- * Open questions: Should we save FP registers?
- * What about vector registers?
- * Differences between darwin and unix?
- * 24-Nov-02 Christian Tismer <tismer@tismer.com>
- * needed to add another magic constant to insure
- * that f in slp_eval_frame(PyFrameObject *f)
- * STACK_REFPLUS will probably be 1 in most cases.
- * gets included into the saved stack area.
- * 04-Oct-02 Gustavo Niemeyer <niemeyer@conectiva.com>
- * Ported from MacOS version.
- * 17-Sep-02 Christian Tismer <tismer@tismer.com>
- * after virtualizing stack save/restore, the
- * stack size shrunk a bit. Needed to introduce
- * an adjustment STACK_MAGIC per platform.
- * 15-Sep-02 Gerd Woetzel <gerd.woetzel@GMD.DE>
- * slightly changed framework for sparc
- * 29-Jun-02 Christian Tismer <tismer@tismer.com>
- * Added register 13-29, 31 saves. The same way as
- * Armin Rigo did for the x86_unix version.
- * This seems to be now fully functional!
- * 04-Mar-02 Hye-Shik Chang <perky@fallin.lv>
- * Ported from i386.
- * 31-Jul-12 Trevor Bowen <trevorbowen@gmail.com>
- * Changed memory constraints to register only.
- */
-
-#define STACK_REFPLUS 1
-
-#ifdef SLP_EVAL
-
-#define STACK_MAGIC 3
-
-/* !!!!WARNING!!!! need to add "r31" in the next line if this header file
- * is meant to be compiled non-dynamically!
- */
-#define REGS_TO_SAVE "r13", "r14", "r15", "r16", "r17", "r18", "r19", "r20", \
- "r21", "r22", "r23", "r24", "r25", "r26", "r27", "r28", "r29", \
- "cr2", "cr3", "cr4"
-static int
-slp_switch(void)
-{
- int err;
- int *stackref, stsizediff;
- __asm__ volatile ("" : : : REGS_TO_SAVE);
- __asm__ ("mr %0, 1" : "=r" (stackref) : );
- {
- SLP_SAVE_STATE(stackref, stsizediff);
- __asm__ volatile (
- "mr 11, %0\n"
- "add 1, 1, 11\n"
- "add 30, 30, 11\n"
- : /* no outputs */
- : "r" (stsizediff)
- : "11"
- );
- SLP_RESTORE_STATE();
- }
- __asm__ volatile ("" : : : REGS_TO_SAVE);
- __asm__ volatile ("li %0, 0" : "=r" (err));
- return err;
-}
-
-#endif
-
-/*
- * further self-processing support
- */
-
-/*
- * if you want to add self-inspection tools, place them
- * here. See the x86_msvc for the necessary defines.
- * These features are highly experimental und not
- * essential yet.
- */
diff --git a/venv/lib/python3.11/site-packages/greenlet/platform/switch_ppc_macosx.h b/venv/lib/python3.11/site-packages/greenlet/platform/switch_ppc_macosx.h
deleted file mode 100644
index d6e5a03..0000000
--- a/venv/lib/python3.11/site-packages/greenlet/platform/switch_ppc_macosx.h
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * this is the internal transfer function.
- *
- * HISTORY
- * 07-Sep-05 (py-dev mailing list discussion)
- * removed 'r31' from the register-saved. !!!! WARNING !!!!
- * It means that this file can no longer be compiled statically!
- * It is now only suitable as part of a dynamic library!
- * 14-Jan-04 Bob Ippolito <bob@redivi.com>
- * added cr2-cr4 to the registers to be saved.
- * Open questions: Should we save FP registers?
- * What about vector registers?
- * Differences between darwin and unix?
- * 24-Nov-02 Christian Tismer <tismer@tismer.com>
- * needed to add another magic constant to insure
- * that f in slp_eval_frame(PyFrameObject *f)
- * STACK_REFPLUS will probably be 1 in most cases.
- * gets included into the saved stack area.
- * 17-Sep-02 Christian Tismer <tismer@tismer.com>
- * after virtualizing stack save/restore, the
- * stack size shrunk a bit. Needed to introduce
- * an adjustment STACK_MAGIC per platform.
- * 15-Sep-02 Gerd Woetzel <gerd.woetzel@GMD.DE>
- * slightly changed framework for sparc
- * 29-Jun-02 Christian Tismer <tismer@tismer.com>
- * Added register 13-29, 31 saves. The same way as
- * Armin Rigo did for the x86_unix version.
- * This seems to be now fully functional!
- * 04-Mar-02 Hye-Shik Chang <perky@fallin.lv>
- * Ported from i386.
- */
-
-#define STACK_REFPLUS 1
-
-#ifdef SLP_EVAL
-
-#define STACK_MAGIC 3
-
-/* !!!!WARNING!!!! need to add "r31" in the next line if this header file
- * is meant to be compiled non-dynamically!
- */
-#define REGS_TO_SAVE "r13", "r14", "r15", "r16", "r17", "r18", "r19", "r20", \
- "r21", "r22", "r23", "r24", "r25", "r26", "r27", "r28", "r29", \
- "cr2", "cr3", "cr4"
-
-static int
-slp_switch(void)
-{
- int err;
- int *stackref, stsizediff;
- __asm__ volatile ("" : : : REGS_TO_SAVE);
- __asm__ ("; asm block 2\n\tmr %0, r1" : "=g" (stackref) : );
- {
- SLP_SAVE_STATE(stackref, stsizediff);
- __asm__ volatile (
- "; asm block 3\n"
- "\tmr r11, %0\n"
- "\tadd r1, r1, r11\n"
- "\tadd r30, r30, r11\n"
- : /* no outputs */
- : "g" (stsizediff)
- : "r11"
- );
- SLP_RESTORE_STATE();
- }
- __asm__ volatile ("" : : : REGS_TO_SAVE);
- __asm__ volatile ("li %0, 0" : "=r" (err));
- return err;
-}
-
-#endif
-
-/*
- * further self-processing support
- */
-
-/*
- * if you want to add self-inspection tools, place them
- * here. See the x86_msvc for the necessary defines.
- * These features are highly experimental und not
- * essential yet.
- */
diff --git a/venv/lib/python3.11/site-packages/greenlet/platform/switch_ppc_unix.h b/venv/lib/python3.11/site-packages/greenlet/platform/switch_ppc_unix.h
deleted file mode 100644
index ca590a5..0000000
--- a/venv/lib/python3.11/site-packages/greenlet/platform/switch_ppc_unix.h
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * this is the internal transfer function.
- *
- * HISTORY
- * 07-Sep-05 (py-dev mailing list discussion)
- * removed 'r31' from the register-saved. !!!! WARNING !!!!
- * It means that this file can no longer be compiled statically!
- * It is now only suitable as part of a dynamic library!
- * 14-Jan-04 Bob Ippolito <bob@redivi.com>
- * added cr2-cr4 to the registers to be saved.
- * Open questions: Should we save FP registers?
- * What about vector registers?
- * Differences between darwin and unix?
- * 24-Nov-02 Christian Tismer <tismer@tismer.com>
- * needed to add another magic constant to insure
- * that f in slp_eval_frame(PyFrameObject *f)
- * STACK_REFPLUS will probably be 1 in most cases.
- * gets included into the saved stack area.
- * 04-Oct-02 Gustavo Niemeyer <niemeyer@conectiva.com>
- * Ported from MacOS version.
- * 17-Sep-02 Christian Tismer <tismer@tismer.com>
- * after virtualizing stack save/restore, the
- * stack size shrunk a bit. Needed to introduce
- * an adjustment STACK_MAGIC per platform.
- * 15-Sep-02 Gerd Woetzel <gerd.woetzel@GMD.DE>
- * slightly changed framework for sparc
- * 29-Jun-02 Christian Tismer <tismer@tismer.com>
- * Added register 13-29, 31 saves. The same way as
- * Armin Rigo did for the x86_unix version.
- * This seems to be now fully functional!
- * 04-Mar-02 Hye-Shik Chang <perky@fallin.lv>
- * Ported from i386.
- */
-
-#define STACK_REFPLUS 1
-
-#ifdef SLP_EVAL
-
-#define STACK_MAGIC 3
-
-/* !!!!WARNING!!!! need to add "r31" in the next line if this header file
- * is meant to be compiled non-dynamically!
- */
-#define REGS_TO_SAVE "r13", "r14", "r15", "r16", "r17", "r18", "r19", "r20", \
- "r21", "r22", "r23", "r24", "r25", "r26", "r27", "r28", "r29", \
- "cr2", "cr3", "cr4"
-static int
-slp_switch(void)
-{
- int err;
- int *stackref, stsizediff;
- __asm__ volatile ("" : : : REGS_TO_SAVE);
- __asm__ ("mr %0, 1" : "=g" (stackref) : );
- {
- SLP_SAVE_STATE(stackref, stsizediff);
- __asm__ volatile (
- "mr 11, %0\n"
- "add 1, 1, 11\n"
- "add 30, 30, 11\n"
- : /* no outputs */
- : "g" (stsizediff)
- : "11"
- );
- SLP_RESTORE_STATE();
- }
- __asm__ volatile ("" : : : REGS_TO_SAVE);
- __asm__ volatile ("li %0, 0" : "=r" (err));
- return err;
-}
-
-#endif
-
-/*
- * further self-processing support
- */
-
-/*
- * if you want to add self-inspection tools, place them
- * here. See the x86_msvc for the necessary defines.
- * These features are highly experimental und not
- * essential yet.
- */
diff --git a/venv/lib/python3.11/site-packages/greenlet/platform/switch_riscv_unix.h b/venv/lib/python3.11/site-packages/greenlet/platform/switch_riscv_unix.h
deleted file mode 100644
index 24df9db..0000000
--- a/venv/lib/python3.11/site-packages/greenlet/platform/switch_riscv_unix.h
+++ /dev/null
@@ -1,32 +0,0 @@
-#define STACK_REFPLUS 1
-
-#ifdef SLP_EVAL
-#define STACK_MAGIC 0
-
-#define REGS_TO_SAVE "s0", "s1", "s2", "s3", "s4", "s5", \
- "s6", "s7", "s8", "s9", "s10", "s11", "fs0", "fs1", \
- "fs2", "fs3", "fs4", "fs5", "fs6", "fs7", "fs8", "fs9", \
- "fs10", "fs11"
-
-static int
-slp_switch(void)
-{
- int ret;
- long *stackref, stsizediff;
- __asm__ volatile ("" : : : REGS_TO_SAVE);
- __asm__ volatile ("mv %0, sp" : "=r" (stackref) : );
- {
- SLP_SAVE_STATE(stackref, stsizediff);
- __asm__ volatile (
- "add sp, sp, %0\n\t"
- : /* no outputs */
- : "r" (stsizediff)
- );
- SLP_RESTORE_STATE();
- }
- __asm__ volatile ("" : : : REGS_TO_SAVE);
- __asm__ volatile ("mv %0, zero" : "=r" (ret) : );
- return ret;
-}
-
-#endif
diff --git a/venv/lib/python3.11/site-packages/greenlet/platform/switch_s390_unix.h b/venv/lib/python3.11/site-packages/greenlet/platform/switch_s390_unix.h
deleted file mode 100644
index 9199367..0000000
--- a/venv/lib/python3.11/site-packages/greenlet/platform/switch_s390_unix.h
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * this is the internal transfer function.
- *
- * HISTORY
- * 25-Jan-12 Alexey Borzenkov <snaury@gmail.com>
- * Fixed Linux/S390 port to work correctly with
- * different optimization options both on 31-bit
- * and 64-bit. Thanks to Stefan Raabe for lots
- * of testing.
- * 24-Nov-02 Christian Tismer <tismer@tismer.com>
- * needed to add another magic constant to insure
- * that f in slp_eval_frame(PyFrameObject *f)
- * STACK_REFPLUS will probably be 1 in most cases.
- * gets included into the saved stack area.
- * 06-Oct-02 Gustavo Niemeyer <niemeyer@conectiva.com>
- * Ported to Linux/S390.
- */
-
-#define STACK_REFPLUS 1
-
-#ifdef SLP_EVAL
-
-#ifdef __s390x__
-#define STACK_MAGIC 20 /* 20 * 8 = 160 bytes of function call area */
-#else
-#define STACK_MAGIC 24 /* 24 * 4 = 96 bytes of function call area */
-#endif
-
-/* Technically, r11-r13 also need saving, but function prolog starts
- with stm(g) and since there are so many saved registers already
- it won't be optimized, resulting in all r6-r15 being saved */
-#define REGS_TO_SAVE "r6", "r7", "r8", "r9", "r10", "r14", \
- "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", \
- "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15"
-
-static int
-slp_switch(void)
-{
- int ret;
- long *stackref, stsizediff;
- __asm__ volatile ("" : : : REGS_TO_SAVE);
-#ifdef __s390x__
- __asm__ volatile ("lgr %0, 15" : "=r" (stackref) : );
-#else
- __asm__ volatile ("lr %0, 15" : "=r" (stackref) : );
-#endif
- {
- SLP_SAVE_STATE(stackref, stsizediff);
-/* N.B.
- r11 may be used as the frame pointer, and in that case it cannot be
- clobbered and needs offsetting just like the stack pointer (but in cases
- where frame pointer isn't used we might clobber it accidentally). What's
- scary is that r11 is 2nd (and even 1st when GOT is used) callee saved
- register that gcc would chose for surviving function calls. However,
- since r6-r10 are clobbered above, their cost for reuse is reduced, so
- gcc IRA will chose them over r11 (not seeing r11 is implicitly saved),
- making it relatively safe to offset in all cases. :) */
- __asm__ volatile (
-#ifdef __s390x__
- "agr 15, %0\n\t"
- "agr 11, %0"
-#else
- "ar 15, %0\n\t"
- "ar 11, %0"
-#endif
- : /* no outputs */
- : "r" (stsizediff)
- );
- SLP_RESTORE_STATE();
- }
- __asm__ volatile ("" : : : REGS_TO_SAVE);
- __asm__ volatile ("lhi %0, 0" : "=r" (ret) : );
- return ret;
-}
-
-#endif
-
-/*
- * further self-processing support
- */
-
-/*
- * if you want to add self-inspection tools, place them
- * here. See the x86_msvc for the necessary defines.
- * These features are highly experimental und not
- * essential yet.
- */
diff --git a/venv/lib/python3.11/site-packages/greenlet/platform/switch_sparc_sun_gcc.h b/venv/lib/python3.11/site-packages/greenlet/platform/switch_sparc_sun_gcc.h
deleted file mode 100644
index 96990c3..0000000
--- a/venv/lib/python3.11/site-packages/greenlet/platform/switch_sparc_sun_gcc.h
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * this is the internal transfer function.
- *
- * HISTORY
- * 16-May-15 Alexey Borzenkov <snaury@gmail.com>
- * Move stack spilling code inside save/restore functions
- * 30-Aug-13 Floris Bruynooghe <flub@devork.be>
- Clean the register windows again before returning.
- This does not clobber the PIC register as it leaves
- the current window intact and is required for multi-
- threaded code to work correctly.
- * 08-Mar-11 Floris Bruynooghe <flub@devork.be>
- * No need to set return value register explicitly
- * before the stack and framepointer are adjusted
- * as none of the other registers are influenced by
- * this. Also don't needlessly clean the windows
- * ('ta %0" :: "i" (ST_CLEAN_WINDOWS)') as that
- * clobbers the gcc PIC register (%l7).
- * 24-Nov-02 Christian Tismer <tismer@tismer.com>
- * needed to add another magic constant to insure
- * that f in slp_eval_frame(PyFrameObject *f)
- * STACK_REFPLUS will probably be 1 in most cases.
- * gets included into the saved stack area.
- * 17-Sep-02 Christian Tismer <tismer@tismer.com>
- * after virtualizing stack save/restore, the
- * stack size shrunk a bit. Needed to introduce
- * an adjustment STACK_MAGIC per platform.
- * 15-Sep-02 Gerd Woetzel <gerd.woetzel@GMD.DE>
- * added support for SunOS sparc with gcc
- */
-
-#define STACK_REFPLUS 1
-
-#ifdef SLP_EVAL
-
-
-#define STACK_MAGIC 0
-
-
-#if defined(__sparcv9)
-#define SLP_FLUSHW __asm__ volatile ("flushw")
-#else
-#define SLP_FLUSHW __asm__ volatile ("ta 3") /* ST_FLUSH_WINDOWS */
-#endif
-
-/* On sparc we need to spill register windows inside save/restore functions */
-#define SLP_BEFORE_SAVE_STATE() SLP_FLUSHW
-#define SLP_BEFORE_RESTORE_STATE() SLP_FLUSHW
-
-
-static int
-slp_switch(void)
-{
- int err;
- int *stackref, stsizediff;
-
- /* Put current stack pointer into stackref.
- * Register spilling is done in save/restore.
- */
- __asm__ volatile ("mov %%sp, %0" : "=r" (stackref));
-
- {
- /* Thou shalt put SLP_SAVE_STATE into a local block */
- /* Copy the current stack onto the heap */
- SLP_SAVE_STATE(stackref, stsizediff);
-
- /* Increment stack and frame pointer by stsizediff */
- __asm__ volatile (
- "add %0, %%sp, %%sp\n\t"
- "add %0, %%fp, %%fp"
- : : "r" (stsizediff));
-
- /* Copy new stack from it's save store on the heap */
- SLP_RESTORE_STATE();
-
- __asm__ volatile ("mov %1, %0" : "=r" (err) : "i" (0));
- return err;
- }
-}
-
-#endif
-
-/*
- * further self-processing support
- */
-
-/*
- * if you want to add self-inspection tools, place them
- * here. See the x86_msvc for the necessary defines.
- * These features are highly experimental und not
- * essential yet.
- */
diff --git a/venv/lib/python3.11/site-packages/greenlet/platform/switch_x32_unix.h b/venv/lib/python3.11/site-packages/greenlet/platform/switch_x32_unix.h
deleted file mode 100644
index 893369c..0000000
--- a/venv/lib/python3.11/site-packages/greenlet/platform/switch_x32_unix.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * this is the internal transfer function.
- *
- * HISTORY
- * 17-Aug-12 Fantix King <fantix.king@gmail.com>
- * Ported from amd64.
- */
-
-#define STACK_REFPLUS 1
-
-#ifdef SLP_EVAL
-
-#define STACK_MAGIC 0
-
-#define REGS_TO_SAVE "r12", "r13", "r14", "r15"
-
-
-static int
-slp_switch(void)
-{
- void* ebp;
- void* ebx;
- unsigned int csr;
- unsigned short cw;
- int err;
- int *stackref, stsizediff;
- __asm__ volatile ("" : : : REGS_TO_SAVE);
- __asm__ volatile ("fstcw %0" : "=m" (cw));
- __asm__ volatile ("stmxcsr %0" : "=m" (csr));
- __asm__ volatile ("movl %%ebp, %0" : "=m" (ebp));
- __asm__ volatile ("movl %%ebx, %0" : "=m" (ebx));
- __asm__ ("movl %%esp, %0" : "=g" (stackref));
- {
- SLP_SAVE_STATE(stackref, stsizediff);
- __asm__ volatile (
- "addl %0, %%esp\n"
- "addl %0, %%ebp\n"
- :
- : "r" (stsizediff)
- );
- SLP_RESTORE_STATE();
- }
- __asm__ volatile ("movl %0, %%ebx" : : "m" (ebx));
- __asm__ volatile ("movl %0, %%ebp" : : "m" (ebp));
- __asm__ volatile ("ldmxcsr %0" : : "m" (csr));
- __asm__ volatile ("fldcw %0" : : "m" (cw));
- __asm__ volatile ("" : : : REGS_TO_SAVE);
- __asm__ volatile ("xorl %%eax, %%eax" : "=a" (err));
- return err;
-}
-
-#endif
-
-/*
- * further self-processing support
- */
-
-/*
- * if you want to add self-inspection tools, place them
- * here. See the x86_msvc for the necessary defines.
- * These features are highly experimental und not
- * essential yet.
- */
diff --git a/venv/lib/python3.11/site-packages/greenlet/platform/switch_x64_masm.asm b/venv/lib/python3.11/site-packages/greenlet/platform/switch_x64_masm.asm
deleted file mode 100644
index f5c72a2..0000000
--- a/venv/lib/python3.11/site-packages/greenlet/platform/switch_x64_masm.asm
+++ /dev/null
@@ -1,111 +0,0 @@
-;
-; stack switching code for MASM on x641
-; Kristjan Valur Jonsson, sept 2005
-;
-
-
-;prototypes for our calls
-slp_save_state_asm PROTO
-slp_restore_state_asm PROTO
-
-
-pushxmm MACRO reg
- sub rsp, 16
- .allocstack 16
- movaps [rsp], reg ; faster than movups, but we must be aligned
- ; .savexmm128 reg, offset (don't know what offset is, no documentation)
-ENDM
-popxmm MACRO reg
- movaps reg, [rsp] ; faster than movups, but we must be aligned
- add rsp, 16
-ENDM
-
-pushreg MACRO reg
- push reg
- .pushreg reg
-ENDM
-popreg MACRO reg
- pop reg
-ENDM
-
-
-.code
-slp_switch PROC FRAME
- ;realign stack to 16 bytes after return address push, makes the following faster
- sub rsp,8
- .allocstack 8
-
- pushxmm xmm15
- pushxmm xmm14
- pushxmm xmm13
- pushxmm xmm12
- pushxmm xmm11
- pushxmm xmm10
- pushxmm xmm9
- pushxmm xmm8
- pushxmm xmm7
- pushxmm xmm6
-
- pushreg r15
- pushreg r14
- pushreg r13
- pushreg r12
-
- pushreg rbp
- pushreg rbx
- pushreg rdi
- pushreg rsi
-
- sub rsp, 10h ;allocate the singlefunction argument (must be multiple of 16)
- .allocstack 10h
-.endprolog
-
- lea rcx, [rsp+10h] ;load stack base that we are saving
- call slp_save_state_asm ;pass stackpointer, return offset in eax
- cmp rax, 1
- je EXIT1
- cmp rax, -1
- je EXIT2
- ;actual stack switch:
- add rsp, rax
- call slp_restore_state_asm
- xor rax, rax ;return 0
-
-EXIT:
-
- add rsp, 10h
- popreg rsi
- popreg rdi
- popreg rbx
- popreg rbp
-
- popreg r12
- popreg r13
- popreg r14
- popreg r15
-
- popxmm xmm6
- popxmm xmm7
- popxmm xmm8
- popxmm xmm9
- popxmm xmm10
- popxmm xmm11
- popxmm xmm12
- popxmm xmm13
- popxmm xmm14
- popxmm xmm15
-
- add rsp, 8
- ret
-
-EXIT1:
- mov rax, 1
- jmp EXIT
-
-EXIT2:
- sar rax, 1
- jmp EXIT
-
-slp_switch ENDP
-
-END \ No newline at end of file
diff --git a/venv/lib/python3.11/site-packages/greenlet/platform/switch_x64_masm.obj b/venv/lib/python3.11/site-packages/greenlet/platform/switch_x64_masm.obj
deleted file mode 100644
index 64e3e6b..0000000
--- a/venv/lib/python3.11/site-packages/greenlet/platform/switch_x64_masm.obj
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/greenlet/platform/switch_x64_msvc.h b/venv/lib/python3.11/site-packages/greenlet/platform/switch_x64_msvc.h
deleted file mode 100644
index 601ea56..0000000
--- a/venv/lib/python3.11/site-packages/greenlet/platform/switch_x64_msvc.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * this is the internal transfer function.
- *
- * HISTORY
- * 24-Nov-02 Christian Tismer <tismer@tismer.com>
- * needed to add another magic constant to insure
- * that f in slp_eval_frame(PyFrameObject *f)
- * STACK_REFPLUS will probably be 1 in most cases.
- * gets included into the saved stack area.
- * 26-Sep-02 Christian Tismer <tismer@tismer.com>
- * again as a result of virtualized stack access,
- * the compiler used less registers. Needed to
- * explicit mention registers in order to get them saved.
- * Thanks to Jeff Senn for pointing this out and help.
- * 17-Sep-02 Christian Tismer <tismer@tismer.com>
- * after virtualizing stack save/restore, the
- * stack size shrunk a bit. Needed to introduce
- * an adjustment STACK_MAGIC per platform.
- * 15-Sep-02 Gerd Woetzel <gerd.woetzel@GMD.DE>
- * slightly changed framework for sparc
- * 01-Mar-02 Christian Tismer <tismer@tismer.com>
- * Initial final version after lots of iterations for i386.
- */
-
-/* Avoid alloca redefined warning on mingw64 */
-#ifndef alloca
-#define alloca _alloca
-#endif
-
-#define STACK_REFPLUS 1
-#define STACK_MAGIC 0
-
-/* Use the generic support for an external assembly language slp_switch function. */
-#define EXTERNAL_ASM
-
-#ifdef SLP_EVAL
-/* This always uses the external masm assembly file. */
-#endif
-
-/*
- * further self-processing support
- */
-
-/* we have IsBadReadPtr available, so we can peek at objects */
-/*
-#define STACKLESS_SPY
-
-#ifdef IMPLEMENT_STACKLESSMODULE
-#include "Windows.h"
-#define CANNOT_READ_MEM(p, bytes) IsBadReadPtr(p, bytes)
-
-static int IS_ON_STACK(void*p)
-{
- int stackref;
- intptr_t stackbase = ((intptr_t)&stackref) & 0xfffff000;
- return (intptr_t)p >= stackbase && (intptr_t)p < stackbase + 0x00100000;
-}
-
-#endif
-*/ \ No newline at end of file
diff --git a/venv/lib/python3.11/site-packages/greenlet/platform/switch_x86_msvc.h b/venv/lib/python3.11/site-packages/greenlet/platform/switch_x86_msvc.h
deleted file mode 100644
index 0f3a59f..0000000
--- a/venv/lib/python3.11/site-packages/greenlet/platform/switch_x86_msvc.h
+++ /dev/null
@@ -1,326 +0,0 @@
-/*
- * this is the internal transfer function.
- *
- * HISTORY
- * 24-Nov-02 Christian Tismer <tismer@tismer.com>
- * needed to add another magic constant to insure
- * that f in slp_eval_frame(PyFrameObject *f)
- * STACK_REFPLUS will probably be 1 in most cases.
- * gets included into the saved stack area.
- * 26-Sep-02 Christian Tismer <tismer@tismer.com>
- * again as a result of virtualized stack access,
- * the compiler used less registers. Needed to
- * explicit mention registers in order to get them saved.
- * Thanks to Jeff Senn for pointing this out and help.
- * 17-Sep-02 Christian Tismer <tismer@tismer.com>
- * after virtualizing stack save/restore, the
- * stack size shrunk a bit. Needed to introduce
- * an adjustment STACK_MAGIC per platform.
- * 15-Sep-02 Gerd Woetzel <gerd.woetzel@GMD.DE>
- * slightly changed framework for sparc
- * 01-Mar-02 Christian Tismer <tismer@tismer.com>
- * Initial final version after lots of iterations for i386.
- */
-
-#define alloca _alloca
-
-#define STACK_REFPLUS 1
-
-#ifdef SLP_EVAL
-
-#define STACK_MAGIC 0
-
-/* Some magic to quell warnings and keep slp_switch() from crashing when built
- with VC90. Disable global optimizations, and the warning: frame pointer
- register 'ebp' modified by inline assembly code.
-
- We used to just disable global optimizations ("g") but upstream stackless
- Python, as well as stackman, turn off all optimizations.
-
-References:
-https://github.com/stackless-dev/stackman/blob/dbc72fe5207a2055e658c819fdeab9731dee78b9/stackman/platforms/switch_x86_msvc.h
-https://github.com/stackless-dev/stackless/blob/main-slp/Stackless/platf/switch_x86_msvc.h
-*/
-#define WIN32_LEAN_AND_MEAN
-#include <windows.h>
-
-#pragma optimize("", off) /* so that autos are stored on the stack */
-#pragma warning(disable:4731)
-#pragma warning(disable:4733) /* disable warning about modifying FS[0] */
-
-/**
- * Most modern compilers and environments handle C++ exceptions without any
- * special help from us. MSVC on 32-bit windows is an exception. There, C++
- * exceptions are dealt with using Windows' Structured Exception Handling
- * (SEH).
- *
- * SEH is implemented as a singly linked list of <function*, prev*> nodes. The
- * head of this list is stored in the Thread Information Block, which itself
- * is pointed to from the FS register. It's the first field in the structure,
- * or offset 0, so we can access it using assembly FS:[0], or the compiler
- * intrinsics and field offset information from the headers (as we do below).
- * Somewhat unusually, the tail of the list doesn't have prev == NULL, it has
- * prev == 0xFFFFFFFF.
- *
- * SEH was designed for C, and traditionally uses the MSVC compiler
- * intrinsincs __try{}/__except{}. It is also utilized for C++ exceptions by
- * MSVC; there, every throw of a C++ exception raises a SEH error with the
- * ExceptionCode 0xE06D7363; the SEH handler list is then traversed to
- * deal with the exception.
- *
- * If the SEH list is corrupt, then when a C++ exception is thrown the program
- * will abruptly exit with exit code 1. This does not use std::terminate(), so
- * std::set_terminate() is useless to debug this.
- *
- * The SEH list is closely tied to the call stack; entering a function that
- * uses __try{} or most C++ functions will push a new handler onto the front
- * of the list. Returning from the function will remove the handler. Saving
- * and restoring the head node of the SEH list (FS:[0]) per-greenlet is NOT
- * ENOUGH to make SEH or exceptions work.
- *
- * Stack switching breaks SEH because the call stack no longer necessarily
- * matches the SEH list. For example, given greenlet A that switches to
- * greenlet B, at the moment of entering greenlet B, we will have any SEH
- * handlers from greenlet A on the SEH list; greenlet B can then add its own
- * handlers to the SEH list. When greenlet B switches back to greenlet A,
- * greenlet B's handlers would still be on the SEH stack, but when switch()
- * returns control to greenlet A, we have replaced the contents of the stack
- * in memory, so all the address that greenlet B added to the SEH list are now
- * invalid: part of the call stack has been unwound, but the SEH list was out
- * of sync with the call stack. The net effect is that exception handling
- * stops working.
- *
- * Thus, when switching greenlets, we need to be sure that the SEH list
- * matches the effective call stack, "cutting out" any handlers that were
- * pushed by the greenlet that switched out and which are no longer valid.
- *
- * The easiest way to do this is to capture the SEH list at the time the main
- * greenlet for a thread is created, and, when initially starting a greenlet,
- * start a new SEH list for it, which contains nothing but the handler
- * established for the new greenlet itself, with the tail being the handlers
- * for the main greenlet. If we then save and restore the SEH per-greenlet,
- * they won't interfere with each others SEH lists. (No greenlet can unwind
- * the call stack past the handlers established by the main greenlet).
- *
- * By observation, a new thread starts with three SEH handlers on the list. By
- * the time we get around to creating the main greenlet, though, there can be
- * many more, established by transient calls that lead to the creation of the
- * main greenlet. Therefore, 3 is a magic constant telling us when to perform
- * the initial slice.
- *
- * All of this can be debugged using a vectored exception handler, which
- * operates independently of the SEH handler list, and is called first.
- * Walking the SEH list at key points can also be helpful.
- *
- * References:
- * https://en.wikipedia.org/wiki/Win32_Thread_Information_Block
- * https://devblogs.microsoft.com/oldnewthing/20100730-00/?p=13273
- * https://docs.microsoft.com/en-us/cpp/cpp/try-except-statement?view=msvc-160
- * https://docs.microsoft.com/en-us/cpp/cpp/structured-exception-handling-c-cpp?view=msvc-160
- * https://docs.microsoft.com/en-us/windows/win32/debug/structured-exception-handling
- * https://docs.microsoft.com/en-us/windows/win32/debug/using-a-vectored-exception-handler
- * https://bytepointer.com/resources/pietrek_crash_course_depths_of_win32_seh.htm
- */
-#define GREENLET_NEEDS_EXCEPTION_STATE_SAVED
-
-
-typedef struct _GExceptionRegistration {
- struct _GExceptionRegistration* prev;
- void* handler_f;
-} GExceptionRegistration;
-
-static void
-slp_set_exception_state(const void *const seh_state)
-{
- // Because the stack from from which we do this is ALSO a handler, and
- // that one we want to keep, we need to relink the current SEH handler
- // frame to point to this one, cutting out the middle men, as it were.
- //
- // Entering a try block doesn't change the SEH frame, but entering a
- // function containing a try block does.
- GExceptionRegistration* current_seh_state = (GExceptionRegistration*)__readfsdword(FIELD_OFFSET(NT_TIB, ExceptionList));
- current_seh_state->prev = (GExceptionRegistration*)seh_state;
-}
-
-
-static GExceptionRegistration*
-x86_slp_get_third_oldest_handler()
-{
- GExceptionRegistration* a = NULL; /* Closest to the top */
- GExceptionRegistration* b = NULL; /* second */
- GExceptionRegistration* c = NULL;
- GExceptionRegistration* seh_state = (GExceptionRegistration*)__readfsdword(FIELD_OFFSET(NT_TIB, ExceptionList));
- a = b = c = seh_state;
-
- while (seh_state && seh_state != (GExceptionRegistration*)0xFFFFFFFF) {
- if ((void*)seh_state->prev < (void*)100) {
- fprintf(stderr, "\tERROR: Broken SEH chain.\n");
- return NULL;
- }
- a = b;
- b = c;
- c = seh_state;
-
- seh_state = seh_state->prev;
- }
- return a ? a : (b ? b : c);
-}
-
-
-static void*
-slp_get_exception_state()
-{
- // XXX: There appear to be three SEH handlers on the stack already at the
- // start of the thread. Is that a guarantee? Almost certainly not. Yet in
- // all observed cases it has been three. This is consistent with
- // faulthandler off or on, and optimizations off or on. It may not be
- // consistent with other operating system versions, though: we only have
- // CI on one or two versions (don't ask what there are).
- // In theory we could capture the number of handlers on the chain when
- // PyInit__greenlet is called: there are probably only the default
- // handlers at that point (unless we're embedded and people have used
- // __try/__except or a C++ handler)?
- return x86_slp_get_third_oldest_handler();
-}
-
-static int
-slp_switch(void)
-{
- /* MASM syntax is typically reversed from other assemblers.
- It is usually <instruction> <destination> <source>
- */
- int *stackref, stsizediff;
- /* store the structured exception state for this stack */
- DWORD seh_state = __readfsdword(FIELD_OFFSET(NT_TIB, ExceptionList));
- __asm mov stackref, esp;
- /* modify EBX, ESI and EDI in order to get them preserved */
- __asm mov ebx, ebx;
- __asm xchg esi, edi;
- {
- SLP_SAVE_STATE(stackref, stsizediff);
- __asm {
- mov eax, stsizediff
- add esp, eax
- add ebp, eax
- }
- SLP_RESTORE_STATE();
- }
- __writefsdword(FIELD_OFFSET(NT_TIB, ExceptionList), seh_state);
- return 0;
-}
-
-/* re-enable ebp warning and global optimizations. */
-#pragma optimize("", on)
-#pragma warning(default:4731)
-#pragma warning(default:4733) /* disable warning about modifying FS[0] */
-
-
-#endif
-
-/*
- * further self-processing support
- */
-
-/* we have IsBadReadPtr available, so we can peek at objects */
-#define STACKLESS_SPY
-
-#ifdef GREENLET_DEBUG
-
-#define CANNOT_READ_MEM(p, bytes) IsBadReadPtr(p, bytes)
-
-static int IS_ON_STACK(void*p)
-{
- int stackref;
- int stackbase = ((int)&stackref) & 0xfffff000;
- return (int)p >= stackbase && (int)p < stackbase + 0x00100000;
-}
-
-static void
-x86_slp_show_seh_chain()
-{
- GExceptionRegistration* seh_state = (GExceptionRegistration*)__readfsdword(FIELD_OFFSET(NT_TIB, ExceptionList));
- fprintf(stderr, "====== SEH Chain ======\n");
- while (seh_state && seh_state != (GExceptionRegistration*)0xFFFFFFFF) {
- fprintf(stderr, "\tSEH_chain addr: %p handler: %p prev: %p\n",
- seh_state,
- seh_state->handler_f, seh_state->prev);
- if ((void*)seh_state->prev < (void*)100) {
- fprintf(stderr, "\tERROR: Broken chain.\n");
- break;
- }
- seh_state = seh_state->prev;
- }
- fprintf(stderr, "====== End SEH Chain ======\n");
- fflush(NULL);
- return;
-}
-
-//addVectoredExceptionHandler constants:
-//CALL_FIRST means call this exception handler first;
-//CALL_LAST means call this exception handler last
-#define CALL_FIRST 1
-#define CALL_LAST 0
-
-LONG WINAPI
-GreenletVectorHandler(PEXCEPTION_POINTERS ExceptionInfo)
-{
- // We get one of these for every C++ exception, with code
- // E06D7363
- // This is a special value that means "C++ exception from MSVC"
- // https://devblogs.microsoft.com/oldnewthing/20100730-00/?p=13273
- //
- // Install in the module init function with:
- // AddVectoredExceptionHandler(CALL_FIRST, GreenletVectorHandler);
- PEXCEPTION_RECORD ExceptionRecord = ExceptionInfo->ExceptionRecord;
-
- fprintf(stderr,
- "GOT VECTORED EXCEPTION:\n"
- "\tExceptionCode : %p\n"
- "\tExceptionFlags : %p\n"
- "\tExceptionAddr : %p\n"
- "\tNumberparams : %ld\n",
- ExceptionRecord->ExceptionCode,
- ExceptionRecord->ExceptionFlags,
- ExceptionRecord->ExceptionAddress,
- ExceptionRecord->NumberParameters
- );
- if (ExceptionRecord->ExceptionFlags & 1) {
- fprintf(stderr, "\t\tEH_NONCONTINUABLE\n" );
- }
- if (ExceptionRecord->ExceptionFlags & 2) {
- fprintf(stderr, "\t\tEH_UNWINDING\n" );
- }
- if (ExceptionRecord->ExceptionFlags & 4) {
- fprintf(stderr, "\t\tEH_EXIT_UNWIND\n" );
- }
- if (ExceptionRecord->ExceptionFlags & 8) {
- fprintf(stderr, "\t\tEH_STACK_INVALID\n" );
- }
- if (ExceptionRecord->ExceptionFlags & 0x10) {
- fprintf(stderr, "\t\tEH_NESTED_CALL\n" );
- }
- if (ExceptionRecord->ExceptionFlags & 0x20) {
- fprintf(stderr, "\t\tEH_TARGET_UNWIND\n" );
- }
- if (ExceptionRecord->ExceptionFlags & 0x40) {
- fprintf(stderr, "\t\tEH_COLLIDED_UNWIND\n" );
- }
- fprintf(stderr, "\n");
- fflush(NULL);
- for(DWORD i = 0; i < ExceptionRecord->NumberParameters; i++) {
- fprintf(stderr, "\t\t\tParam %ld: %lX\n", i, ExceptionRecord->ExceptionInformation[i]);
- }
-
- if (ExceptionRecord->NumberParameters == 3) {
- fprintf(stderr, "\tAbout to traverse SEH chain\n");
- // C++ Exception records have 3 params.
- x86_slp_show_seh_chain();
- }
-
- return EXCEPTION_CONTINUE_SEARCH;
-}
-
-
-
-
-#endif
diff --git a/venv/lib/python3.11/site-packages/greenlet/platform/switch_x86_unix.h b/venv/lib/python3.11/site-packages/greenlet/platform/switch_x86_unix.h
deleted file mode 100644
index 493fa6b..0000000
--- a/venv/lib/python3.11/site-packages/greenlet/platform/switch_x86_unix.h
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * this is the internal transfer function.
- *
- * HISTORY
- * 3-May-13 Ralf Schmitt <ralf@systemexit.de>
- * Add support for strange GCC caller-save decisions
- * (ported from switch_aarch64_gcc.h)
- * 19-Aug-11 Alexey Borzenkov <snaury@gmail.com>
- * Correctly save ebp, ebx and cw
- * 07-Sep-05 (py-dev mailing list discussion)
- * removed 'ebx' from the register-saved. !!!! WARNING !!!!
- * It means that this file can no longer be compiled statically!
- * It is now only suitable as part of a dynamic library!
- * 24-Nov-02 Christian Tismer <tismer@tismer.com>
- * needed to add another magic constant to insure
- * that f in slp_eval_frame(PyFrameObject *f)
- * STACK_REFPLUS will probably be 1 in most cases.
- * gets included into the saved stack area.
- * 17-Sep-02 Christian Tismer <tismer@tismer.com>
- * after virtualizing stack save/restore, the
- * stack size shrunk a bit. Needed to introduce
- * an adjustment STACK_MAGIC per platform.
- * 15-Sep-02 Gerd Woetzel <gerd.woetzel@GMD.DE>
- * slightly changed framework for spark
- * 31-Avr-02 Armin Rigo <arigo@ulb.ac.be>
- * Added ebx, esi and edi register-saves.
- * 01-Mar-02 Samual M. Rushing <rushing@ironport.com>
- * Ported from i386.
- */
-
-#define STACK_REFPLUS 1
-
-#ifdef SLP_EVAL
-
-/* #define STACK_MAGIC 3 */
-/* the above works fine with gcc 2.96, but 2.95.3 wants this */
-#define STACK_MAGIC 0
-
-#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)
-# define ATTR_NOCLONE __attribute__((noclone))
-#else
-# define ATTR_NOCLONE
-#endif
-
-static int
-slp_switch(void)
-{
- int err;
-#ifdef _WIN32
- void *seh;
-#endif
- void *ebp, *ebx;
- unsigned short cw;
- int *stackref, stsizediff;
- __asm__ volatile ("" : : : "esi", "edi");
- __asm__ volatile ("fstcw %0" : "=m" (cw));
- __asm__ volatile ("movl %%ebp, %0" : "=m" (ebp));
- __asm__ volatile ("movl %%ebx, %0" : "=m" (ebx));
-#ifdef _WIN32
- __asm__ volatile (
- "movl %%fs:0x0, %%eax\n"
- "movl %%eax, %0\n"
- : "=m" (seh)
- :
- : "eax");
-#endif
- __asm__ ("movl %%esp, %0" : "=g" (stackref));
- {
- SLP_SAVE_STATE(stackref, stsizediff);
- __asm__ volatile (
- "addl %0, %%esp\n"
- "addl %0, %%ebp\n"
- :
- : "r" (stsizediff)
- );
- SLP_RESTORE_STATE();
- __asm__ volatile ("xorl %%eax, %%eax" : "=a" (err));
- }
-#ifdef _WIN32
- __asm__ volatile (
- "movl %0, %%eax\n"
- "movl %%eax, %%fs:0x0\n"
- :
- : "m" (seh)
- : "eax");
-#endif
- __asm__ volatile ("movl %0, %%ebx" : : "m" (ebx));
- __asm__ volatile ("movl %0, %%ebp" : : "m" (ebp));
- __asm__ volatile ("fldcw %0" : : "m" (cw));
- __asm__ volatile ("" : : : "esi", "edi");
- return err;
-}
-
-#endif
-
-/*
- * further self-processing support
- */
-
-/*
- * if you want to add self-inspection tools, place them
- * here. See the x86_msvc for the necessary defines.
- * These features are highly experimental und not
- * essential yet.
- */
diff --git a/venv/lib/python3.11/site-packages/greenlet/slp_platformselect.h b/venv/lib/python3.11/site-packages/greenlet/slp_platformselect.h
deleted file mode 100644
index c959f0f..0000000
--- a/venv/lib/python3.11/site-packages/greenlet/slp_platformselect.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Platform Selection for Stackless Python
- */
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#if defined(MS_WIN32) && !defined(MS_WIN64) && defined(_M_IX86) && defined(_MSC_VER)
-# include "platform/switch_x86_msvc.h" /* MS Visual Studio on X86 */
-#elif defined(MS_WIN64) && defined(_M_X64) && defined(_MSC_VER) || defined(__MINGW64__)
-# include "platform/switch_x64_msvc.h" /* MS Visual Studio on X64 */
-#elif defined(MS_WIN64) && defined(_M_ARM64)
-# include "platform/switch_arm64_msvc.h" /* MS Visual Studio on ARM64 */
-#elif defined(__GNUC__) && defined(__amd64__) && defined(__ILP32__)
-# include "platform/switch_x32_unix.h" /* gcc on amd64 with x32 ABI */
-#elif defined(__GNUC__) && defined(__amd64__)
-# include "platform/switch_amd64_unix.h" /* gcc on amd64 */
-#elif defined(__GNUC__) && defined(__i386__)
-# include "platform/switch_x86_unix.h" /* gcc on X86 */
-#elif defined(__GNUC__) && defined(__powerpc64__) && (defined(__linux__) || defined(__FreeBSD__))
-# include "platform/switch_ppc64_linux.h" /* gcc on PowerPC 64-bit */
-#elif defined(__GNUC__) && defined(__PPC__) && (defined(__linux__) || defined(__FreeBSD__))
-# include "platform/switch_ppc_linux.h" /* gcc on PowerPC */
-#elif defined(__GNUC__) && defined(__ppc__) && defined(__APPLE__)
-# include "platform/switch_ppc_macosx.h" /* Apple MacOS X on PowerPC */
-#elif defined(__GNUC__) && defined(__powerpc64__) && defined(_AIX)
-# include "platform/switch_ppc64_aix.h" /* gcc on AIX/PowerPC 64-bit */
-#elif defined(__GNUC__) && defined(_ARCH_PPC) && defined(_AIX)
-# include "platform/switch_ppc_aix.h" /* gcc on AIX/PowerPC */
-#elif defined(__GNUC__) && defined(sparc)
-# include "platform/switch_sparc_sun_gcc.h" /* SunOS sparc with gcc */
-#elif defined(__SUNPRO_C) && defined(sparc) && defined(sun)
-# iiclude "platform/switch_sparc_sun_gcc.h" /* SunStudio on amd64 */
-#elif defined(__SUNPRO_C) && defined(__amd64__) && defined(sun)
-# include "platform/switch_amd64_unix.h" /* SunStudio on amd64 */
-#elif defined(__SUNPRO_C) && defined(__i386__) && defined(sun)
-# include "platform/switch_x86_unix.h" /* SunStudio on x86 */
-#elif defined(__GNUC__) && defined(__s390__) && defined(__linux__)
-# include "platform/switch_s390_unix.h" /* Linux/S390 */
-#elif defined(__GNUC__) && defined(__s390x__) && defined(__linux__)
-# include "platform/switch_s390_unix.h" /* Linux/S390 zSeries (64-bit) */
-#elif defined(__GNUC__) && defined(__arm__)
-# ifdef __APPLE__
-# include <TargetConditionals.h>
-# endif
-# if TARGET_OS_IPHONE
-# include "platform/switch_arm32_ios.h" /* iPhone OS on arm32 */
-# else
-# include "platform/switch_arm32_gcc.h" /* gcc using arm32 */
-# endif
-#elif defined(__GNUC__) && defined(__mips__) && defined(__linux__)
-# include "platform/switch_mips_unix.h" /* Linux/MIPS */
-#elif defined(__GNUC__) && defined(__aarch64__)
-# include "platform/switch_aarch64_gcc.h" /* Aarch64 ABI */
-#elif defined(__GNUC__) && defined(__mc68000__)
-# include "platform/switch_m68k_gcc.h" /* gcc on m68k */
-#elif defined(__GNUC__) && defined(__csky__)
-#include "platform/switch_csky_gcc.h" /* gcc on csky */
-# elif defined(__GNUC__) && defined(__riscv)
-# include "platform/switch_riscv_unix.h" /* gcc on RISC-V */
-#elif defined(__GNUC__) && defined(__alpha__)
-# include "platform/switch_alpha_unix.h" /* gcc on DEC Alpha */
-#elif defined(MS_WIN32) && defined(__llvm__) && defined(__aarch64__)
-# include "platform/switch_aarch64_gcc.h" /* LLVM Aarch64 ABI for Windows */
-#elif defined(__GNUC__) && defined(__loongarch64) && defined(__linux__)
-# include "platform/switch_loongarch64_linux.h" /* LoongArch64 */
-#endif
-
-#ifdef __cplusplus
-};
-#endif
diff --git a/venv/lib/python3.11/site-packages/greenlet/tests/__init__.py b/venv/lib/python3.11/site-packages/greenlet/tests/__init__.py
deleted file mode 100644
index e249e35..0000000
--- a/venv/lib/python3.11/site-packages/greenlet/tests/__init__.py
+++ /dev/null
@@ -1,237 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-Tests for greenlet.
-
-"""
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import sys
-import unittest
-
-from gc import collect
-from gc import get_objects
-from threading import active_count as active_thread_count
-from time import sleep
-from time import time
-
-import psutil
-
-from greenlet import greenlet as RawGreenlet
-from greenlet import getcurrent
-
-from greenlet._greenlet import get_pending_cleanup_count
-from greenlet._greenlet import get_total_main_greenlets
-
-from . import leakcheck
-
-PY312 = sys.version_info[:2] >= (3, 12)
-WIN = sys.platform.startswith("win")
-
-class TestCaseMetaClass(type):
- # wrap each test method with
- # a) leak checks
- def __new__(cls, classname, bases, classDict):
- # pylint and pep8 fight over what this should be called (mcs or cls).
- # pylint gets it right, but we can't scope disable pep8, so we go with
- # its convention.
- # pylint: disable=bad-mcs-classmethod-argument
- check_totalrefcount = True
-
- # Python 3: must copy, we mutate the classDict. Interestingly enough,
- # it doesn't actually error out, but under 3.6 we wind up wrapping
- # and re-wrapping the same items over and over and over.
- for key, value in list(classDict.items()):
- if key.startswith('test') and callable(value):
- classDict.pop(key)
- if check_totalrefcount:
- value = leakcheck.wrap_refcount(value)
- classDict[key] = value
- return type.__new__(cls, classname, bases, classDict)
-
-
-class TestCase(TestCaseMetaClass(
- "NewBase",
- (unittest.TestCase,),
- {})):
-
- cleanup_attempt_sleep_duration = 0.001
- cleanup_max_sleep_seconds = 1
-
- def wait_for_pending_cleanups(self,
- initial_active_threads=None,
- initial_main_greenlets=None):
- initial_active_threads = initial_active_threads or self.threads_before_test
- initial_main_greenlets = initial_main_greenlets or self.main_greenlets_before_test
- sleep_time = self.cleanup_attempt_sleep_duration
- # NOTE: This is racy! A Python-level thread object may be dead
- # and gone, but the C thread may not yet have fired its
- # destructors and added to the queue. There's no particular
- # way to know that's about to happen. We try to watch the
- # Python threads to make sure they, at least, have gone away.
- # Counting the main greenlets, which we can easily do deterministically,
- # also helps.
-
- # Always sleep at least once to let other threads run
- sleep(sleep_time)
- quit_after = time() + self.cleanup_max_sleep_seconds
- # TODO: We could add an API that calls us back when a particular main greenlet is deleted?
- # It would have to drop the GIL
- while (
- get_pending_cleanup_count()
- or active_thread_count() > initial_active_threads
- or (not self.expect_greenlet_leak
- and get_total_main_greenlets() > initial_main_greenlets)):
- sleep(sleep_time)
- if time() > quit_after:
- print("Time limit exceeded.")
- print("Threads: Waiting for only", initial_active_threads,
- "-->", active_thread_count())
- print("MGlets : Waiting for only", initial_main_greenlets,
- "-->", get_total_main_greenlets())
- break
- collect()
-
- def count_objects(self, kind=list, exact_kind=True):
- # pylint:disable=unidiomatic-typecheck
- # Collect the garbage.
- for _ in range(3):
- collect()
- if exact_kind:
- return sum(
- 1
- for x in get_objects()
- if type(x) is kind
- )
- # instances
- return sum(
- 1
- for x in get_objects()
- if isinstance(x, kind)
- )
-
- greenlets_before_test = 0
- threads_before_test = 0
- main_greenlets_before_test = 0
- expect_greenlet_leak = False
-
- def count_greenlets(self):
- """
- Find all the greenlets and subclasses tracked by the GC.
- """
- return self.count_objects(RawGreenlet, False)
-
- def setUp(self):
- # Ensure the main greenlet exists, otherwise the first test
- # gets a false positive leak
- super().setUp()
- getcurrent()
- self.threads_before_test = active_thread_count()
- self.main_greenlets_before_test = get_total_main_greenlets()
- self.wait_for_pending_cleanups(self.threads_before_test, self.main_greenlets_before_test)
- self.greenlets_before_test = self.count_greenlets()
-
- def tearDown(self):
- if getattr(self, 'skipTearDown', False):
- return
-
- self.wait_for_pending_cleanups(self.threads_before_test, self.main_greenlets_before_test)
- super().tearDown()
-
- def get_expected_returncodes_for_aborted_process(self):
- import signal
- # The child should be aborted in an unusual way. On POSIX
- # platforms, this is done with abort() and signal.SIGABRT,
- # which is reflected in a negative return value; however, on
- # Windows, even though we observe the child print "Fatal
- # Python error: Aborted" and in older versions of the C
- # runtime "This application has requested the Runtime to
- # terminate it in an unusual way," it always has an exit code
- # of 3. This is interesting because 3 is the error code for
- # ERROR_PATH_NOT_FOUND; BUT: the C runtime abort() function
- # also uses this code.
- #
- # If we link to the static C library on Windows, the error
- # code changes to '0xc0000409' (hex(3221226505)), which
- # apparently is STATUS_STACK_BUFFER_OVERRUN; but "What this
- # means is that nowadays when you get a
- # STATUS_STACK_BUFFER_OVERRUN, it doesn’t actually mean that
- # there is a stack buffer overrun. It just means that the
- # application decided to terminate itself with great haste."
- #
- #
- # On windows, we've also seen '0xc0000005' (hex(3221225477)).
- # That's "Access Violation"
- #
- # See
- # https://devblogs.microsoft.com/oldnewthing/20110519-00/?p=10623
- # and
- # https://docs.microsoft.com/en-us/previous-versions/k089yyh0(v=vs.140)?redirectedfrom=MSDN
- # and
- # https://devblogs.microsoft.com/oldnewthing/20190108-00/?p=100655
- expected_exit = (
- -signal.SIGABRT,
- # But beginning on Python 3.11, the faulthandler
- # that prints the C backtraces sometimes segfaults after
- # reporting the exception but before printing the stack.
- # This has only been seen on linux/gcc.
- -signal.SIGSEGV,
- ) if not WIN else (
- 3,
- 0xc0000409,
- 0xc0000005,
- )
- return expected_exit
-
- def get_process_uss(self):
- """
- Return the current process's USS in bytes.
-
- uss is available on Linux, macOS, Windows. Also known as
- "Unique Set Size", this is the memory which is unique to a
- process and which would be freed if the process was terminated
- right now.
-
- If this is not supported by ``psutil``, this raises the
- :exc:`unittest.SkipTest` exception.
- """
- try:
- return psutil.Process().memory_full_info().uss
- except AttributeError as e:
- raise unittest.SkipTest("uss not supported") from e
-
- def run_script(self, script_name, show_output=True):
- import subprocess
- import os
- script = os.path.join(
- os.path.dirname(__file__),
- script_name,
- )
-
- try:
- return subprocess.check_output([sys.executable, script],
- encoding='utf-8',
- stderr=subprocess.STDOUT)
- except subprocess.CalledProcessError as ex:
- if show_output:
- print('-----')
- print('Failed to run script', script)
- print('~~~~~')
- print(ex.output)
- print('------')
- raise
-
-
- def assertScriptRaises(self, script_name, exitcodes=None):
- import subprocess
- with self.assertRaises(subprocess.CalledProcessError) as exc:
- output = self.run_script(script_name, show_output=False)
- __traceback_info__ = output
- # We're going to fail the assertion if we get here, at least
- # preserve the output in the traceback.
-
- if exitcodes is None:
- exitcodes = self.get_expected_returncodes_for_aborted_process()
- self.assertIn(exc.exception.returncode, exitcodes)
- return exc.exception
diff --git a/venv/lib/python3.11/site-packages/greenlet/tests/__pycache__/__init__.cpython-311.pyc b/venv/lib/python3.11/site-packages/greenlet/tests/__pycache__/__init__.cpython-311.pyc
deleted file mode 100644
index 245565c..0000000
--- a/venv/lib/python3.11/site-packages/greenlet/tests/__pycache__/__init__.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/greenlet/tests/__pycache__/fail_clearing_run_switches.cpython-311.pyc b/venv/lib/python3.11/site-packages/greenlet/tests/__pycache__/fail_clearing_run_switches.cpython-311.pyc
deleted file mode 100644
index f8ca571..0000000
--- a/venv/lib/python3.11/site-packages/greenlet/tests/__pycache__/fail_clearing_run_switches.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/greenlet/tests/__pycache__/fail_cpp_exception.cpython-311.pyc b/venv/lib/python3.11/site-packages/greenlet/tests/__pycache__/fail_cpp_exception.cpython-311.pyc
deleted file mode 100644
index 1293a2e..0000000
--- a/venv/lib/python3.11/site-packages/greenlet/tests/__pycache__/fail_cpp_exception.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/greenlet/tests/__pycache__/fail_initialstub_already_started.cpython-311.pyc b/venv/lib/python3.11/site-packages/greenlet/tests/__pycache__/fail_initialstub_already_started.cpython-311.pyc
deleted file mode 100644
index 12af9c5..0000000
--- a/venv/lib/python3.11/site-packages/greenlet/tests/__pycache__/fail_initialstub_already_started.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/greenlet/tests/__pycache__/fail_slp_switch.cpython-311.pyc b/venv/lib/python3.11/site-packages/greenlet/tests/__pycache__/fail_slp_switch.cpython-311.pyc
deleted file mode 100644
index 41fa814..0000000
--- a/venv/lib/python3.11/site-packages/greenlet/tests/__pycache__/fail_slp_switch.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/greenlet/tests/__pycache__/fail_switch_three_greenlets.cpython-311.pyc b/venv/lib/python3.11/site-packages/greenlet/tests/__pycache__/fail_switch_three_greenlets.cpython-311.pyc
deleted file mode 100644
index 73d0e65..0000000
--- a/venv/lib/python3.11/site-packages/greenlet/tests/__pycache__/fail_switch_three_greenlets.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/greenlet/tests/__pycache__/fail_switch_three_greenlets2.cpython-311.pyc b/venv/lib/python3.11/site-packages/greenlet/tests/__pycache__/fail_switch_three_greenlets2.cpython-311.pyc
deleted file mode 100644
index dcdbc02..0000000
--- a/venv/lib/python3.11/site-packages/greenlet/tests/__pycache__/fail_switch_three_greenlets2.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/greenlet/tests/__pycache__/fail_switch_two_greenlets.cpython-311.pyc b/venv/lib/python3.11/site-packages/greenlet/tests/__pycache__/fail_switch_two_greenlets.cpython-311.pyc
deleted file mode 100644
index 97be12a..0000000
--- a/venv/lib/python3.11/site-packages/greenlet/tests/__pycache__/fail_switch_two_greenlets.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/greenlet/tests/__pycache__/leakcheck.cpython-311.pyc b/venv/lib/python3.11/site-packages/greenlet/tests/__pycache__/leakcheck.cpython-311.pyc
deleted file mode 100644
index 7a2616e..0000000
--- a/venv/lib/python3.11/site-packages/greenlet/tests/__pycache__/leakcheck.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/greenlet/tests/__pycache__/test_contextvars.cpython-311.pyc b/venv/lib/python3.11/site-packages/greenlet/tests/__pycache__/test_contextvars.cpython-311.pyc
deleted file mode 100644
index afb0e23..0000000
--- a/venv/lib/python3.11/site-packages/greenlet/tests/__pycache__/test_contextvars.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/greenlet/tests/__pycache__/test_cpp.cpython-311.pyc b/venv/lib/python3.11/site-packages/greenlet/tests/__pycache__/test_cpp.cpython-311.pyc
deleted file mode 100644
index 3f24186..0000000
--- a/venv/lib/python3.11/site-packages/greenlet/tests/__pycache__/test_cpp.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/greenlet/tests/__pycache__/test_extension_interface.cpython-311.pyc b/venv/lib/python3.11/site-packages/greenlet/tests/__pycache__/test_extension_interface.cpython-311.pyc
deleted file mode 100644
index 987e490..0000000
--- a/venv/lib/python3.11/site-packages/greenlet/tests/__pycache__/test_extension_interface.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/greenlet/tests/__pycache__/test_gc.cpython-311.pyc b/venv/lib/python3.11/site-packages/greenlet/tests/__pycache__/test_gc.cpython-311.pyc
deleted file mode 100644
index c4edf24..0000000
--- a/venv/lib/python3.11/site-packages/greenlet/tests/__pycache__/test_gc.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/greenlet/tests/__pycache__/test_generator.cpython-311.pyc b/venv/lib/python3.11/site-packages/greenlet/tests/__pycache__/test_generator.cpython-311.pyc
deleted file mode 100644
index 936decb..0000000
--- a/venv/lib/python3.11/site-packages/greenlet/tests/__pycache__/test_generator.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/greenlet/tests/__pycache__/test_generator_nested.cpython-311.pyc b/venv/lib/python3.11/site-packages/greenlet/tests/__pycache__/test_generator_nested.cpython-311.pyc
deleted file mode 100644
index fa8ca9c..0000000
--- a/venv/lib/python3.11/site-packages/greenlet/tests/__pycache__/test_generator_nested.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/greenlet/tests/__pycache__/test_greenlet.cpython-311.pyc b/venv/lib/python3.11/site-packages/greenlet/tests/__pycache__/test_greenlet.cpython-311.pyc
deleted file mode 100644
index 6f4f510..0000000
--- a/venv/lib/python3.11/site-packages/greenlet/tests/__pycache__/test_greenlet.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/greenlet/tests/__pycache__/test_greenlet_trash.cpython-311.pyc b/venv/lib/python3.11/site-packages/greenlet/tests/__pycache__/test_greenlet_trash.cpython-311.pyc
deleted file mode 100644
index e40225d..0000000
--- a/venv/lib/python3.11/site-packages/greenlet/tests/__pycache__/test_greenlet_trash.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/greenlet/tests/__pycache__/test_leaks.cpython-311.pyc b/venv/lib/python3.11/site-packages/greenlet/tests/__pycache__/test_leaks.cpython-311.pyc
deleted file mode 100644
index 88e931a..0000000
--- a/venv/lib/python3.11/site-packages/greenlet/tests/__pycache__/test_leaks.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/greenlet/tests/__pycache__/test_stack_saved.cpython-311.pyc b/venv/lib/python3.11/site-packages/greenlet/tests/__pycache__/test_stack_saved.cpython-311.pyc
deleted file mode 100644
index b3f464d..0000000
--- a/venv/lib/python3.11/site-packages/greenlet/tests/__pycache__/test_stack_saved.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/greenlet/tests/__pycache__/test_throw.cpython-311.pyc b/venv/lib/python3.11/site-packages/greenlet/tests/__pycache__/test_throw.cpython-311.pyc
deleted file mode 100644
index 2427360..0000000
--- a/venv/lib/python3.11/site-packages/greenlet/tests/__pycache__/test_throw.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/greenlet/tests/__pycache__/test_tracing.cpython-311.pyc b/venv/lib/python3.11/site-packages/greenlet/tests/__pycache__/test_tracing.cpython-311.pyc
deleted file mode 100644
index a488241..0000000
--- a/venv/lib/python3.11/site-packages/greenlet/tests/__pycache__/test_tracing.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/greenlet/tests/__pycache__/test_version.cpython-311.pyc b/venv/lib/python3.11/site-packages/greenlet/tests/__pycache__/test_version.cpython-311.pyc
deleted file mode 100644
index 16d09c1..0000000
--- a/venv/lib/python3.11/site-packages/greenlet/tests/__pycache__/test_version.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/greenlet/tests/__pycache__/test_weakref.cpython-311.pyc b/venv/lib/python3.11/site-packages/greenlet/tests/__pycache__/test_weakref.cpython-311.pyc
deleted file mode 100644
index ba0b403..0000000
--- a/venv/lib/python3.11/site-packages/greenlet/tests/__pycache__/test_weakref.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/greenlet/tests/_test_extension.c b/venv/lib/python3.11/site-packages/greenlet/tests/_test_extension.c
deleted file mode 100644
index 05e81c0..0000000
--- a/venv/lib/python3.11/site-packages/greenlet/tests/_test_extension.c
+++ /dev/null
@@ -1,231 +0,0 @@
-/* This is a set of functions used by test_extension_interface.py to test the
- * Greenlet C API.
- */
-
-#include "../greenlet.h"
-
-#ifndef Py_RETURN_NONE
-# define Py_RETURN_NONE return Py_INCREF(Py_None), Py_None
-#endif
-
-#define TEST_MODULE_NAME "_test_extension"
-
-static PyObject*
-test_switch(PyObject* self, PyObject* greenlet)
-{
- PyObject* result = NULL;
-
- if (greenlet == NULL || !PyGreenlet_Check(greenlet)) {
- PyErr_BadArgument();
- return NULL;
- }
-
- result = PyGreenlet_Switch((PyGreenlet*)greenlet, NULL, NULL);
- if (result == NULL) {
- if (!PyErr_Occurred()) {
- PyErr_SetString(PyExc_AssertionError,
- "greenlet.switch() failed for some reason.");
- }
- return NULL;
- }
- Py_INCREF(result);
- return result;
-}
-
-static PyObject*
-test_switch_kwargs(PyObject* self, PyObject* args, PyObject* kwargs)
-{
- PyGreenlet* g = NULL;
- PyObject* result = NULL;
-
- PyArg_ParseTuple(args, "O!", &PyGreenlet_Type, &g);
-
- if (g == NULL || !PyGreenlet_Check(g)) {
- PyErr_BadArgument();
- return NULL;
- }
-
- result = PyGreenlet_Switch(g, NULL, kwargs);
- if (result == NULL) {
- if (!PyErr_Occurred()) {
- PyErr_SetString(PyExc_AssertionError,
- "greenlet.switch() failed for some reason.");
- }
- return NULL;
- }
- Py_XINCREF(result);
- return result;
-}
-
-static PyObject*
-test_getcurrent(PyObject* self)
-{
- PyGreenlet* g = PyGreenlet_GetCurrent();
- if (g == NULL || !PyGreenlet_Check(g) || !PyGreenlet_ACTIVE(g)) {
- PyErr_SetString(PyExc_AssertionError,
- "getcurrent() returned an invalid greenlet");
- Py_XDECREF(g);
- return NULL;
- }
- Py_DECREF(g);
- Py_RETURN_NONE;
-}
-
-static PyObject*
-test_setparent(PyObject* self, PyObject* arg)
-{
- PyGreenlet* current;
- PyGreenlet* greenlet = NULL;
-
- if (arg == NULL || !PyGreenlet_Check(arg)) {
- PyErr_BadArgument();
- return NULL;
- }
- if ((current = PyGreenlet_GetCurrent()) == NULL) {
- return NULL;
- }
- greenlet = (PyGreenlet*)arg;
- if (PyGreenlet_SetParent(greenlet, current)) {
- Py_DECREF(current);
- return NULL;
- }
- Py_DECREF(current);
- if (PyGreenlet_Switch(greenlet, NULL, NULL) == NULL) {
- return NULL;
- }
- Py_RETURN_NONE;
-}
-
-static PyObject*
-test_new_greenlet(PyObject* self, PyObject* callable)
-{
- PyObject* result = NULL;
- PyGreenlet* greenlet = PyGreenlet_New(callable, NULL);
-
- if (!greenlet) {
- return NULL;
- }
-
- result = PyGreenlet_Switch(greenlet, NULL, NULL);
- Py_CLEAR(greenlet);
- if (result == NULL) {
- return NULL;
- }
-
- Py_INCREF(result);
- return result;
-}
-
-static PyObject*
-test_raise_dead_greenlet(PyObject* self)
-{
- PyErr_SetString(PyExc_GreenletExit, "test GreenletExit exception.");
- return NULL;
-}
-
-static PyObject*
-test_raise_greenlet_error(PyObject* self)
-{
- PyErr_SetString(PyExc_GreenletError, "test greenlet.error exception");
- return NULL;
-}
-
-static PyObject*
-test_throw(PyObject* self, PyGreenlet* g)
-{
- const char msg[] = "take that sucka!";
- PyObject* msg_obj = Py_BuildValue("s", msg);
- PyGreenlet_Throw(g, PyExc_ValueError, msg_obj, NULL);
- Py_DECREF(msg_obj);
- if (PyErr_Occurred()) {
- return NULL;
- }
- Py_RETURN_NONE;
-}
-
-static PyObject*
-test_throw_exact(PyObject* self, PyObject* args)
-{
- PyGreenlet* g = NULL;
- PyObject* typ = NULL;
- PyObject* val = NULL;
- PyObject* tb = NULL;
-
- if (!PyArg_ParseTuple(args, "OOOO:throw", &g, &typ, &val, &tb)) {
- return NULL;
- }
-
- PyGreenlet_Throw(g, typ, val, tb);
- if (PyErr_Occurred()) {
- return NULL;
- }
- Py_RETURN_NONE;
-}
-
-static PyMethodDef test_methods[] = {
- {"test_switch",
- (PyCFunction)test_switch,
- METH_O,
- "Switch to the provided greenlet sending provided arguments, and \n"
- "return the results."},
- {"test_switch_kwargs",
- (PyCFunction)test_switch_kwargs,
- METH_VARARGS | METH_KEYWORDS,
- "Switch to the provided greenlet sending the provided keyword args."},
- {"test_getcurrent",
- (PyCFunction)test_getcurrent,
- METH_NOARGS,
- "Test PyGreenlet_GetCurrent()"},
- {"test_setparent",
- (PyCFunction)test_setparent,
- METH_O,
- "Se the parent of the provided greenlet and switch to it."},
- {"test_new_greenlet",
- (PyCFunction)test_new_greenlet,
- METH_O,
- "Test PyGreenlet_New()"},
- {"test_raise_dead_greenlet",
- (PyCFunction)test_raise_dead_greenlet,
- METH_NOARGS,
- "Just raise greenlet.GreenletExit"},
- {"test_raise_greenlet_error",
- (PyCFunction)test_raise_greenlet_error,
- METH_NOARGS,
- "Just raise greenlet.error"},
- {"test_throw",
- (PyCFunction)test_throw,
- METH_O,
- "Throw a ValueError at the provided greenlet"},
- {"test_throw_exact",
- (PyCFunction)test_throw_exact,
- METH_VARARGS,
- "Throw exactly the arguments given at the provided greenlet"},
- {NULL, NULL, 0, NULL}
-};
-
-
-#define INITERROR return NULL
-
-static struct PyModuleDef moduledef = {PyModuleDef_HEAD_INIT,
- TEST_MODULE_NAME,
- NULL,
- 0,
- test_methods,
- NULL,
- NULL,
- NULL,
- NULL};
-
-PyMODINIT_FUNC
-PyInit__test_extension(void)
-{
- PyObject* module = NULL;
- module = PyModule_Create(&moduledef);
-
- if (module == NULL) {
- return NULL;
- }
-
- PyGreenlet_Import();
- return module;
-}
diff --git a/venv/lib/python3.11/site-packages/greenlet/tests/_test_extension.cpython-311-x86_64-linux-gnu.so b/venv/lib/python3.11/site-packages/greenlet/tests/_test_extension.cpython-311-x86_64-linux-gnu.so
deleted file mode 100755
index 2c7fff0..0000000
--- a/venv/lib/python3.11/site-packages/greenlet/tests/_test_extension.cpython-311-x86_64-linux-gnu.so
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/greenlet/tests/_test_extension_cpp.cpp b/venv/lib/python3.11/site-packages/greenlet/tests/_test_extension_cpp.cpp
deleted file mode 100644
index 5cbe6a7..0000000
--- a/venv/lib/python3.11/site-packages/greenlet/tests/_test_extension_cpp.cpp
+++ /dev/null
@@ -1,226 +0,0 @@
-/* This is a set of functions used to test C++ exceptions are not
- * broken during greenlet switches
- */
-
-#include "../greenlet.h"
-#include "../greenlet_compiler_compat.hpp"
-#include <exception>
-#include <stdexcept>
-
-struct exception_t {
- int depth;
- exception_t(int depth) : depth(depth) {}
-};
-
-/* Functions are called via pointers to prevent inlining */
-static void (*p_test_exception_throw_nonstd)(int depth);
-static void (*p_test_exception_throw_std)();
-static PyObject* (*p_test_exception_switch_recurse)(int depth, int left);
-
-static void
-test_exception_throw_nonstd(int depth)
-{
- throw exception_t(depth);
-}
-
-static void
-test_exception_throw_std()
-{
- throw std::runtime_error("Thrown from an extension.");
-}
-
-static PyObject*
-test_exception_switch_recurse(int depth, int left)
-{
- if (left > 0) {
- return p_test_exception_switch_recurse(depth, left - 1);
- }
-
- PyObject* result = NULL;
- PyGreenlet* self = PyGreenlet_GetCurrent();
- if (self == NULL)
- return NULL;
-
- try {
- if (PyGreenlet_Switch(PyGreenlet_GET_PARENT(self), NULL, NULL) == NULL) {
- Py_DECREF(self);
- return NULL;
- }
- p_test_exception_throw_nonstd(depth);
- PyErr_SetString(PyExc_RuntimeError,
- "throwing C++ exception didn't work");
- }
- catch (const exception_t& e) {
- if (e.depth != depth)
- PyErr_SetString(PyExc_AssertionError, "depth mismatch");
- else
- result = PyLong_FromLong(depth);
- }
- catch (...) {
- PyErr_SetString(PyExc_RuntimeError, "unexpected C++ exception");
- }
-
- Py_DECREF(self);
- return result;
-}
-
-/* test_exception_switch(int depth)
- * - recurses depth times
- * - switches to parent inside try/catch block
- * - throws an exception that (expected to be caught in the same function)
- * - verifies depth matches (exceptions shouldn't be caught in other greenlets)
- */
-static PyObject*
-test_exception_switch(PyObject* UNUSED(self), PyObject* args)
-{
- int depth;
- if (!PyArg_ParseTuple(args, "i", &depth))
- return NULL;
- return p_test_exception_switch_recurse(depth, depth);
-}
-
-
-static PyObject*
-py_test_exception_throw_nonstd(PyObject* self, PyObject* args)
-{
- if (!PyArg_ParseTuple(args, ""))
- return NULL;
- p_test_exception_throw_nonstd(0);
- PyErr_SetString(PyExc_AssertionError, "unreachable code running after throw");
- return NULL;
-}
-
-static PyObject*
-py_test_exception_throw_std(PyObject* self, PyObject* args)
-{
- if (!PyArg_ParseTuple(args, ""))
- return NULL;
- p_test_exception_throw_std();
- PyErr_SetString(PyExc_AssertionError, "unreachable code running after throw");
- return NULL;
-}
-
-static PyObject*
-py_test_call(PyObject* self, PyObject* arg)
-{
- PyObject* noargs = PyTuple_New(0);
- PyObject* ret = PyObject_Call(arg, noargs, nullptr);
- Py_DECREF(noargs);
- return ret;
-}
-
-
-
-/* test_exception_switch_and_do_in_g2(g2func)
- * - creates new greenlet g2 to run g2func
- * - switches to g2 inside try/catch block
- * - verifies that no exception has been caught
- *
- * it is used together with test_exception_throw to verify that unhandled
- * exceptions thrown in one greenlet do not propagate to other greenlet nor
- * segfault the process.
- */
-static PyObject*
-test_exception_switch_and_do_in_g2(PyObject* self, PyObject* args)
-{
- PyObject* g2func = NULL;
- PyObject* result = NULL;
-
- if (!PyArg_ParseTuple(args, "O", &g2func))
- return NULL;
- PyGreenlet* g2 = PyGreenlet_New(g2func, NULL);
- if (!g2) {
- return NULL;
- }
-
- try {
- result = PyGreenlet_Switch(g2, NULL, NULL);
- if (!result) {
- return NULL;
- }
- }
- catch (const exception_t& e) {
- /* if we are here the memory can be already corrupted and the program
- * might crash before below py-level exception might become printed.
- * -> print something to stderr to make it clear that we had entered
- * this catch block.
- * See comments in inner_bootstrap()
- */
-#if defined(WIN32) || defined(_WIN32)
- fprintf(stderr, "C++ exception unexpectedly caught in g1\n");
- PyErr_SetString(PyExc_AssertionError, "C++ exception unexpectedly caught in g1");
- Py_XDECREF(result);
- return NULL;
-#else
- throw;
-#endif
- }
-
- Py_XDECREF(result);
- Py_RETURN_NONE;
-}
-
-static PyMethodDef test_methods[] = {
- {"test_exception_switch",
- (PyCFunction)&test_exception_switch,
- METH_VARARGS,
- "Switches to parent twice, to test exception handling and greenlet "
- "switching."},
- {"test_exception_switch_and_do_in_g2",
- (PyCFunction)&test_exception_switch_and_do_in_g2,
- METH_VARARGS,
- "Creates new greenlet g2 to run g2func and switches to it inside try/catch "
- "block. Used together with test_exception_throw to verify that unhandled "
- "C++ exceptions thrown in a greenlet doe not corrupt memory."},
- {"test_exception_throw_nonstd",
- (PyCFunction)&py_test_exception_throw_nonstd,
- METH_VARARGS,
- "Throws non-standard C++ exception. Calling this function directly should abort the process."
- },
- {"test_exception_throw_std",
- (PyCFunction)&py_test_exception_throw_std,
- METH_VARARGS,
- "Throws standard C++ exception. Calling this function directly should abort the process."
- },
- {"test_call",
- (PyCFunction)&py_test_call,
- METH_O,
- "Call the given callable. Unlike calling it directly, this creates a "
- "new C-level stack frame, which may be helpful in testing."
- },
- {NULL, NULL, 0, NULL}
-};
-
-
-static struct PyModuleDef moduledef = {PyModuleDef_HEAD_INIT,
- "greenlet.tests._test_extension_cpp",
- NULL,
- 0,
- test_methods,
- NULL,
- NULL,
- NULL,
- NULL};
-
-PyMODINIT_FUNC
-PyInit__test_extension_cpp(void)
-{
- PyObject* module = NULL;
-
- module = PyModule_Create(&moduledef);
-
- if (module == NULL) {
- return NULL;
- }
-
- PyGreenlet_Import();
- if (_PyGreenlet_API == NULL) {
- return NULL;
- }
-
- p_test_exception_throw_nonstd = test_exception_throw_nonstd;
- p_test_exception_throw_std = test_exception_throw_std;
- p_test_exception_switch_recurse = test_exception_switch_recurse;
-
- return module;
-}
diff --git a/venv/lib/python3.11/site-packages/greenlet/tests/_test_extension_cpp.cpython-311-x86_64-linux-gnu.so b/venv/lib/python3.11/site-packages/greenlet/tests/_test_extension_cpp.cpython-311-x86_64-linux-gnu.so
deleted file mode 100755
index 714dfa8..0000000
--- a/venv/lib/python3.11/site-packages/greenlet/tests/_test_extension_cpp.cpython-311-x86_64-linux-gnu.so
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/greenlet/tests/fail_clearing_run_switches.py b/venv/lib/python3.11/site-packages/greenlet/tests/fail_clearing_run_switches.py
deleted file mode 100644
index 6dd1492..0000000
--- a/venv/lib/python3.11/site-packages/greenlet/tests/fail_clearing_run_switches.py
+++ /dev/null
@@ -1,47 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-If we have a run callable passed to the constructor or set as an
-attribute, but we don't actually use that (because ``__getattribute__``
-or the like interferes), then when we clear callable before beginning
-to run, there's an opportunity for Python code to run.
-
-"""
-import greenlet
-
-g = None
-main = greenlet.getcurrent()
-
-results = []
-
-class RunCallable:
-
- def __del__(self):
- results.append(('RunCallable', '__del__'))
- main.switch('from RunCallable')
-
-
-class G(greenlet.greenlet):
-
- def __getattribute__(self, name):
- if name == 'run':
- results.append(('G.__getattribute__', 'run'))
- return run_func
- return object.__getattribute__(self, name)
-
-
-def run_func():
- results.append(('run_func', 'enter'))
-
-
-g = G(RunCallable())
-# Try to start G. It will get to the point where it deletes
-# its run callable C++ variable in inner_bootstrap. That triggers
-# the __del__ method, which switches back to main before g
-# actually even starts running.
-x = g.switch()
-results.append(('main: g.switch()', x))
-# In the C++ code, this results in g->g_switch() appearing to return, even though
-# it has yet to run.
-print('In main with', x, flush=True)
-g.switch()
-print('RESULTS', results)
diff --git a/venv/lib/python3.11/site-packages/greenlet/tests/fail_cpp_exception.py b/venv/lib/python3.11/site-packages/greenlet/tests/fail_cpp_exception.py
deleted file mode 100644
index fa4dc2e..0000000
--- a/venv/lib/python3.11/site-packages/greenlet/tests/fail_cpp_exception.py
+++ /dev/null
@@ -1,33 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-Helper for testing a C++ exception throw aborts the process.
-
-Takes one argument, the name of the function in :mod:`_test_extension_cpp` to call.
-"""
-import sys
-import greenlet
-from greenlet.tests import _test_extension_cpp
-print('fail_cpp_exception is running')
-
-def run_unhandled_exception_in_greenlet_aborts():
- def _():
- _test_extension_cpp.test_exception_switch_and_do_in_g2(
- _test_extension_cpp.test_exception_throw_nonstd
- )
- g1 = greenlet.greenlet(_)
- g1.switch()
-
-
-func_name = sys.argv[1]
-try:
- func = getattr(_test_extension_cpp, func_name)
-except AttributeError:
- if func_name == run_unhandled_exception_in_greenlet_aborts.__name__:
- func = run_unhandled_exception_in_greenlet_aborts
- elif func_name == 'run_as_greenlet_target':
- g = greenlet.greenlet(_test_extension_cpp.test_exception_throw_std)
- func = g.switch
- else:
- raise
-print('raising', func, flush=True)
-func()
diff --git a/venv/lib/python3.11/site-packages/greenlet/tests/fail_initialstub_already_started.py b/venv/lib/python3.11/site-packages/greenlet/tests/fail_initialstub_already_started.py
deleted file mode 100644
index c1a44ef..0000000
--- a/venv/lib/python3.11/site-packages/greenlet/tests/fail_initialstub_already_started.py
+++ /dev/null
@@ -1,78 +0,0 @@
-"""
-Testing initialstub throwing an already started exception.
-"""
-
-import greenlet
-
-a = None
-b = None
-c = None
-main = greenlet.getcurrent()
-
-# If we switch into a dead greenlet,
-# we go looking for its parents.
-# if a parent is not yet started, we start it.
-
-results = []
-
-def a_run(*args):
- #results.append('A')
- results.append(('Begin A', args))
-
-
-def c_run():
- results.append('Begin C')
- b.switch('From C')
- results.append('C done')
-
-class A(greenlet.greenlet): pass
-
-class B(greenlet.greenlet):
- doing_it = False
- def __getattribute__(self, name):
- if name == 'run' and not self.doing_it:
- assert greenlet.getcurrent() is c
- self.doing_it = True
- results.append('Switch to b from B.__getattribute__ in '
- + type(greenlet.getcurrent()).__name__)
- b.switch()
- results.append('B.__getattribute__ back from main in '
- + type(greenlet.getcurrent()).__name__)
- if name == 'run':
- name = '_B_run'
- return object.__getattribute__(self, name)
-
- def _B_run(self, *arg):
- results.append(('Begin B', arg))
- results.append('_B_run switching to main')
- main.switch('From B')
-
-class C(greenlet.greenlet):
- pass
-a = A(a_run)
-b = B(parent=a)
-c = C(c_run, b)
-
-# Start a child; while running, it will start B,
-# but starting B will ALSO start B.
-result = c.switch()
-results.append(('main from c', result))
-
-# Switch back to C, which was in the middle of switching
-# already. This will throw the ``GreenletStartedWhileInPython``
-# exception, which results in parent A getting started (B is finished)
-c.switch()
-
-results.append(('A dead?', a.dead, 'B dead?', b.dead, 'C dead?', c.dead))
-
-# A and B should both be dead now.
-assert a.dead
-assert b.dead
-assert not c.dead
-
-result = c.switch()
-results.append(('main from c.2', result))
-# Now C is dead
-assert c.dead
-
-print("RESULTS:", results)
diff --git a/venv/lib/python3.11/site-packages/greenlet/tests/fail_slp_switch.py b/venv/lib/python3.11/site-packages/greenlet/tests/fail_slp_switch.py
deleted file mode 100644
index 0990526..0000000
--- a/venv/lib/python3.11/site-packages/greenlet/tests/fail_slp_switch.py
+++ /dev/null
@@ -1,29 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-A test helper for seeing what happens when slp_switch()
-fails.
-"""
-# pragma: no cover
-
-import greenlet
-
-
-print('fail_slp_switch is running', flush=True)
-
-runs = []
-def func():
- runs.append(1)
- greenlet.getcurrent().parent.switch()
- runs.append(2)
- greenlet.getcurrent().parent.switch()
- runs.append(3)
-
-g = greenlet._greenlet.UnswitchableGreenlet(func)
-g.switch()
-assert runs == [1]
-g.switch()
-assert runs == [1, 2]
-g.force_slp_switch_error = True
-
-# This should crash.
-g.switch()
diff --git a/venv/lib/python3.11/site-packages/greenlet/tests/fail_switch_three_greenlets.py b/venv/lib/python3.11/site-packages/greenlet/tests/fail_switch_three_greenlets.py
deleted file mode 100644
index e151b19..0000000
--- a/venv/lib/python3.11/site-packages/greenlet/tests/fail_switch_three_greenlets.py
+++ /dev/null
@@ -1,44 +0,0 @@
-"""
-Uses a trace function to switch greenlets at unexpected times.
-
-In the trace function, we switch from the current greenlet to another
-greenlet, which switches
-"""
-import greenlet
-
-g1 = None
-g2 = None
-
-switch_to_g2 = False
-
-def tracefunc(*args):
- print('TRACE', *args)
- global switch_to_g2
- if switch_to_g2:
- switch_to_g2 = False
- g2.switch()
- print('\tLEAVE TRACE', *args)
-
-def g1_run():
- print('In g1_run')
- global switch_to_g2
- switch_to_g2 = True
- from_parent = greenlet.getcurrent().parent.switch()
- print('Return to g1_run')
- print('From parent', from_parent)
-
-def g2_run():
- #g1.switch()
- greenlet.getcurrent().parent.switch()
-
-greenlet.settrace(tracefunc)
-
-g1 = greenlet.greenlet(g1_run)
-g2 = greenlet.greenlet(g2_run)
-
-# This switch didn't actually finish!
-# And if it did, it would raise TypeError
-# because g1_run() doesn't take any arguments.
-g1.switch(1)
-print('Back in main')
-g1.switch(2)
diff --git a/venv/lib/python3.11/site-packages/greenlet/tests/fail_switch_three_greenlets2.py b/venv/lib/python3.11/site-packages/greenlet/tests/fail_switch_three_greenlets2.py
deleted file mode 100644
index 1f6b66b..0000000
--- a/venv/lib/python3.11/site-packages/greenlet/tests/fail_switch_three_greenlets2.py
+++ /dev/null
@@ -1,55 +0,0 @@
-"""
-Like fail_switch_three_greenlets, but the call into g1_run would actually be
-valid.
-"""
-import greenlet
-
-g1 = None
-g2 = None
-
-switch_to_g2 = True
-
-results = []
-
-def tracefunc(*args):
- results.append(('trace', args[0]))
- print('TRACE', *args)
- global switch_to_g2
- if switch_to_g2:
- switch_to_g2 = False
- g2.switch('g2 from tracefunc')
- print('\tLEAVE TRACE', *args)
-
-def g1_run(arg):
- results.append(('g1 arg', arg))
- print('In g1_run')
- from_parent = greenlet.getcurrent().parent.switch('from g1_run')
- results.append(('g1 from parent', from_parent))
- return 'g1 done'
-
-def g2_run(arg):
- #g1.switch()
- results.append(('g2 arg', arg))
- parent = greenlet.getcurrent().parent.switch('from g2_run')
- global switch_to_g2
- switch_to_g2 = False
- results.append(('g2 from parent', parent))
- return 'g2 done'
-
-
-greenlet.settrace(tracefunc)
-
-g1 = greenlet.greenlet(g1_run)
-g2 = greenlet.greenlet(g2_run)
-
-x = g1.switch('g1 from main')
-results.append(('main g1', x))
-print('Back in main', x)
-x = g1.switch('g2 from main')
-results.append(('main g2', x))
-print('back in amain again', x)
-x = g1.switch('g1 from main 2')
-results.append(('main g1.2', x))
-x = g2.switch()
-results.append(('main g2.2', x))
-print("RESULTS:", results)
diff --git a/venv/lib/python3.11/site-packages/greenlet/tests/fail_switch_two_greenlets.py b/venv/lib/python3.11/site-packages/greenlet/tests/fail_switch_two_greenlets.py
deleted file mode 100644
index 3e52345..0000000
--- a/venv/lib/python3.11/site-packages/greenlet/tests/fail_switch_two_greenlets.py
+++ /dev/null
@@ -1,41 +0,0 @@
-"""
-Uses a trace function to switch greenlets at unexpected times.
-
-In the trace function, we switch from the current greenlet to another
-greenlet, which switches
-"""
-import greenlet
-
-g1 = None
-g2 = None
-
-switch_to_g2 = False
-
-def tracefunc(*args):
- print('TRACE', *args)
- global switch_to_g2
- if switch_to_g2:
- switch_to_g2 = False
- g2.switch()
- print('\tLEAVE TRACE', *args)
-
-def g1_run():
- print('In g1_run')
- global switch_to_g2
- switch_to_g2 = True
- greenlet.getcurrent().parent.switch()
- print('Return to g1_run')
- print('Falling off end of g1_run')
-
-def g2_run():
- g1.switch()
- print('Falling off end of g2')
-
-greenlet.settrace(tracefunc)
-
-g1 = greenlet.greenlet(g1_run)
-g2 = greenlet.greenlet(g2_run)
-
-g1.switch()
-print('Falling off end of main')
-g2.switch()
diff --git a/venv/lib/python3.11/site-packages/greenlet/tests/leakcheck.py b/venv/lib/python3.11/site-packages/greenlet/tests/leakcheck.py
deleted file mode 100644
index a5152fb..0000000
--- a/venv/lib/python3.11/site-packages/greenlet/tests/leakcheck.py
+++ /dev/null
@@ -1,319 +0,0 @@
-# Copyright (c) 2018 gevent community
-# Copyright (c) 2021 greenlet community
-#
-# This was originally part of gevent's test suite. The main author
-# (Jason Madden) vendored a copy of it into greenlet.
-#
-# Permission is hereby granted, free of charge, to any person obtaining a copy
-# of this software and associated documentation files (the "Software"), to deal
-# in the Software without restriction, including without limitation the rights
-# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-# copies of the Software, and to permit persons to whom the Software is
-# furnished to do so, subject to the following conditions:
-#
-# The above copyright notice and this permission notice shall be included in
-# all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-# THE SOFTWARE.
-from __future__ import print_function
-
-import os
-import sys
-import gc
-
-from functools import wraps
-import unittest
-
-
-import objgraph
-
-# graphviz 0.18 (Nov 7 2021), available only on Python 3.6 and newer,
-# has added type hints (sigh). It wants to use ``typing.Literal`` for
-# some stuff, but that's only available on Python 3.9+. If that's not
-# found, it creates a ``unittest.mock.MagicMock`` object and annotates
-# with that. These are GC'able objects, and doing almost *anything*
-# with them results in an explosion of objects. For example, trying to
-# compare them for equality creates new objects. This causes our
-# leakchecks to fail, with reports like:
-#
-# greenlet.tests.leakcheck.LeakCheckError: refcount increased by [337, 1333, 343, 430, 530, 643, 769]
-# _Call 1820 +546
-# dict 4094 +76
-# MagicProxy 585 +73
-# tuple 2693 +66
-# _CallList 24 +3
-# weakref 1441 +1
-# function 5996 +1
-# type 736 +1
-# cell 592 +1
-# MagicMock 8 +1
-#
-# To avoid this, we *could* filter this type of object out early. In
-# principle it could leak, but we don't use mocks in greenlet, so it
-# doesn't leak from us. However, a further issue is that ``MagicMock``
-# objects have subobjects that are also GC'able, like ``_Call``, and
-# those create new mocks of their own too. So we'd have to filter them
-# as well, and they're not public. That's OK, we can workaround the
-# problem by being very careful to never compare by equality or other
-# user-defined operators, only using object identity or other builtin
-# functions.
-
-RUNNING_ON_GITHUB_ACTIONS = os.environ.get('GITHUB_ACTIONS')
-RUNNING_ON_TRAVIS = os.environ.get('TRAVIS') or RUNNING_ON_GITHUB_ACTIONS
-RUNNING_ON_APPVEYOR = os.environ.get('APPVEYOR')
-RUNNING_ON_CI = RUNNING_ON_TRAVIS or RUNNING_ON_APPVEYOR
-RUNNING_ON_MANYLINUX = os.environ.get('GREENLET_MANYLINUX')
-SKIP_LEAKCHECKS = RUNNING_ON_MANYLINUX or os.environ.get('GREENLET_SKIP_LEAKCHECKS')
-SKIP_FAILING_LEAKCHECKS = os.environ.get('GREENLET_SKIP_FAILING_LEAKCHECKS')
-ONLY_FAILING_LEAKCHECKS = os.environ.get('GREENLET_ONLY_FAILING_LEAKCHECKS')
-
-def ignores_leakcheck(func):
- """
- Ignore the given object during leakchecks.
-
- Can be applied to a method, in which case the method will run, but
- will not be subject to leak checks.
-
- If applied to a class, the entire class will be skipped during leakchecks. This
- is intended to be used for classes that are very slow and cause problems such as
- test timeouts; typically it will be used for classes that are subclasses of a base
- class and specify variants of behaviour (such as pool sizes).
- """
- func.ignore_leakcheck = True
- return func
-
-def fails_leakcheck(func):
- """
- Mark that the function is known to leak.
- """
- func.fails_leakcheck = True
- if SKIP_FAILING_LEAKCHECKS:
- func = unittest.skip("Skipping known failures")(func)
- return func
-
-class LeakCheckError(AssertionError):
- pass
-
-if hasattr(sys, 'getobjects'):
- # In a Python build with ``--with-trace-refs``, make objgraph
- # trace *all* the objects, not just those that are tracked by the
- # GC
- class _MockGC(object):
- def get_objects(self):
- return sys.getobjects(0) # pylint:disable=no-member
- def __getattr__(self, name):
- return getattr(gc, name)
- objgraph.gc = _MockGC()
- fails_strict_leakcheck = fails_leakcheck
-else:
- def fails_strict_leakcheck(func):
- """
- Decorator for a function that is known to fail when running
- strict (``sys.getobjects()``) leakchecks.
-
- This type of leakcheck finds all objects, even those, such as
- strings, which are not tracked by the garbage collector.
- """
- return func
-
-class ignores_types_in_strict_leakcheck(object):
- def __init__(self, types):
- self.types = types
- def __call__(self, func):
- func.leakcheck_ignore_types = self.types
- return func
-
-class _RefCountChecker(object):
-
- # Some builtin things that we ignore
- # XXX: Those things were ignored by gevent, but they're important here,
- # presumably.
- IGNORED_TYPES = () #(tuple, dict, types.FrameType, types.TracebackType)
-
- def __init__(self, testcase, function):
- self.testcase = testcase
- self.function = function
- self.deltas = []
- self.peak_stats = {}
- self.ignored_types = ()
-
- # The very first time we are called, we have already been
- # self.setUp() by the test runner, so we don't need to do it again.
- self.needs_setUp = False
-
- def _include_object_p(self, obj):
- # pylint:disable=too-many-return-statements
- #
- # See the comment block at the top. We must be careful to
- # avoid invoking user-defined operations.
- if obj is self:
- return False
- kind = type(obj)
- # ``self._include_object_p == obj`` returns NotImplemented
- # for non-function objects, which causes the interpreter
- # to try to reverse the order of arguments...which leads
- # to the explosion of mock objects. We don't want that, so we implement
- # the check manually.
- if kind == type(self._include_object_p):
- try:
- # pylint:disable=not-callable
- exact_method_equals = self._include_object_p.__eq__(obj)
- except AttributeError:
- # Python 2.7 methods may only have __cmp__, and that raises a
- # TypeError for non-method arguments
- # pylint:disable=no-member
- exact_method_equals = self._include_object_p.__cmp__(obj) == 0
-
- if exact_method_equals is not NotImplemented and exact_method_equals:
- return False
-
- # Similarly, we need to check identity in our __dict__ to avoid mock explosions.
- for x in self.__dict__.values():
- if obj is x:
- return False
-
-
- if kind in self.ignored_types or kind in self.IGNORED_TYPES:
- return False
-
- return True
-
- def _growth(self):
- return objgraph.growth(limit=None, peak_stats=self.peak_stats,
- filter=self._include_object_p)
-
- def _report_diff(self, growth):
- if not growth:
- return "<Unable to calculate growth>"
-
- lines = []
- width = max(len(name) for name, _, _ in growth)
- for name, count, delta in growth:
- lines.append('%-*s%9d %+9d' % (width, name, count, delta))
-
- diff = '\n'.join(lines)
- return diff
-
-
- def _run_test(self, args, kwargs):
- gc_enabled = gc.isenabled()
- gc.disable()
-
- if self.needs_setUp:
- self.testcase.setUp()
- self.testcase.skipTearDown = False
- try:
- self.function(self.testcase, *args, **kwargs)
- finally:
- self.testcase.tearDown()
- self.testcase.doCleanups()
- self.testcase.skipTearDown = True
- self.needs_setUp = True
- if gc_enabled:
- gc.enable()
-
- def _growth_after(self):
- # Grab post snapshot
- # pylint:disable=no-member
- if 'urlparse' in sys.modules:
- sys.modules['urlparse'].clear_cache()
- if 'urllib.parse' in sys.modules:
- sys.modules['urllib.parse'].clear_cache()
-
- return self._growth()
-
- def _check_deltas(self, growth):
- # Return false when we have decided there is no leak,
- # true if we should keep looping, raises an assertion
- # if we have decided there is a leak.
-
- deltas = self.deltas
- if not deltas:
- # We haven't run yet, no data, keep looping
- return True
-
- if gc.garbage:
- raise LeakCheckError("Generated uncollectable garbage %r" % (gc.garbage,))
-
-
- # the following configurations are classified as "no leak"
- # [0, 0]
- # [x, 0, 0]
- # [... a, b, c, d] where a+b+c+d = 0
- #
- # the following configurations are classified as "leak"
- # [... z, z, z] where z > 0
-
- if deltas[-2:] == [0, 0] and len(deltas) in (2, 3):
- return False
-
- if deltas[-3:] == [0, 0, 0]:
- return False
-
- if len(deltas) >= 4 and sum(deltas[-4:]) == 0:
- return False
-
- if len(deltas) >= 3 and deltas[-1] > 0 and deltas[-1] == deltas[-2] and deltas[-2] == deltas[-3]:
- diff = self._report_diff(growth)
- raise LeakCheckError('refcount increased by %r\n%s' % (deltas, diff))
-
- # OK, we don't know for sure yet. Let's search for more
- if sum(deltas[-3:]) <= 0 or sum(deltas[-4:]) <= 0 or deltas[-4:].count(0) >= 2:
- # this is suspicious, so give a few more runs
- limit = 11
- else:
- limit = 7
- if len(deltas) >= limit:
- raise LeakCheckError('refcount increased by %r\n%s'
- % (deltas,
- self._report_diff(growth)))
-
- # We couldn't decide yet, keep going
- return True
-
- def __call__(self, args, kwargs):
- for _ in range(3):
- gc.collect()
-
- expect_failure = getattr(self.function, 'fails_leakcheck', False)
- if expect_failure:
- self.testcase.expect_greenlet_leak = True
- self.ignored_types = getattr(self.function, "leakcheck_ignore_types", ())
-
- # Capture state before; the incremental will be
- # updated by each call to _growth_after
- growth = self._growth()
-
- try:
- while self._check_deltas(growth):
- self._run_test(args, kwargs)
-
- growth = self._growth_after()
-
- self.deltas.append(sum((stat[2] for stat in growth)))
- except LeakCheckError:
- if not expect_failure:
- raise
- else:
- if expect_failure:
- raise LeakCheckError("Expected %s to leak but it did not." % (self.function,))
-
-def wrap_refcount(method):
- if getattr(method, 'ignore_leakcheck', False) or SKIP_LEAKCHECKS:
- return method
-
- @wraps(method)
- def wrapper(self, *args, **kwargs): # pylint:disable=too-many-branches
- if getattr(self, 'ignore_leakcheck', False):
- raise unittest.SkipTest("This class ignored during leakchecks")
- if ONLY_FAILING_LEAKCHECKS and not getattr(method, 'fails_leakcheck', False):
- raise unittest.SkipTest("Only running tests that fail leakchecks.")
- return _RefCountChecker(self, method)(args, kwargs)
-
- return wrapper
diff --git a/venv/lib/python3.11/site-packages/greenlet/tests/test_contextvars.py b/venv/lib/python3.11/site-packages/greenlet/tests/test_contextvars.py
deleted file mode 100644
index 9a16f67..0000000
--- a/venv/lib/python3.11/site-packages/greenlet/tests/test_contextvars.py
+++ /dev/null
@@ -1,310 +0,0 @@
-from __future__ import print_function
-
-import gc
-import sys
-import unittest
-
-from functools import partial
-from unittest import skipUnless
-from unittest import skipIf
-
-from greenlet import greenlet
-from greenlet import getcurrent
-from . import TestCase
-
-
-try:
- from contextvars import Context
- from contextvars import ContextVar
- from contextvars import copy_context
- # From the documentation:
- #
- # Important: Context Variables should be created at the top module
- # level and never in closures. Context objects hold strong
- # references to context variables which prevents context variables
- # from being properly garbage collected.
- ID_VAR = ContextVar("id", default=None)
- VAR_VAR = ContextVar("var", default=None)
- ContextVar = None
-except ImportError:
- Context = ContextVar = copy_context = None
-
-# We don't support testing if greenlet's built-in context var support is disabled.
-@skipUnless(Context is not None, "ContextVar not supported")
-class ContextVarsTests(TestCase):
- def _new_ctx_run(self, *args, **kwargs):
- return copy_context().run(*args, **kwargs)
-
- def _increment(self, greenlet_id, callback, counts, expect):
- ctx_var = ID_VAR
- if expect is None:
- self.assertIsNone(ctx_var.get())
- else:
- self.assertEqual(ctx_var.get(), expect)
- ctx_var.set(greenlet_id)
- for _ in range(2):
- counts[ctx_var.get()] += 1
- callback()
-
- def _test_context(self, propagate_by):
- # pylint:disable=too-many-branches
- ID_VAR.set(0)
-
- callback = getcurrent().switch
- counts = dict((i, 0) for i in range(5))
-
- lets = [
- greenlet(partial(
- partial(
- copy_context().run,
- self._increment
- ) if propagate_by == "run" else self._increment,
- greenlet_id=i,
- callback=callback,
- counts=counts,
- expect=(
- i - 1 if propagate_by == "share" else
- 0 if propagate_by in ("set", "run") else None
- )
- ))
- for i in range(1, 5)
- ]
-
- for let in lets:
- if propagate_by == "set":
- let.gr_context = copy_context()
- elif propagate_by == "share":
- let.gr_context = getcurrent().gr_context
-
- for i in range(2):
- counts[ID_VAR.get()] += 1
- for let in lets:
- let.switch()
-
- if propagate_by == "run":
- # Must leave each context.run() in reverse order of entry
- for let in reversed(lets):
- let.switch()
- else:
- # No context.run(), so fine to exit in any order.
- for let in lets:
- let.switch()
-
- for let in lets:
- self.assertTrue(let.dead)
- # When using run(), we leave the run() as the greenlet dies,
- # and there's no context "underneath". When not using run(),
- # gr_context still reflects the context the greenlet was
- # running in.
- if propagate_by == 'run':
- self.assertIsNone(let.gr_context)
- else:
- self.assertIsNotNone(let.gr_context)
-
-
- if propagate_by == "share":
- self.assertEqual(counts, {0: 1, 1: 1, 2: 1, 3: 1, 4: 6})
- else:
- self.assertEqual(set(counts.values()), set([2]))
-
- def test_context_propagated_by_context_run(self):
- self._new_ctx_run(self._test_context, "run")
-
- def test_context_propagated_by_setting_attribute(self):
- self._new_ctx_run(self._test_context, "set")
-
- def test_context_not_propagated(self):
- self._new_ctx_run(self._test_context, None)
-
- def test_context_shared(self):
- self._new_ctx_run(self._test_context, "share")
-
- def test_break_ctxvars(self):
- let1 = greenlet(copy_context().run)
- let2 = greenlet(copy_context().run)
- let1.switch(getcurrent().switch)
- let2.switch(getcurrent().switch)
- # Since let2 entered the current context and let1 exits its own, the
- # interpreter emits:
- # RuntimeError: cannot exit context: thread state references a different context object
- let1.switch()
-
- def test_not_broken_if_using_attribute_instead_of_context_run(self):
- let1 = greenlet(getcurrent().switch)
- let2 = greenlet(getcurrent().switch)
- let1.gr_context = copy_context()
- let2.gr_context = copy_context()
- let1.switch()
- let2.switch()
- let1.switch()
- let2.switch()
-
- def test_context_assignment_while_running(self):
- # pylint:disable=too-many-statements
- ID_VAR.set(None)
-
- def target():
- self.assertIsNone(ID_VAR.get())
- self.assertIsNone(gr.gr_context)
-
- # Context is created on first use
- ID_VAR.set(1)
- self.assertIsInstance(gr.gr_context, Context)
- self.assertEqual(ID_VAR.get(), 1)
- self.assertEqual(gr.gr_context[ID_VAR], 1)
-
- # Clearing the context makes it get re-created as another
- # empty context when next used
- old_context = gr.gr_context
- gr.gr_context = None # assign None while running
- self.assertIsNone(ID_VAR.get())
- self.assertIsNone(gr.gr_context)
- ID_VAR.set(2)
- self.assertIsInstance(gr.gr_context, Context)
- self.assertEqual(ID_VAR.get(), 2)
- self.assertEqual(gr.gr_context[ID_VAR], 2)
-
- new_context = gr.gr_context
- getcurrent().parent.switch((old_context, new_context))
- # parent switches us back to old_context
-
- self.assertEqual(ID_VAR.get(), 1)
- gr.gr_context = new_context # assign non-None while running
- self.assertEqual(ID_VAR.get(), 2)
-
- getcurrent().parent.switch()
- # parent switches us back to no context
- self.assertIsNone(ID_VAR.get())
- self.assertIsNone(gr.gr_context)
- gr.gr_context = old_context
- self.assertEqual(ID_VAR.get(), 1)
-
- getcurrent().parent.switch()
- # parent switches us back to no context
- self.assertIsNone(ID_VAR.get())
- self.assertIsNone(gr.gr_context)
-
- gr = greenlet(target)
-
- with self.assertRaisesRegex(AttributeError, "can't delete context attribute"):
- del gr.gr_context
-
- self.assertIsNone(gr.gr_context)
- old_context, new_context = gr.switch()
- self.assertIs(new_context, gr.gr_context)
- self.assertEqual(old_context[ID_VAR], 1)
- self.assertEqual(new_context[ID_VAR], 2)
- self.assertEqual(new_context.run(ID_VAR.get), 2)
- gr.gr_context = old_context # assign non-None while suspended
- gr.switch()
- self.assertIs(gr.gr_context, new_context)
- gr.gr_context = None # assign None while suspended
- gr.switch()
- self.assertIs(gr.gr_context, old_context)
- gr.gr_context = None
- gr.switch()
- self.assertIsNone(gr.gr_context)
-
- # Make sure there are no reference leaks
- gr = None
- gc.collect()
- self.assertEqual(sys.getrefcount(old_context), 2)
- self.assertEqual(sys.getrefcount(new_context), 2)
-
- def test_context_assignment_different_thread(self):
- import threading
- VAR_VAR.set(None)
- ctx = Context()
-
- is_running = threading.Event()
- should_suspend = threading.Event()
- did_suspend = threading.Event()
- should_exit = threading.Event()
- holder = []
-
- def greenlet_in_thread_fn():
- VAR_VAR.set(1)
- is_running.set()
- should_suspend.wait(10)
- VAR_VAR.set(2)
- getcurrent().parent.switch()
- holder.append(VAR_VAR.get())
-
- def thread_fn():
- gr = greenlet(greenlet_in_thread_fn)
- gr.gr_context = ctx
- holder.append(gr)
- gr.switch()
- did_suspend.set()
- should_exit.wait(10)
- gr.switch()
- del gr
- greenlet() # trigger cleanup
-
- thread = threading.Thread(target=thread_fn, daemon=True)
- thread.start()
- is_running.wait(10)
- gr = holder[0]
-
- # Can't access or modify context if the greenlet is running
- # in a different thread
- with self.assertRaisesRegex(ValueError, "running in a different"):
- getattr(gr, 'gr_context')
- with self.assertRaisesRegex(ValueError, "running in a different"):
- gr.gr_context = None
-
- should_suspend.set()
- did_suspend.wait(10)
-
- # OK to access and modify context if greenlet is suspended
- self.assertIs(gr.gr_context, ctx)
- self.assertEqual(gr.gr_context[VAR_VAR], 2)
- gr.gr_context = None
-
- should_exit.set()
- thread.join(10)
-
- self.assertEqual(holder, [gr, None])
-
- # Context can still be accessed/modified when greenlet is dead:
- self.assertIsNone(gr.gr_context)
- gr.gr_context = ctx
- self.assertIs(gr.gr_context, ctx)
-
- # Otherwise we leak greenlets on some platforms.
- # XXX: Should be able to do this automatically
- del holder[:]
- gr = None
- thread = None
-
- def test_context_assignment_wrong_type(self):
- g = greenlet()
- with self.assertRaisesRegex(TypeError,
- "greenlet context must be a contextvars.Context or None"):
- g.gr_context = self
-
-
-@skipIf(Context is not None, "ContextVar supported")
-class NoContextVarsTests(TestCase):
- def test_contextvars_errors(self):
- let1 = greenlet(getcurrent().switch)
- self.assertFalse(hasattr(let1, 'gr_context'))
- with self.assertRaises(AttributeError):
- getattr(let1, 'gr_context')
-
- with self.assertRaises(AttributeError):
- let1.gr_context = None
-
- let1.switch()
-
- with self.assertRaises(AttributeError):
- getattr(let1, 'gr_context')
-
- with self.assertRaises(AttributeError):
- let1.gr_context = None
-
- del let1
-
-
-if __name__ == '__main__':
- unittest.main()
diff --git a/venv/lib/python3.11/site-packages/greenlet/tests/test_cpp.py b/venv/lib/python3.11/site-packages/greenlet/tests/test_cpp.py
deleted file mode 100644
index 2d0cc9c..0000000
--- a/venv/lib/python3.11/site-packages/greenlet/tests/test_cpp.py
+++ /dev/null
@@ -1,73 +0,0 @@
-from __future__ import print_function
-from __future__ import absolute_import
-
-import subprocess
-import unittest
-
-import greenlet
-from . import _test_extension_cpp
-from . import TestCase
-from . import WIN
-
-class CPPTests(TestCase):
- def test_exception_switch(self):
- greenlets = []
- for i in range(4):
- g = greenlet.greenlet(_test_extension_cpp.test_exception_switch)
- g.switch(i)
- greenlets.append(g)
- for i, g in enumerate(greenlets):
- self.assertEqual(g.switch(), i)
-
- def _do_test_unhandled_exception(self, target):
- import os
- import sys
- script = os.path.join(
- os.path.dirname(__file__),
- 'fail_cpp_exception.py',
- )
- args = [sys.executable, script, target.__name__ if not isinstance(target, str) else target]
- __traceback_info__ = args
- with self.assertRaises(subprocess.CalledProcessError) as exc:
- subprocess.check_output(
- args,
- encoding='utf-8',
- stderr=subprocess.STDOUT
- )
-
- ex = exc.exception
- expected_exit = self.get_expected_returncodes_for_aborted_process()
- self.assertIn(ex.returncode, expected_exit)
- self.assertIn('fail_cpp_exception is running', ex.output)
- return ex.output
-
-
- def test_unhandled_nonstd_exception_aborts(self):
- # verify that plain unhandled throw aborts
- self._do_test_unhandled_exception(_test_extension_cpp.test_exception_throw_nonstd)
-
- def test_unhandled_std_exception_aborts(self):
- # verify that plain unhandled throw aborts
- self._do_test_unhandled_exception(_test_extension_cpp.test_exception_throw_std)
-
- @unittest.skipIf(WIN, "XXX: This does not crash on Windows")
- # Meaning the exception is getting lost somewhere...
- def test_unhandled_std_exception_as_greenlet_function_aborts(self):
- # verify that plain unhandled throw aborts
- output = self._do_test_unhandled_exception('run_as_greenlet_target')
- self.assertIn(
- # We really expect this to be prefixed with "greenlet: Unhandled C++ exception:"
- # as added by our handler for std::exception (see TUserGreenlet.cpp), but
- # that's not correct everywhere --- our handler never runs before std::terminate
- # gets called (for example, on arm32).
- 'Thrown from an extension.',
- output
- )
-
- def test_unhandled_exception_in_greenlet_aborts(self):
- # verify that unhandled throw called in greenlet aborts too
- self._do_test_unhandled_exception('run_unhandled_exception_in_greenlet_aborts')
-
-
-if __name__ == '__main__':
- unittest.main()
diff --git a/venv/lib/python3.11/site-packages/greenlet/tests/test_extension_interface.py b/venv/lib/python3.11/site-packages/greenlet/tests/test_extension_interface.py
deleted file mode 100644
index 34b6656..0000000
--- a/venv/lib/python3.11/site-packages/greenlet/tests/test_extension_interface.py
+++ /dev/null
@@ -1,115 +0,0 @@
-from __future__ import print_function
-from __future__ import absolute_import
-
-import sys
-
-import greenlet
-from . import _test_extension
-from . import TestCase
-
-# pylint:disable=c-extension-no-member
-
-class CAPITests(TestCase):
- def test_switch(self):
- self.assertEqual(
- 50, _test_extension.test_switch(greenlet.greenlet(lambda: 50)))
-
- def test_switch_kwargs(self):
- def adder(x, y):
- return x * y
- g = greenlet.greenlet(adder)
- self.assertEqual(6, _test_extension.test_switch_kwargs(g, x=3, y=2))
-
- def test_setparent(self):
- # pylint:disable=disallowed-name
- def foo():
- def bar():
- greenlet.getcurrent().parent.switch()
-
- # This final switch should go back to the main greenlet, since
- # the test_setparent() function in the C extension should have
- # reparented this greenlet.
- greenlet.getcurrent().parent.switch()
- raise AssertionError("Should never have reached this code")
- child = greenlet.greenlet(bar)
- child.switch()
- greenlet.getcurrent().parent.switch(child)
- greenlet.getcurrent().parent.throw(
- AssertionError("Should never reach this code"))
- foo_child = greenlet.greenlet(foo).switch()
- self.assertEqual(None, _test_extension.test_setparent(foo_child))
-
- def test_getcurrent(self):
- _test_extension.test_getcurrent()
-
- def test_new_greenlet(self):
- self.assertEqual(-15, _test_extension.test_new_greenlet(lambda: -15))
-
- def test_raise_greenlet_dead(self):
- self.assertRaises(
- greenlet.GreenletExit, _test_extension.test_raise_dead_greenlet)
-
- def test_raise_greenlet_error(self):
- self.assertRaises(
- greenlet.error, _test_extension.test_raise_greenlet_error)
-
- def test_throw(self):
- seen = []
-
- def foo(): # pylint:disable=disallowed-name
- try:
- greenlet.getcurrent().parent.switch()
- except ValueError:
- seen.append(sys.exc_info()[1])
- except greenlet.GreenletExit:
- raise AssertionError
- g = greenlet.greenlet(foo)
- g.switch()
- _test_extension.test_throw(g)
- self.assertEqual(len(seen), 1)
- self.assertTrue(
- isinstance(seen[0], ValueError),
- "ValueError was not raised in foo()")
- self.assertEqual(
- str(seen[0]),
- 'take that sucka!',
- "message doesn't match")
-
- def test_non_traceback_param(self):
- with self.assertRaises(TypeError) as exc:
- _test_extension.test_throw_exact(
- greenlet.getcurrent(),
- Exception,
- Exception(),
- self
- )
- self.assertEqual(str(exc.exception),
- "throw() third argument must be a traceback object")
-
- def test_instance_of_wrong_type(self):
- with self.assertRaises(TypeError) as exc:
- _test_extension.test_throw_exact(
- greenlet.getcurrent(),
- Exception(),
- BaseException(),
- None,
- )
-
- self.assertEqual(str(exc.exception),
- "instance exception may not have a separate value")
-
- def test_not_throwable(self):
- with self.assertRaises(TypeError) as exc:
- _test_extension.test_throw_exact(
- greenlet.getcurrent(),
- "abc",
- None,
- None,
- )
- self.assertEqual(str(exc.exception),
- "exceptions must be classes, or instances, not str")
-
-
-if __name__ == '__main__':
- import unittest
- unittest.main()
diff --git a/venv/lib/python3.11/site-packages/greenlet/tests/test_gc.py b/venv/lib/python3.11/site-packages/greenlet/tests/test_gc.py
deleted file mode 100644
index 994addb..0000000
--- a/venv/lib/python3.11/site-packages/greenlet/tests/test_gc.py
+++ /dev/null
@@ -1,86 +0,0 @@
-import gc
-
-import weakref
-
-import greenlet
-
-
-from . import TestCase
-from .leakcheck import fails_leakcheck
-# These only work with greenlet gc support
-# which is no longer optional.
-assert greenlet.GREENLET_USE_GC
-
-class GCTests(TestCase):
- def test_dead_circular_ref(self):
- o = weakref.ref(greenlet.greenlet(greenlet.getcurrent).switch())
- gc.collect()
- if o() is not None:
- import sys
- print("O IS NOT NONE.", sys.getrefcount(o()))
- self.assertIsNone(o())
- self.assertFalse(gc.garbage, gc.garbage)
-
- def test_circular_greenlet(self):
- class circular_greenlet(greenlet.greenlet):
- self = None
- o = circular_greenlet()
- o.self = o
- o = weakref.ref(o)
- gc.collect()
- self.assertIsNone(o())
- self.assertFalse(gc.garbage, gc.garbage)
-
- def test_inactive_ref(self):
- class inactive_greenlet(greenlet.greenlet):
- def __init__(self):
- greenlet.greenlet.__init__(self, run=self.run)
-
- def run(self):
- pass
- o = inactive_greenlet()
- o = weakref.ref(o)
- gc.collect()
- self.assertIsNone(o())
- self.assertFalse(gc.garbage, gc.garbage)
-
- @fails_leakcheck
- def test_finalizer_crash(self):
- # This test is designed to crash when active greenlets
- # are made garbage collectable, until the underlying
- # problem is resolved. How does it work:
- # - order of object creation is important
- # - array is created first, so it is moved to unreachable first
- # - we create a cycle between a greenlet and this array
- # - we create an object that participates in gc, is only
- # referenced by a greenlet, and would corrupt gc lists
- # on destruction, the easiest is to use an object with
- # a finalizer
- # - because array is the first object in unreachable it is
- # cleared first, which causes all references to greenlet
- # to disappear and causes greenlet to be destroyed, but since
- # it is still live it causes a switch during gc, which causes
- # an object with finalizer to be destroyed, which causes stack
- # corruption and then a crash
-
- class object_with_finalizer(object):
- def __del__(self):
- pass
- array = []
- parent = greenlet.getcurrent()
- def greenlet_body():
- greenlet.getcurrent().object = object_with_finalizer()
- try:
- parent.switch()
- except greenlet.GreenletExit:
- print("Got greenlet exit!")
- finally:
- del greenlet.getcurrent().object
- g = greenlet.greenlet(greenlet_body)
- g.array = array
- array.append(g)
- g.switch()
- del array
- del g
- greenlet.getcurrent()
- gc.collect()
diff --git a/venv/lib/python3.11/site-packages/greenlet/tests/test_generator.py b/venv/lib/python3.11/site-packages/greenlet/tests/test_generator.py
deleted file mode 100644
index ca4a644..0000000
--- a/venv/lib/python3.11/site-packages/greenlet/tests/test_generator.py
+++ /dev/null
@@ -1,59 +0,0 @@
-
-from greenlet import greenlet
-
-from . import TestCase
-
-class genlet(greenlet):
- parent = None
- def __init__(self, *args, **kwds):
- self.args = args
- self.kwds = kwds
-
- def run(self):
- fn, = self.fn
- fn(*self.args, **self.kwds)
-
- def __iter__(self):
- return self
-
- def __next__(self):
- self.parent = greenlet.getcurrent()
- result = self.switch()
- if self:
- return result
-
- raise StopIteration
-
- next = __next__
-
-
-def Yield(value):
- g = greenlet.getcurrent()
- while not isinstance(g, genlet):
- if g is None:
- raise RuntimeError('yield outside a genlet')
- g = g.parent
- g.parent.switch(value)
-
-
-def generator(func):
- class Generator(genlet):
- fn = (func,)
- return Generator
-
-# ____________________________________________________________
-
-
-class GeneratorTests(TestCase):
- def test_generator(self):
- seen = []
-
- def g(n):
- for i in range(n):
- seen.append(i)
- Yield(i)
- g = generator(g)
- for _ in range(3):
- for j in g(5):
- seen.append(j)
- self.assertEqual(seen, 3 * [0, 0, 1, 1, 2, 2, 3, 3, 4, 4])
diff --git a/venv/lib/python3.11/site-packages/greenlet/tests/test_generator_nested.py b/venv/lib/python3.11/site-packages/greenlet/tests/test_generator_nested.py
deleted file mode 100644
index 8d752a6..0000000
--- a/venv/lib/python3.11/site-packages/greenlet/tests/test_generator_nested.py
+++ /dev/null
@@ -1,168 +0,0 @@
-
-from greenlet import greenlet
-from . import TestCase
-from .leakcheck import fails_leakcheck
-
-class genlet(greenlet):
- parent = None
- def __init__(self, *args, **kwds):
- self.args = args
- self.kwds = kwds
- self.child = None
-
- def run(self):
- # Note the function is packed in a tuple
- # to avoid creating a bound method for it.
- fn, = self.fn
- fn(*self.args, **self.kwds)
-
- def __iter__(self):
- return self
-
- def set_child(self, child):
- self.child = child
-
- def __next__(self):
- if self.child:
- child = self.child
- while child.child:
- tmp = child
- child = child.child
- tmp.child = None
-
- result = child.switch()
- else:
- self.parent = greenlet.getcurrent()
- result = self.switch()
-
- if self:
- return result
-
- raise StopIteration
-
- next = __next__
-
-def Yield(value, level=1):
- g = greenlet.getcurrent()
-
- while level != 0:
- if not isinstance(g, genlet):
- raise RuntimeError('yield outside a genlet')
- if level > 1:
- g.parent.set_child(g)
- g = g.parent
- level -= 1
-
- g.switch(value)
-
-
-def Genlet(func):
- class TheGenlet(genlet):
- fn = (func,)
- return TheGenlet
-
-# ____________________________________________________________
-
-
-def g1(n, seen):
- for i in range(n):
- seen.append(i + 1)
- yield i
-
-
-def g2(n, seen):
- for i in range(n):
- seen.append(i + 1)
- Yield(i)
-
-g2 = Genlet(g2)
-
-
-def nested(i):
- Yield(i)
-
-
-def g3(n, seen):
- for i in range(n):
- seen.append(i + 1)
- nested(i)
-g3 = Genlet(g3)
-
-
-def a(n):
- if n == 0:
- return
- for ii in ax(n - 1):
- Yield(ii)
- Yield(n)
-ax = Genlet(a)
-
-
-def perms(l):
- if len(l) > 1:
- for e in l:
- # No syntactical sugar for generator expressions
- x = [Yield([e] + p) for p in perms([x for x in l if x != e])]
- assert x
- else:
- Yield(l)
-perms = Genlet(perms)
-
-
-def gr1(n):
- for ii in range(1, n):
- Yield(ii)
- Yield(ii * ii, 2)
-
-gr1 = Genlet(gr1)
-
-
-def gr2(n, seen):
- for ii in gr1(n):
- seen.append(ii)
-
-gr2 = Genlet(gr2)
-
-
-class NestedGeneratorTests(TestCase):
- def test_layered_genlets(self):
- seen = []
- for ii in gr2(5, seen):
- seen.append(ii)
- self.assertEqual(seen, [1, 1, 2, 4, 3, 9, 4, 16])
-
- @fails_leakcheck
- def test_permutations(self):
- gen_perms = perms(list(range(4)))
- permutations = list(gen_perms)
- self.assertEqual(len(permutations), 4 * 3 * 2 * 1)
- self.assertIn([0, 1, 2, 3], permutations)
- self.assertIn([3, 2, 1, 0], permutations)
- res = []
- for ii in zip(perms(list(range(4))), perms(list(range(3)))):
- res.append(ii)
- self.assertEqual(
- res,
- [([0, 1, 2, 3], [0, 1, 2]), ([0, 1, 3, 2], [0, 2, 1]),
- ([0, 2, 1, 3], [1, 0, 2]), ([0, 2, 3, 1], [1, 2, 0]),
- ([0, 3, 1, 2], [2, 0, 1]), ([0, 3, 2, 1], [2, 1, 0])])
- # XXX Test to make sure we are working as a generator expression
-
- def test_genlet_simple(self):
- for g in g1, g2, g3:
- seen = []
- for _ in range(3):
- for j in g(5, seen):
- seen.append(j)
- self.assertEqual(seen, 3 * [1, 0, 2, 1, 3, 2, 4, 3, 5, 4])
-
- def test_genlet_bad(self):
- try:
- Yield(10)
- except RuntimeError:
- pass
-
- def test_nested_genlets(self):
- seen = []
- for ii in ax(5):
- seen.append(ii)
diff --git a/venv/lib/python3.11/site-packages/greenlet/tests/test_greenlet.py b/venv/lib/python3.11/site-packages/greenlet/tests/test_greenlet.py
deleted file mode 100644
index 51849cd..0000000
--- a/venv/lib/python3.11/site-packages/greenlet/tests/test_greenlet.py
+++ /dev/null
@@ -1,1311 +0,0 @@
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import gc
-import sys
-import time
-import threading
-
-from abc import ABCMeta, abstractmethod
-
-import greenlet
-from greenlet import greenlet as RawGreenlet
-from . import TestCase
-from .leakcheck import fails_leakcheck
-
-
-# We manually manage locks in many tests
-# pylint:disable=consider-using-with
-# pylint:disable=too-many-public-methods
-# This module is quite large.
-# TODO: Refactor into separate test files. For example,
-# put all the regression tests that used to produce
-# crashes in test_greenlet_no_crash; put tests that DO deliberately crash
-# the interpreter into test_greenlet_crash.
-# pylint:disable=too-many-lines
-
-class SomeError(Exception):
- pass
-
-
-def fmain(seen):
- try:
- greenlet.getcurrent().parent.switch()
- except:
- seen.append(sys.exc_info()[0])
- raise
- raise SomeError
-
-
-def send_exception(g, exc):
- # note: send_exception(g, exc) can be now done with g.throw(exc).
- # the purpose of this test is to explicitly check the propagation rules.
- def crasher(exc):
- raise exc
- g1 = RawGreenlet(crasher, parent=g)
- g1.switch(exc)
-
-
-class TestGreenlet(TestCase):
-
- def _do_simple_test(self):
- lst = []
-
- def f():
- lst.append(1)
- greenlet.getcurrent().parent.switch()
- lst.append(3)
- g = RawGreenlet(f)
- lst.append(0)
- g.switch()
- lst.append(2)
- g.switch()
- lst.append(4)
- self.assertEqual(lst, list(range(5)))
-
- def test_simple(self):
- self._do_simple_test()
-
- def test_switch_no_run_raises_AttributeError(self):
- g = RawGreenlet()
- with self.assertRaises(AttributeError) as exc:
- g.switch()
-
- self.assertIn("run", str(exc.exception))
-
- def test_throw_no_run_raises_AttributeError(self):
- g = RawGreenlet()
- with self.assertRaises(AttributeError) as exc:
- g.throw(SomeError)
-
- self.assertIn("run", str(exc.exception))
-
- def test_parent_equals_None(self):
- g = RawGreenlet(parent=None)
- self.assertIsNotNone(g)
- self.assertIs(g.parent, greenlet.getcurrent())
-
- def test_run_equals_None(self):
- g = RawGreenlet(run=None)
- self.assertIsNotNone(g)
- self.assertIsNone(g.run)
-
- def test_two_children(self):
- lst = []
-
- def f():
- lst.append(1)
- greenlet.getcurrent().parent.switch()
- lst.extend([1, 1])
- g = RawGreenlet(f)
- h = RawGreenlet(f)
- g.switch()
- self.assertEqual(len(lst), 1)
- h.switch()
- self.assertEqual(len(lst), 2)
- h.switch()
- self.assertEqual(len(lst), 4)
- self.assertEqual(h.dead, True)
- g.switch()
- self.assertEqual(len(lst), 6)
- self.assertEqual(g.dead, True)
-
- def test_two_recursive_children(self):
- lst = []
-
- def f():
- lst.append('b')
- greenlet.getcurrent().parent.switch()
-
- def g():
- lst.append('a')
- g = RawGreenlet(f)
- g.switch()
- lst.append('c')
-
- g = RawGreenlet(g)
- self.assertEqual(sys.getrefcount(g), 2)
- g.switch()
- self.assertEqual(lst, ['a', 'b', 'c'])
- # Just the one in this frame, plus the one on the stack we pass to the function
- self.assertEqual(sys.getrefcount(g), 2)
-
- def test_threads(self):
- success = []
-
- def f():
- self._do_simple_test()
- success.append(True)
- ths = [threading.Thread(target=f) for i in range(10)]
- for th in ths:
- th.start()
- for th in ths:
- th.join(10)
- self.assertEqual(len(success), len(ths))
-
- def test_exception(self):
- seen = []
- g1 = RawGreenlet(fmain)
- g2 = RawGreenlet(fmain)
- g1.switch(seen)
- g2.switch(seen)
- g2.parent = g1
-
- self.assertEqual(seen, [])
- #with self.assertRaises(SomeError):
- # p("***Switching back")
- # g2.switch()
- # Creating this as a bound method can reveal bugs that
- # are hidden on newer versions of Python that avoid creating
- # bound methods for direct expressions; IOW, don't use the `with`
- # form!
- self.assertRaises(SomeError, g2.switch)
- self.assertEqual(seen, [SomeError])
-
- value = g2.switch()
- self.assertEqual(value, ())
- self.assertEqual(seen, [SomeError])
-
- value = g2.switch(25)
- self.assertEqual(value, 25)
- self.assertEqual(seen, [SomeError])
-
-
- def test_send_exception(self):
- seen = []
- g1 = RawGreenlet(fmain)
- g1.switch(seen)
- self.assertRaises(KeyError, send_exception, g1, KeyError)
- self.assertEqual(seen, [KeyError])
-
- def test_dealloc(self):
- seen = []
- g1 = RawGreenlet(fmain)
- g2 = RawGreenlet(fmain)
- g1.switch(seen)
- g2.switch(seen)
- self.assertEqual(seen, [])
- del g1
- gc.collect()
- self.assertEqual(seen, [greenlet.GreenletExit])
- del g2
- gc.collect()
- self.assertEqual(seen, [greenlet.GreenletExit, greenlet.GreenletExit])
-
- def test_dealloc_catches_GreenletExit_throws_other(self):
- def run():
- try:
- greenlet.getcurrent().parent.switch()
- except greenlet.GreenletExit:
- raise SomeError from None
-
- g = RawGreenlet(run)
- g.switch()
- # Destroying the only reference to the greenlet causes it
- # to get GreenletExit; when it in turn raises, even though we're the parent
- # we don't get the exception, it just gets printed.
- # When we run on 3.8 only, we can use sys.unraisablehook
- oldstderr = sys.stderr
- try:
- from cStringIO import StringIO
- except ImportError:
- from io import StringIO
- stderr = sys.stderr = StringIO()
- try:
- del g
- finally:
- sys.stderr = oldstderr
-
- v = stderr.getvalue()
- self.assertIn("Exception", v)
- self.assertIn('ignored', v)
- self.assertIn("SomeError", v)
-
-
- def test_dealloc_other_thread(self):
- seen = []
- someref = []
-
- bg_glet_created_running_and_no_longer_ref_in_bg = threading.Event()
- fg_ref_released = threading.Event()
- bg_should_be_clear = threading.Event()
- ok_to_exit_bg_thread = threading.Event()
-
- def f():
- g1 = RawGreenlet(fmain)
- g1.switch(seen)
- someref.append(g1)
- del g1
- gc.collect()
-
- bg_glet_created_running_and_no_longer_ref_in_bg.set()
- fg_ref_released.wait(3)
-
- RawGreenlet() # trigger release
- bg_should_be_clear.set()
- ok_to_exit_bg_thread.wait(3)
- RawGreenlet() # One more time
-
- t = threading.Thread(target=f)
- t.start()
- bg_glet_created_running_and_no_longer_ref_in_bg.wait(10)
-
- self.assertEqual(seen, [])
- self.assertEqual(len(someref), 1)
- del someref[:]
- gc.collect()
- # g1 is not released immediately because it's from another thread
- self.assertEqual(seen, [])
- fg_ref_released.set()
- bg_should_be_clear.wait(3)
- try:
- self.assertEqual(seen, [greenlet.GreenletExit])
- finally:
- ok_to_exit_bg_thread.set()
- t.join(10)
- del seen[:]
- del someref[:]
-
- def test_frame(self):
- def f1():
- f = sys._getframe(0) # pylint:disable=protected-access
- self.assertEqual(f.f_back, None)
- greenlet.getcurrent().parent.switch(f)
- return "meaning of life"
- g = RawGreenlet(f1)
- frame = g.switch()
- self.assertTrue(frame is g.gr_frame)
- self.assertTrue(g)
-
- from_g = g.switch()
- self.assertFalse(g)
- self.assertEqual(from_g, 'meaning of life')
- self.assertEqual(g.gr_frame, None)
-
- def test_thread_bug(self):
- def runner(x):
- g = RawGreenlet(lambda: time.sleep(x))
- g.switch()
- t1 = threading.Thread(target=runner, args=(0.2,))
- t2 = threading.Thread(target=runner, args=(0.3,))
- t1.start()
- t2.start()
- t1.join(10)
- t2.join(10)
-
- def test_switch_kwargs(self):
- def run(a, b):
- self.assertEqual(a, 4)
- self.assertEqual(b, 2)
- return 42
- x = RawGreenlet(run).switch(a=4, b=2)
- self.assertEqual(x, 42)
-
- def test_switch_kwargs_to_parent(self):
- def run(x):
- greenlet.getcurrent().parent.switch(x=x)
- greenlet.getcurrent().parent.switch(2, x=3)
- return x, x ** 2
- g = RawGreenlet(run)
- self.assertEqual({'x': 3}, g.switch(3))
- self.assertEqual(((2,), {'x': 3}), g.switch())
- self.assertEqual((3, 9), g.switch())
-
- def test_switch_to_another_thread(self):
- data = {}
- created_event = threading.Event()
- done_event = threading.Event()
-
- def run():
- data['g'] = RawGreenlet(lambda: None)
- created_event.set()
- done_event.wait(10)
- thread = threading.Thread(target=run)
- thread.start()
- created_event.wait(10)
- with self.assertRaises(greenlet.error):
- data['g'].switch()
- done_event.set()
- thread.join(10)
- # XXX: Should handle this automatically
- data.clear()
-
- def test_exc_state(self):
- def f():
- try:
- raise ValueError('fun')
- except: # pylint:disable=bare-except
- exc_info = sys.exc_info()
- RawGreenlet(h).switch()
- self.assertEqual(exc_info, sys.exc_info())
-
- def h():
- self.assertEqual(sys.exc_info(), (None, None, None))
-
- RawGreenlet(f).switch()
-
- def test_instance_dict(self):
- def f():
- greenlet.getcurrent().test = 42
- def deldict(g):
- del g.__dict__
- def setdict(g, value):
- g.__dict__ = value
- g = RawGreenlet(f)
- self.assertEqual(g.__dict__, {})
- g.switch()
- self.assertEqual(g.test, 42)
- self.assertEqual(g.__dict__, {'test': 42})
- g.__dict__ = g.__dict__
- self.assertEqual(g.__dict__, {'test': 42})
- self.assertRaises(TypeError, deldict, g)
- self.assertRaises(TypeError, setdict, g, 42)
-
- def test_running_greenlet_has_no_run(self):
- has_run = []
- def func():
- has_run.append(
- hasattr(greenlet.getcurrent(), 'run')
- )
-
- g = RawGreenlet(func)
- g.switch()
- self.assertEqual(has_run, [False])
-
- def test_deepcopy(self):
- import copy
- self.assertRaises(TypeError, copy.copy, RawGreenlet())
- self.assertRaises(TypeError, copy.deepcopy, RawGreenlet())
-
- def test_parent_restored_on_kill(self):
- hub = RawGreenlet(lambda: None)
- main = greenlet.getcurrent()
- result = []
- def worker():
- try:
- # Wait to be killed by going back to the test.
- main.switch()
- except greenlet.GreenletExit:
- # Resurrect and switch to parent
- result.append(greenlet.getcurrent().parent)
- result.append(greenlet.getcurrent())
- hub.switch()
- g = RawGreenlet(worker, parent=hub)
- g.switch()
- # delete the only reference, thereby raising GreenletExit
- del g
- self.assertTrue(result)
- self.assertIs(result[0], main)
- self.assertIs(result[1].parent, hub)
- # Delete them, thereby breaking the cycle between the greenlet
- # and the frame, which otherwise would never be collectable
- # XXX: We should be able to automatically fix this.
- del result[:]
- hub = None
- main = None
-
- def test_parent_return_failure(self):
- # No run causes AttributeError on switch
- g1 = RawGreenlet()
- # Greenlet that implicitly switches to parent
- g2 = RawGreenlet(lambda: None, parent=g1)
- # AttributeError should propagate to us, no fatal errors
- with self.assertRaises(AttributeError):
- g2.switch()
-
- def test_throw_exception_not_lost(self):
- class mygreenlet(RawGreenlet):
- def __getattribute__(self, name):
- try:
- raise Exception # pylint:disable=broad-exception-raised
- except: # pylint:disable=bare-except
- pass
- return RawGreenlet.__getattribute__(self, name)
- g = mygreenlet(lambda: None)
- self.assertRaises(SomeError, g.throw, SomeError())
-
- @fails_leakcheck
- def _do_test_throw_to_dead_thread_doesnt_crash(self, wait_for_cleanup=False):
- result = []
- def worker():
- greenlet.getcurrent().parent.switch()
-
- def creator():
- g = RawGreenlet(worker)
- g.switch()
- result.append(g)
- if wait_for_cleanup:
- # Let this greenlet eventually be cleaned up.
- g.switch()
- greenlet.getcurrent()
- t = threading.Thread(target=creator)
- t.start()
- t.join(10)
- del t
- # But, depending on the operating system, the thread
- # deallocator may not actually have run yet! So we can't be
- # sure about the error message unless we wait.
- if wait_for_cleanup:
- self.wait_for_pending_cleanups()
- with self.assertRaises(greenlet.error) as exc:
- result[0].throw(SomeError)
-
- if not wait_for_cleanup:
- self.assertIn(
- str(exc.exception), [
- "cannot switch to a different thread (which happens to have exited)",
- "cannot switch to a different thread"
- ]
- )
- else:
- self.assertEqual(
- str(exc.exception),
- "cannot switch to a different thread (which happens to have exited)",
- )
-
- if hasattr(result[0].gr_frame, 'clear'):
- # The frame is actually executing (it thinks), we can't clear it.
- with self.assertRaises(RuntimeError):
- result[0].gr_frame.clear()
- # Unfortunately, this doesn't actually clear the references, they're in the
- # fast local array.
- if not wait_for_cleanup:
- result[0].gr_frame.f_locals.clear()
- else:
- self.assertIsNone(result[0].gr_frame)
-
- del creator
- worker = None
- del result[:]
- # XXX: we ought to be able to automatically fix this.
- # See issue 252
- self.expect_greenlet_leak = True # direct us not to wait for it to go away
-
- @fails_leakcheck
- def test_throw_to_dead_thread_doesnt_crash(self):
- self._do_test_throw_to_dead_thread_doesnt_crash()
-
- def test_throw_to_dead_thread_doesnt_crash_wait(self):
- self._do_test_throw_to_dead_thread_doesnt_crash(True)
-
- @fails_leakcheck
- def test_recursive_startup(self):
- class convoluted(RawGreenlet):
- def __init__(self):
- RawGreenlet.__init__(self)
- self.count = 0
- def __getattribute__(self, name):
- if name == 'run' and self.count == 0:
- self.count = 1
- self.switch(43)
- return RawGreenlet.__getattribute__(self, name)
- def run(self, value):
- while True:
- self.parent.switch(value)
- g = convoluted()
- self.assertEqual(g.switch(42), 43)
- # Exits the running greenlet, otherwise it leaks
- # XXX: We should be able to automatically fix this
- #g.throw(greenlet.GreenletExit)
- #del g
- self.expect_greenlet_leak = True
-
- def test_threaded_updatecurrent(self):
- # released when main thread should execute
- lock1 = threading.Lock()
- lock1.acquire()
- # released when another thread should execute
- lock2 = threading.Lock()
- lock2.acquire()
- class finalized(object):
- def __del__(self):
- # happens while in green_updatecurrent() in main greenlet
- # should be very careful not to accidentally call it again
- # at the same time we must make sure another thread executes
- lock2.release()
- lock1.acquire()
- # now ts_current belongs to another thread
- def deallocator():
- greenlet.getcurrent().parent.switch()
- def fthread():
- lock2.acquire()
- greenlet.getcurrent()
- del g[0]
- lock1.release()
- lock2.acquire()
- greenlet.getcurrent()
- lock1.release()
- main = greenlet.getcurrent()
- g = [RawGreenlet(deallocator)]
- g[0].bomb = finalized()
- g[0].switch()
- t = threading.Thread(target=fthread)
- t.start()
- # let another thread grab ts_current and deallocate g[0]
- lock2.release()
- lock1.acquire()
- # this is the corner stone
- # getcurrent() will notice that ts_current belongs to another thread
- # and start the update process, which would notice that g[0] should
- # be deallocated, and that will execute an object's finalizer. Now,
- # that object will let another thread run so it can grab ts_current
- # again, which would likely crash the interpreter if there's no
- # check for this case at the end of green_updatecurrent(). This test
- # passes if getcurrent() returns correct result, but it's likely
- # to randomly crash if it's not anyway.
- self.assertEqual(greenlet.getcurrent(), main)
- # wait for another thread to complete, just in case
- t.join(10)
-
- def test_dealloc_switch_args_not_lost(self):
- seen = []
- def worker():
- # wait for the value
- value = greenlet.getcurrent().parent.switch()
- # delete all references to ourself
- del worker[0]
- initiator.parent = greenlet.getcurrent().parent
- # switch to main with the value, but because
- # ts_current is the last reference to us we
- # return here immediately, where we resurrect ourself.
- try:
- greenlet.getcurrent().parent.switch(value)
- finally:
- seen.append(greenlet.getcurrent())
- def initiator():
- return 42 # implicitly falls thru to parent
-
- worker = [RawGreenlet(worker)]
-
- worker[0].switch() # prime worker
- initiator = RawGreenlet(initiator, worker[0])
- value = initiator.switch()
- self.assertTrue(seen)
- self.assertEqual(value, 42)
-
- def test_tuple_subclass(self):
- # The point of this test is to see what happens when a custom
- # tuple subclass is used as an object passed directly to the C
- # function ``green_switch``; part of ``green_switch`` checks
- # the ``len()`` of the ``args`` tuple, and that can call back
- # into Python. Here, when it calls back into Python, we
- # recursively enter ``green_switch`` again.
-
- # This test is really only relevant on Python 2. The builtin
- # `apply` function directly passes the given args tuple object
- # to the underlying function, whereas the Python 3 version
- # unpacks and repacks into an actual tuple. This could still
- # happen using the C API on Python 3 though. We should write a
- # builtin version of apply() ourself.
- def _apply(func, a, k):
- func(*a, **k)
-
- class mytuple(tuple):
- def __len__(self):
- greenlet.getcurrent().switch()
- return tuple.__len__(self)
- args = mytuple()
- kwargs = dict(a=42)
- def switchapply():
- _apply(greenlet.getcurrent().parent.switch, args, kwargs)
- g = RawGreenlet(switchapply)
- self.assertEqual(g.switch(), kwargs)
-
- def test_abstract_subclasses(self):
- AbstractSubclass = ABCMeta(
- 'AbstractSubclass',
- (RawGreenlet,),
- {'run': abstractmethod(lambda self: None)})
-
- class BadSubclass(AbstractSubclass):
- pass
-
- class GoodSubclass(AbstractSubclass):
- def run(self):
- pass
-
- GoodSubclass() # should not raise
- self.assertRaises(TypeError, BadSubclass)
-
- def test_implicit_parent_with_threads(self):
- if not gc.isenabled():
- return # cannot test with disabled gc
- N = gc.get_threshold()[0]
- if N < 50:
- return # cannot test with such a small N
- def attempt():
- lock1 = threading.Lock()
- lock1.acquire()
- lock2 = threading.Lock()
- lock2.acquire()
- recycled = [False]
- def another_thread():
- lock1.acquire() # wait for gc
- greenlet.getcurrent() # update ts_current
- lock2.release() # release gc
- t = threading.Thread(target=another_thread)
- t.start()
- class gc_callback(object):
- def __del__(self):
- lock1.release()
- lock2.acquire()
- recycled[0] = True
- class garbage(object):
- def __init__(self):
- self.cycle = self
- self.callback = gc_callback()
- l = []
- x = range(N*2)
- current = greenlet.getcurrent()
- g = garbage()
- for _ in x:
- g = None # lose reference to garbage
- if recycled[0]:
- # gc callback called prematurely
- t.join(10)
- return False
- last = RawGreenlet()
- if recycled[0]:
- break # yes! gc called in green_new
- l.append(last) # increase allocation counter
- else:
- # gc callback not called when expected
- gc.collect()
- if recycled[0]:
- t.join(10)
- return False
- self.assertEqual(last.parent, current)
- for g in l:
- self.assertEqual(g.parent, current)
- return True
- for _ in range(5):
- if attempt():
- break
-
- def test_issue_245_reference_counting_subclass_no_threads(self):
- # https://github.com/python-greenlet/greenlet/issues/245
- # Before the fix, this crashed pretty reliably on
- # Python 3.10, at least on macOS; but much less reliably on other
- # interpreters (memory layout must have changed).
- # The threaded test crashed more reliably on more interpreters.
- from greenlet import getcurrent
- from greenlet import GreenletExit
-
- class Greenlet(RawGreenlet):
- pass
-
- initial_refs = sys.getrefcount(Greenlet)
- # This has to be an instance variable because
- # Python 2 raises a SyntaxError if we delete a local
- # variable referenced in an inner scope.
- self.glets = [] # pylint:disable=attribute-defined-outside-init
-
- def greenlet_main():
- try:
- getcurrent().parent.switch()
- except GreenletExit:
- self.glets.append(getcurrent())
-
- # Before the
- for _ in range(10):
- Greenlet(greenlet_main).switch()
-
- del self.glets
- self.assertEqual(sys.getrefcount(Greenlet), initial_refs)
-
- def test_issue_245_reference_counting_subclass_threads(self):
- # https://github.com/python-greenlet/greenlet/issues/245
- from threading import Thread
- from threading import Event
-
- from greenlet import getcurrent
-
- class MyGreenlet(RawGreenlet):
- pass
-
- glets = []
- ref_cleared = Event()
-
- def greenlet_main():
- getcurrent().parent.switch()
-
- def thread_main(greenlet_running_event):
- mine = MyGreenlet(greenlet_main)
- glets.append(mine)
- # The greenlets being deleted must be active
- mine.switch()
- # Don't keep any reference to it in this thread
- del mine
- # Let main know we published our greenlet.
- greenlet_running_event.set()
- # Wait for main to let us know the references are
- # gone and the greenlet objects no longer reachable
- ref_cleared.wait(10)
- # The creating thread must call getcurrent() (or a few other
- # greenlet APIs) because that's when the thread-local list of dead
- # greenlets gets cleared.
- getcurrent()
-
- # We start with 3 references to the subclass:
- # - This module
- # - Its __mro__
- # - The __subclassess__ attribute of greenlet
- # - (If we call gc.get_referents(), we find four entries, including
- # some other tuple ``(greenlet)`` that I'm not sure about but must be part
- # of the machinery.)
- #
- # On Python 3.10 it's often enough to just run 3 threads; on Python 2.7,
- # more threads are needed, and the results are still
- # non-deterministic. Presumably the memory layouts are different
- initial_refs = sys.getrefcount(MyGreenlet)
- thread_ready_events = []
- for _ in range(
- initial_refs + 45
- ):
- event = Event()
- thread = Thread(target=thread_main, args=(event,))
- thread_ready_events.append(event)
- thread.start()
-
-
- for done_event in thread_ready_events:
- done_event.wait(10)
-
-
- del glets[:]
- ref_cleared.set()
- # Let any other thread run; it will crash the interpreter
- # if not fixed (or silently corrupt memory and we possibly crash
- # later).
- self.wait_for_pending_cleanups()
- self.assertEqual(sys.getrefcount(MyGreenlet), initial_refs)
-
- def test_falling_off_end_switches_to_unstarted_parent_raises_error(self):
- def no_args():
- return 13
-
- parent_never_started = RawGreenlet(no_args)
-
- def leaf():
- return 42
-
- child = RawGreenlet(leaf, parent_never_started)
-
- # Because the run function takes to arguments
- with self.assertRaises(TypeError):
- child.switch()
-
- def test_falling_off_end_switches_to_unstarted_parent_works(self):
- def one_arg(x):
- return (x, 24)
-
- parent_never_started = RawGreenlet(one_arg)
-
- def leaf():
- return 42
-
- child = RawGreenlet(leaf, parent_never_started)
-
- result = child.switch()
- self.assertEqual(result, (42, 24))
-
- def test_switch_to_dead_greenlet_with_unstarted_perverse_parent(self):
- class Parent(RawGreenlet):
- def __getattribute__(self, name):
- if name == 'run':
- raise SomeError
-
-
- parent_never_started = Parent()
- seen = []
- child = RawGreenlet(lambda: seen.append(42), parent_never_started)
- # Because we automatically start the parent when the child is
- # finished
- with self.assertRaises(SomeError):
- child.switch()
-
- self.assertEqual(seen, [42])
-
- with self.assertRaises(SomeError):
- child.switch()
- self.assertEqual(seen, [42])
-
- def test_switch_to_dead_greenlet_reparent(self):
- seen = []
- parent_never_started = RawGreenlet(lambda: seen.append(24))
- child = RawGreenlet(lambda: seen.append(42))
-
- child.switch()
- self.assertEqual(seen, [42])
-
- child.parent = parent_never_started
- # This actually is the same as switching to the parent.
- result = child.switch()
- self.assertIsNone(result)
- self.assertEqual(seen, [42, 24])
-
- def test_can_access_f_back_of_suspended_greenlet(self):
- # This tests our frame rewriting to work around Python 3.12+ having
- # some interpreter frames on the C stack. It will crash in the absence
- # of that logic.
- main = greenlet.getcurrent()
-
- def outer():
- inner()
-
- def inner():
- main.switch(sys._getframe(0))
-
- hub = RawGreenlet(outer)
- # start it
- hub.switch()
-
- # start another greenlet to make sure we aren't relying on
- # anything in `hub` still being on the C stack
- unrelated = RawGreenlet(lambda: None)
- unrelated.switch()
-
- # now it is suspended
- self.assertIsNotNone(hub.gr_frame)
- self.assertEqual(hub.gr_frame.f_code.co_name, "inner")
- self.assertIsNotNone(hub.gr_frame.f_back)
- self.assertEqual(hub.gr_frame.f_back.f_code.co_name, "outer")
- # The next line is what would crash
- self.assertIsNone(hub.gr_frame.f_back.f_back)
-
- def test_get_stack_with_nested_c_calls(self):
- from functools import partial
- from . import _test_extension_cpp
-
- def recurse(v):
- if v > 0:
- return v * _test_extension_cpp.test_call(partial(recurse, v - 1))
- return greenlet.getcurrent().parent.switch()
-
- gr = RawGreenlet(recurse)
- gr.switch(5)
- frame = gr.gr_frame
- for i in range(5):
- self.assertEqual(frame.f_locals["v"], i)
- frame = frame.f_back
- self.assertEqual(frame.f_locals["v"], 5)
- self.assertIsNone(frame.f_back)
- self.assertEqual(gr.switch(10), 1200) # 1200 = 5! * 10
-
- def test_frames_always_exposed(self):
- # On Python 3.12 this will crash if we don't set the
- # gr_frames_always_exposed attribute. More background:
- # https://github.com/python-greenlet/greenlet/issues/388
- main = greenlet.getcurrent()
-
- def outer():
- inner(sys._getframe(0))
-
- def inner(frame):
- main.switch(frame)
-
- gr = RawGreenlet(outer)
- frame = gr.switch()
-
- # Do something else to clobber the part of the C stack used by `gr`,
- # so we can't skate by on "it just happened to still be there"
- unrelated = RawGreenlet(lambda: None)
- unrelated.switch()
-
- self.assertEqual(frame.f_code.co_name, "outer")
- # The next line crashes on 3.12 if we haven't exposed the frames.
- self.assertIsNone(frame.f_back)
-
-
-class TestGreenletSetParentErrors(TestCase):
- def test_threaded_reparent(self):
- data = {}
- created_event = threading.Event()
- done_event = threading.Event()
-
- def run():
- data['g'] = RawGreenlet(lambda: None)
- created_event.set()
- done_event.wait(10)
-
- def blank():
- greenlet.getcurrent().parent.switch()
-
- thread = threading.Thread(target=run)
- thread.start()
- created_event.wait(10)
- g = RawGreenlet(blank)
- g.switch()
- with self.assertRaises(ValueError) as exc:
- g.parent = data['g']
- done_event.set()
- thread.join(10)
-
- self.assertEqual(str(exc.exception), "parent cannot be on a different thread")
-
- def test_unexpected_reparenting(self):
- another = []
- def worker():
- g = RawGreenlet(lambda: None)
- another.append(g)
- g.switch()
- t = threading.Thread(target=worker)
- t.start()
- t.join(10)
- # The first time we switch (running g_initialstub(), which is
- # when we look up the run attribute) we attempt to change the
- # parent to one from another thread (which also happens to be
- # dead). ``g_initialstub()`` should detect this and raise a
- # greenlet error.
- #
- # EXCEPT: With the fix for #252, this is actually detected
- # sooner, when setting the parent itself. Prior to that fix,
- # the main greenlet from the background thread kept a valid
- # value for ``run_info``, and appeared to be a valid parent
- # until we actually started the greenlet. But now that it's
- # cleared, this test is catching whether ``green_setparent``
- # can detect the dead thread.
- #
- # Further refactoring once again changes this back to a greenlet.error
- #
- # We need to wait for the cleanup to happen, but we're
- # deliberately leaking a main greenlet here.
- self.wait_for_pending_cleanups(initial_main_greenlets=self.main_greenlets_before_test + 1)
-
- class convoluted(RawGreenlet):
- def __getattribute__(self, name):
- if name == 'run':
- self.parent = another[0] # pylint:disable=attribute-defined-outside-init
- return RawGreenlet.__getattribute__(self, name)
- g = convoluted(lambda: None)
- with self.assertRaises(greenlet.error) as exc:
- g.switch()
- self.assertEqual(str(exc.exception),
- "cannot switch to a different thread (which happens to have exited)")
- del another[:]
-
- def test_unexpected_reparenting_thread_running(self):
- # Like ``test_unexpected_reparenting``, except the background thread is
- # actually still alive.
- another = []
- switched_to_greenlet = threading.Event()
- keep_main_alive = threading.Event()
- def worker():
- g = RawGreenlet(lambda: None)
- another.append(g)
- g.switch()
- switched_to_greenlet.set()
- keep_main_alive.wait(10)
- class convoluted(RawGreenlet):
- def __getattribute__(self, name):
- if name == 'run':
- self.parent = another[0] # pylint:disable=attribute-defined-outside-init
- return RawGreenlet.__getattribute__(self, name)
-
- t = threading.Thread(target=worker)
- t.start()
-
- switched_to_greenlet.wait(10)
- try:
- g = convoluted(lambda: None)
-
- with self.assertRaises(greenlet.error) as exc:
- g.switch()
- self.assertEqual(str(exc.exception), "cannot switch to a different thread")
- finally:
- keep_main_alive.set()
- t.join(10)
- # XXX: Should handle this automatically.
- del another[:]
-
- def test_cannot_delete_parent(self):
- worker = RawGreenlet(lambda: None)
- self.assertIs(worker.parent, greenlet.getcurrent())
-
- with self.assertRaises(AttributeError) as exc:
- del worker.parent
- self.assertEqual(str(exc.exception), "can't delete attribute")
-
- def test_cannot_delete_parent_of_main(self):
- with self.assertRaises(AttributeError) as exc:
- del greenlet.getcurrent().parent
- self.assertEqual(str(exc.exception), "can't delete attribute")
-
-
- def test_main_greenlet_parent_is_none(self):
- # assuming we're in a main greenlet here.
- self.assertIsNone(greenlet.getcurrent().parent)
-
- def test_set_parent_wrong_types(self):
- def bg():
- # Go back to main.
- greenlet.getcurrent().parent.switch()
-
- def check(glet):
- for p in None, 1, self, "42":
- with self.assertRaises(TypeError) as exc:
- glet.parent = p
-
- self.assertEqual(
- str(exc.exception),
- "GreenletChecker: Expected any type of greenlet, not " + type(p).__name__)
-
- # First, not running
- g = RawGreenlet(bg)
- self.assertFalse(g)
- check(g)
-
- # Then when running.
- g.switch()
- self.assertTrue(g)
- check(g)
-
- # Let it finish
- g.switch()
-
-
- def test_trivial_cycle(self):
- glet = RawGreenlet(lambda: None)
- with self.assertRaises(ValueError) as exc:
- glet.parent = glet
- self.assertEqual(str(exc.exception), "cyclic parent chain")
-
- def test_trivial_cycle_main(self):
- # This used to produce a ValueError, but we catch it earlier than that now.
- with self.assertRaises(AttributeError) as exc:
- greenlet.getcurrent().parent = greenlet.getcurrent()
- self.assertEqual(str(exc.exception), "cannot set the parent of a main greenlet")
-
- def test_deeper_cycle(self):
- g1 = RawGreenlet(lambda: None)
- g2 = RawGreenlet(lambda: None)
- g3 = RawGreenlet(lambda: None)
-
- g1.parent = g2
- g2.parent = g3
- with self.assertRaises(ValueError) as exc:
- g3.parent = g1
- self.assertEqual(str(exc.exception), "cyclic parent chain")
-
-
-class TestRepr(TestCase):
-
- def assertEndsWith(self, got, suffix):
- self.assertTrue(got.endswith(suffix), (got, suffix))
-
- def test_main_while_running(self):
- r = repr(greenlet.getcurrent())
- self.assertEndsWith(r, " current active started main>")
-
- def test_main_in_background(self):
- main = greenlet.getcurrent()
- def run():
- return repr(main)
-
- g = RawGreenlet(run)
- r = g.switch()
- self.assertEndsWith(r, ' suspended active started main>')
-
- def test_initial(self):
- r = repr(RawGreenlet())
- self.assertEndsWith(r, ' pending>')
-
- def test_main_from_other_thread(self):
- main = greenlet.getcurrent()
-
- class T(threading.Thread):
- original_main = thread_main = None
- main_glet = None
- def run(self):
- self.original_main = repr(main)
- self.main_glet = greenlet.getcurrent()
- self.thread_main = repr(self.main_glet)
-
- t = T()
- t.start()
- t.join(10)
-
- self.assertEndsWith(t.original_main, ' suspended active started main>')
- self.assertEndsWith(t.thread_main, ' current active started main>')
- # give the machinery time to notice the death of the thread,
- # and clean it up. Note that we don't use
- # ``expect_greenlet_leak`` or wait_for_pending_cleanups,
- # because at this point we know we have an extra greenlet
- # still reachable.
- for _ in range(3):
- time.sleep(0.001)
-
- # In the past, main greenlets, even from dead threads, never
- # really appear dead. We have fixed that, and we also report
- # that the thread is dead in the repr. (Do this multiple times
- # to make sure that we don't self-modify and forget our state
- # in the C++ code).
- for _ in range(3):
- self.assertTrue(t.main_glet.dead)
- r = repr(t.main_glet)
- self.assertEndsWith(r, ' (thread exited) dead>')
-
- def test_dead(self):
- g = RawGreenlet(lambda: None)
- g.switch()
- self.assertEndsWith(repr(g), ' dead>')
- self.assertNotIn('suspended', repr(g))
- self.assertNotIn('started', repr(g))
- self.assertNotIn('active', repr(g))
-
- def test_formatting_produces_native_str(self):
- # https://github.com/python-greenlet/greenlet/issues/218
- # %s formatting on Python 2 was producing unicode, not str.
-
- g_dead = RawGreenlet(lambda: None)
- g_not_started = RawGreenlet(lambda: None)
- g_cur = greenlet.getcurrent()
-
- for g in g_dead, g_not_started, g_cur:
-
- self.assertIsInstance(
- '%s' % (g,),
- str
- )
- self.assertIsInstance(
- '%r' % (g,),
- str,
- )
-
-
-class TestMainGreenlet(TestCase):
- # Tests some implementation details, and relies on some
- # implementation details.
-
- def _check_current_is_main(self):
- # implementation detail
- assert 'main' in repr(greenlet.getcurrent())
-
- t = type(greenlet.getcurrent())
- assert 'main' not in repr(t)
- return t
-
- def test_main_greenlet_type_can_be_subclassed(self):
- main_type = self._check_current_is_main()
- subclass = type('subclass', (main_type,), {})
- self.assertIsNotNone(subclass)
-
- def test_main_greenlet_is_greenlet(self):
- self._check_current_is_main()
- self.assertIsInstance(greenlet.getcurrent(), RawGreenlet)
-
-
-
-class TestBrokenGreenlets(TestCase):
- # Tests for things that used to, or still do, terminate the interpreter.
- # This often means doing unsavory things.
-
- def test_failed_to_initialstub(self):
- def func():
- raise AssertionError("Never get here")
-
-
- g = greenlet._greenlet.UnswitchableGreenlet(func)
- g.force_switch_error = True
-
- with self.assertRaisesRegex(SystemError,
- "Failed to switch stacks into a greenlet for the first time."):
- g.switch()
-
- def test_failed_to_switch_into_running(self):
- runs = []
- def func():
- runs.append(1)
- greenlet.getcurrent().parent.switch()
- runs.append(2)
- greenlet.getcurrent().parent.switch()
- runs.append(3) # pragma: no cover
-
- g = greenlet._greenlet.UnswitchableGreenlet(func)
- g.switch()
- self.assertEqual(runs, [1])
- g.switch()
- self.assertEqual(runs, [1, 2])
- g.force_switch_error = True
-
- with self.assertRaisesRegex(SystemError,
- "Failed to switch stacks into a running greenlet."):
- g.switch()
-
- # If we stopped here, we would fail the leakcheck, because we've left
- # the ``inner_bootstrap()`` C frame and its descendents hanging around,
- # which have a bunch of Python references. They'll never get cleaned up
- # if we don't let the greenlet finish.
- g.force_switch_error = False
- g.switch()
- self.assertEqual(runs, [1, 2, 3])
-
- def test_failed_to_slp_switch_into_running(self):
- ex = self.assertScriptRaises('fail_slp_switch.py')
-
- self.assertIn('fail_slp_switch is running', ex.output)
- self.assertIn(ex.returncode, self.get_expected_returncodes_for_aborted_process())
-
- def test_reentrant_switch_two_greenlets(self):
- # Before we started capturing the arguments in g_switch_finish, this could crash.
- output = self.run_script('fail_switch_two_greenlets.py')
- self.assertIn('In g1_run', output)
- self.assertIn('TRACE', output)
- self.assertIn('LEAVE TRACE', output)
- self.assertIn('Falling off end of main', output)
- self.assertIn('Falling off end of g1_run', output)
- self.assertIn('Falling off end of g2', output)
-
- def test_reentrant_switch_three_greenlets(self):
- # On debug builds of greenlet, this used to crash with an assertion error;
- # on non-debug versions, it ran fine (which it should not do!).
- # Now it always crashes correctly with a TypeError
- ex = self.assertScriptRaises('fail_switch_three_greenlets.py', exitcodes=(1,))
-
- self.assertIn('TypeError', ex.output)
- self.assertIn('positional arguments', ex.output)
-
- def test_reentrant_switch_three_greenlets2(self):
- # This actually passed on debug and non-debug builds. It
- # should probably have been triggering some debug assertions
- # but it didn't.
- #
- # I think the fixes for the above test also kicked in here.
- output = self.run_script('fail_switch_three_greenlets2.py')
- self.assertIn(
- "RESULTS: [('trace', 'switch'), "
- "('trace', 'switch'), ('g2 arg', 'g2 from tracefunc'), "
- "('trace', 'switch'), ('main g1', 'from g2_run'), ('trace', 'switch'), "
- "('g1 arg', 'g1 from main'), ('trace', 'switch'), ('main g2', 'from g1_run'), "
- "('trace', 'switch'), ('g1 from parent', 'g1 from main 2'), ('trace', 'switch'), "
- "('main g1.2', 'g1 done'), ('trace', 'switch'), ('g2 from parent', ()), "
- "('trace', 'switch'), ('main g2.2', 'g2 done')]",
- output
- )
-
- def test_reentrant_switch_GreenletAlreadyStartedInPython(self):
- output = self.run_script('fail_initialstub_already_started.py')
-
- self.assertIn(
- "RESULTS: ['Begin C', 'Switch to b from B.__getattribute__ in C', "
- "('Begin B', ()), '_B_run switching to main', ('main from c', 'From B'), "
- "'B.__getattribute__ back from main in C', ('Begin A', (None,)), "
- "('A dead?', True, 'B dead?', True, 'C dead?', False), "
- "'C done', ('main from c.2', None)]",
- output
- )
-
- def test_reentrant_switch_run_callable_has_del(self):
- output = self.run_script('fail_clearing_run_switches.py')
- self.assertIn(
- "RESULTS ["
- "('G.__getattribute__', 'run'), ('RunCallable', '__del__'), "
- "('main: g.switch()', 'from RunCallable'), ('run_func', 'enter')"
- "]",
- output
- )
-
-if __name__ == '__main__':
- import unittest
- unittest.main()
diff --git a/venv/lib/python3.11/site-packages/greenlet/tests/test_greenlet_trash.py b/venv/lib/python3.11/site-packages/greenlet/tests/test_greenlet_trash.py
deleted file mode 100644
index 8d9716e..0000000
--- a/venv/lib/python3.11/site-packages/greenlet/tests/test_greenlet_trash.py
+++ /dev/null
@@ -1,178 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-Tests for greenlets interacting with the CPython trash can API.
-
-The CPython trash can API is not designed to be re-entered from a
-single thread. But this can happen using greenlets, if something
-during the object deallocation process switches greenlets, and this second
-greenlet then causes the trash can to get entered again. Here, we do this
-very explicitly, but in other cases (like gevent) it could be arbitrarily more
-complicated: for example, a weakref callback might try to acquire a lock that's
-already held by another greenlet; that would allow a greenlet switch to occur.
-
-See https://github.com/gevent/gevent/issues/1909
-
-This test is fragile and relies on details of the CPython
-implementation (like most of the rest of this package):
-
- - We enter the trashcan and deferred deallocation after
- ``_PyTrash_UNWIND_LEVEL`` calls. This constant, defined in
- CPython's object.c, is generally 50. That's basically how many objects are required to
- get us into the deferred deallocation situation.
-
- - The test fails by hitting an ``assert()`` in object.c; if the
- build didn't enable assert, then we don't catch this.
-
- - If the test fails in that way, the interpreter crashes.
-"""
-from __future__ import print_function, absolute_import, division
-
-import unittest
-
-class TestTrashCanReEnter(unittest.TestCase):
-
- def test_it(self):
- # Try several times to trigger it, because it isn't 100%
- # reliable.
- for _ in range(10):
- self.check_it()
-
- def check_it(self): # pylint:disable=too-many-statements
- import greenlet
- from greenlet._greenlet import get_tstate_trash_delete_nesting # pylint:disable=no-name-in-module
-
- main = greenlet.getcurrent()
-
- assert get_tstate_trash_delete_nesting() == 0
-
- # We expect to be in deferred deallocation after this many
- # deallocations have occurred. TODO: I wish we had a better way to do
- # this --- that was before get_tstate_trash_delete_nesting; perhaps
- # we can use that API to do better?
- TRASH_UNWIND_LEVEL = 50
- # How many objects to put in a container; it's the container that
- # queues objects for deferred deallocation.
- OBJECTS_PER_CONTAINER = 500
-
- class Dealloc: # define the class here because we alter class variables each time we run.
- """
- An object with a ``__del__`` method. When it starts getting deallocated
- from a deferred trash can run, it switches greenlets, allocates more objects
- which then also go in the trash can. If we don't save state appropriately,
- nesting gets out of order and we can crash the interpreter.
- """
-
- #: Has our deallocation actually run and switched greenlets?
- #: When it does, this will be set to the current greenlet. This should
- #: be happening in the main greenlet, so we check that down below.
- SPAWNED = False
-
- #: Has the background greenlet run?
- BG_RAN = False
-
- BG_GLET = None
-
- #: How many of these things have ever been allocated.
- CREATED = 0
-
- #: How many of these things have ever been deallocated.
- DESTROYED = 0
-
- #: How many were destroyed not in the main greenlet. There should always
- #: be some.
- #: If the test is broken or things change in the trashcan implementation,
- #: this may not be correct.
- DESTROYED_BG = 0
-
- def __init__(self, sequence_number):
- """
- :param sequence_number: The ordinal of this object during
- one particular creation run. This is used to detect (guess, really)
- when we have entered the trash can's deferred deallocation.
- """
- self.i = sequence_number
- Dealloc.CREATED += 1
-
- def __del__(self):
- if self.i == TRASH_UNWIND_LEVEL and not self.SPAWNED:
- Dealloc.SPAWNED = greenlet.getcurrent()
- other = Dealloc.BG_GLET = greenlet.greenlet(background_greenlet)
- x = other.switch()
- assert x == 42
- # It's important that we don't switch back to the greenlet,
- # we leave it hanging there in an incomplete state. But we don't let it
- # get collected, either. If we complete it now, while we're still
- # in the scope of the initial trash can, things work out and we
- # don't see the problem. We need this greenlet to complete
- # at some point in the future, after we've exited this trash can invocation.
- del other
- elif self.i == 40 and greenlet.getcurrent() is not main:
- Dealloc.BG_RAN = True
- try:
- main.switch(42)
- except greenlet.GreenletExit as ex:
- # We expect this; all references to us go away
- # while we're still running, and we need to finish deleting
- # ourself.
- Dealloc.BG_RAN = type(ex)
- del ex
-
- # Record the fact that we're dead last of all. This ensures that
- # we actually get returned too.
- Dealloc.DESTROYED += 1
- if greenlet.getcurrent() is not main:
- Dealloc.DESTROYED_BG += 1
-
-
- def background_greenlet():
- # We direct through a second function, instead of
- # directly calling ``make_some()``, so that we have complete
- # control over when these objects are destroyed: we need them
- # to be destroyed in the context of the background greenlet
- t = make_some()
- del t # Triggere deletion.
-
- def make_some():
- t = ()
- i = OBJECTS_PER_CONTAINER
- while i:
- # Nest the tuples; it's the recursion that gets us
- # into trash.
- t = (Dealloc(i), t)
- i -= 1
- return t
-
-
- some = make_some()
- self.assertEqual(Dealloc.CREATED, OBJECTS_PER_CONTAINER)
- self.assertEqual(Dealloc.DESTROYED, 0)
-
- # If we're going to crash, it should be on the following line.
- # We only crash if ``assert()`` is enabled, of course.
- del some
-
- # For non-debug builds of CPython, we won't crash. The best we can do is check
- # the nesting level explicitly.
- self.assertEqual(0, get_tstate_trash_delete_nesting())
-
- # Discard this, raising GreenletExit into where it is waiting.
- Dealloc.BG_GLET = None
- # The same nesting level maintains.
- self.assertEqual(0, get_tstate_trash_delete_nesting())
-
- # We definitely cleaned some up in the background
- self.assertGreater(Dealloc.DESTROYED_BG, 0)
-
- # Make sure all the cleanups happened.
- self.assertIs(Dealloc.SPAWNED, main)
- self.assertTrue(Dealloc.BG_RAN)
- self.assertEqual(Dealloc.BG_RAN, greenlet.GreenletExit)
- self.assertEqual(Dealloc.CREATED, Dealloc.DESTROYED )
- self.assertEqual(Dealloc.CREATED, OBJECTS_PER_CONTAINER * 2)
-
- import gc
- gc.collect()
-
-
-if __name__ == '__main__':
- unittest.main()
diff --git a/venv/lib/python3.11/site-packages/greenlet/tests/test_leaks.py b/venv/lib/python3.11/site-packages/greenlet/tests/test_leaks.py
deleted file mode 100644
index ed1fa71..0000000
--- a/venv/lib/python3.11/site-packages/greenlet/tests/test_leaks.py
+++ /dev/null
@@ -1,443 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-Testing scenarios that may have leaked.
-"""
-from __future__ import print_function, absolute_import, division
-
-import sys
-import gc
-
-import time
-import weakref
-import threading
-
-
-import greenlet
-from . import TestCase
-from .leakcheck import fails_leakcheck
-from .leakcheck import ignores_leakcheck
-from .leakcheck import RUNNING_ON_MANYLINUX
-
-# pylint:disable=protected-access
-
-assert greenlet.GREENLET_USE_GC # Option to disable this was removed in 1.0
-
-class HasFinalizerTracksInstances(object):
- EXTANT_INSTANCES = set()
- def __init__(self, msg):
- self.msg = sys.intern(msg)
- self.EXTANT_INSTANCES.add(id(self))
- def __del__(self):
- self.EXTANT_INSTANCES.remove(id(self))
- def __repr__(self):
- return "<HasFinalizerTracksInstances at 0x%x %r>" % (
- id(self), self.msg
- )
- @classmethod
- def reset(cls):
- cls.EXTANT_INSTANCES.clear()
-
-
-class TestLeaks(TestCase):
-
- def test_arg_refs(self):
- args = ('a', 'b', 'c')
- refcount_before = sys.getrefcount(args)
- # pylint:disable=unnecessary-lambda
- g = greenlet.greenlet(
- lambda *args: greenlet.getcurrent().parent.switch(*args))
- for _ in range(100):
- g.switch(*args)
- self.assertEqual(sys.getrefcount(args), refcount_before)
-
- def test_kwarg_refs(self):
- kwargs = {}
- # pylint:disable=unnecessary-lambda
- g = greenlet.greenlet(
- lambda **kwargs: greenlet.getcurrent().parent.switch(**kwargs))
- for _ in range(100):
- g.switch(**kwargs)
- self.assertEqual(sys.getrefcount(kwargs), 2)
-
-
- @staticmethod
- def __recycle_threads():
- # By introducing a thread that does sleep we allow other threads,
- # that have triggered their __block condition, but did not have a
- # chance to deallocate their thread state yet, to finally do so.
- # The way it works is by requiring a GIL switch (different thread),
- # which does a GIL release (sleep), which might do a GIL switch
- # to finished threads and allow them to clean up.
- def worker():
- time.sleep(0.001)
- t = threading.Thread(target=worker)
- t.start()
- time.sleep(0.001)
- t.join(10)
-
- def test_threaded_leak(self):
- gg = []
- def worker():
- # only main greenlet present
- gg.append(weakref.ref(greenlet.getcurrent()))
- for _ in range(2):
- t = threading.Thread(target=worker)
- t.start()
- t.join(10)
- del t
- greenlet.getcurrent() # update ts_current
- self.__recycle_threads()
- greenlet.getcurrent() # update ts_current
- gc.collect()
- greenlet.getcurrent() # update ts_current
- for g in gg:
- self.assertIsNone(g())
-
- def test_threaded_adv_leak(self):
- gg = []
- def worker():
- # main and additional *finished* greenlets
- ll = greenlet.getcurrent().ll = []
- def additional():
- ll.append(greenlet.getcurrent())
- for _ in range(2):
- greenlet.greenlet(additional).switch()
- gg.append(weakref.ref(greenlet.getcurrent()))
- for _ in range(2):
- t = threading.Thread(target=worker)
- t.start()
- t.join(10)
- del t
- greenlet.getcurrent() # update ts_current
- self.__recycle_threads()
- greenlet.getcurrent() # update ts_current
- gc.collect()
- greenlet.getcurrent() # update ts_current
- for g in gg:
- self.assertIsNone(g())
-
- def assertClocksUsed(self):
- used = greenlet._greenlet.get_clocks_used_doing_optional_cleanup()
- self.assertGreaterEqual(used, 0)
- # we don't lose the value
- greenlet._greenlet.enable_optional_cleanup(True)
- used2 = greenlet._greenlet.get_clocks_used_doing_optional_cleanup()
- self.assertEqual(used, used2)
- self.assertGreater(greenlet._greenlet.CLOCKS_PER_SEC, 1)
-
- def _check_issue251(self,
- manually_collect_background=True,
- explicit_reference_to_switch=False):
- # See https://github.com/python-greenlet/greenlet/issues/251
- # Killing a greenlet (probably not the main one)
- # in one thread from another thread would
- # result in leaking a list (the ts_delkey list).
- # We no longer use lists to hold that stuff, though.
-
- # For the test to be valid, even empty lists have to be tracked by the
- # GC
-
- assert gc.is_tracked([])
- HasFinalizerTracksInstances.reset()
- greenlet.getcurrent()
- greenlets_before = self.count_objects(greenlet.greenlet, exact_kind=False)
-
- background_glet_running = threading.Event()
- background_glet_killed = threading.Event()
- background_greenlets = []
-
- # XXX: Switching this to a greenlet subclass that overrides
- # run results in all callers failing the leaktest; that
- # greenlet instance is leaked. There's a bound method for
- # run() living on the stack of the greenlet in g_initialstub,
- # and since we don't manually switch back to the background
- # greenlet to let it "fall off the end" and exit the
- # g_initialstub function, it never gets cleaned up. Making the
- # garbage collector aware of this bound method (making it an
- # attribute of the greenlet structure and traversing into it)
- # doesn't help, for some reason.
- def background_greenlet():
- # Throw control back to the main greenlet.
- jd = HasFinalizerTracksInstances("DELETING STACK OBJECT")
- greenlet._greenlet.set_thread_local(
- 'test_leaks_key',
- HasFinalizerTracksInstances("DELETING THREAD STATE"))
- # Explicitly keeping 'switch' in a local variable
- # breaks this test in all versions
- if explicit_reference_to_switch:
- s = greenlet.getcurrent().parent.switch
- s([jd])
- else:
- greenlet.getcurrent().parent.switch([jd])
-
- bg_main_wrefs = []
-
- def background_thread():
- glet = greenlet.greenlet(background_greenlet)
- bg_main_wrefs.append(weakref.ref(glet.parent))
-
- background_greenlets.append(glet)
- glet.switch() # Be sure it's active.
- # Control is ours again.
- del glet # Delete one reference from the thread it runs in.
- background_glet_running.set()
- background_glet_killed.wait(10)
-
- # To trigger the background collection of the dead
- # greenlet, thus clearing out the contents of the list, we
- # need to run some APIs. See issue 252.
- if manually_collect_background:
- greenlet.getcurrent()
-
-
- t = threading.Thread(target=background_thread)
- t.start()
- background_glet_running.wait(10)
- greenlet.getcurrent()
- lists_before = self.count_objects(list, exact_kind=True)
-
- assert len(background_greenlets) == 1
- self.assertFalse(background_greenlets[0].dead)
- # Delete the last reference to the background greenlet
- # from a different thread. This puts it in the background thread's
- # ts_delkey list.
- del background_greenlets[:]
- background_glet_killed.set()
-
- # Now wait for the background thread to die.
- t.join(10)
- del t
- # As part of the fix for 252, we need to cycle the ceval.c
- # interpreter loop to be sure it has had a chance to process
- # the pending call.
- self.wait_for_pending_cleanups()
-
- lists_after = self.count_objects(list, exact_kind=True)
- greenlets_after = self.count_objects(greenlet.greenlet, exact_kind=False)
-
- # On 2.7, we observe that lists_after is smaller than
- # lists_before. No idea what lists got cleaned up. All the
- # Python 3 versions match exactly.
- self.assertLessEqual(lists_after, lists_before)
- # On versions after 3.6, we've successfully cleaned up the
- # greenlet references thanks to the internal "vectorcall"
- # protocol; prior to that, there is a reference path through
- # the ``greenlet.switch`` method still on the stack that we
- # can't reach to clean up. The C code goes through terrific
- # lengths to clean that up.
- if not explicit_reference_to_switch \
- and greenlet._greenlet.get_clocks_used_doing_optional_cleanup() is not None:
- # If cleanup was disabled, though, we may not find it.
- self.assertEqual(greenlets_after, greenlets_before)
- if manually_collect_background:
- # TODO: Figure out how to make this work!
- # The one on the stack is still leaking somehow
- # in the non-manually-collect state.
- self.assertEqual(HasFinalizerTracksInstances.EXTANT_INSTANCES, set())
- else:
- # The explicit reference prevents us from collecting it
- # and it isn't always found by the GC either for some
- # reason. The entire frame is leaked somehow, on some
- # platforms (e.g., MacPorts builds of Python (all
- # versions!)), but not on other platforms (the linux and
- # windows builds on GitHub actions and Appveyor). So we'd
- # like to write a test that proves that the main greenlet
- # sticks around, and we can on my machine (macOS 11.6,
- # MacPorts builds of everything) but we can't write that
- # same test on other platforms. However, hopefully iteration
- # done by leakcheck will find it.
- pass
-
- if greenlet._greenlet.get_clocks_used_doing_optional_cleanup() is not None:
- self.assertClocksUsed()
-
- def test_issue251_killing_cross_thread_leaks_list(self):
- self._check_issue251()
-
- def test_issue251_with_cleanup_disabled(self):
- greenlet._greenlet.enable_optional_cleanup(False)
- try:
- self._check_issue251()
- finally:
- greenlet._greenlet.enable_optional_cleanup(True)
-
- @fails_leakcheck
- def test_issue251_issue252_need_to_collect_in_background(self):
- # Between greenlet 1.1.2 and the next version, this was still
- # failing because the leak of the list still exists when we
- # don't call a greenlet API before exiting the thread. The
- # proximate cause is that neither of the two greenlets from
- # the background thread are actually being destroyed, even
- # though the GC is in fact visiting both objects. It's not
- # clear where that leak is? For some reason the thread-local
- # dict holding it isn't being cleaned up.
- #
- # The leak, I think, is in the CPYthon internal function that
- # calls into green_switch(). The argument tuple is still on
- # the C stack somewhere and can't be reached? That doesn't
- # make sense, because the tuple should be collectable when
- # this object goes away.
- #
- # Note that this test sometimes spuriously passes on Linux,
- # for some reason, but I've never seen it pass on macOS.
- self._check_issue251(manually_collect_background=False)
-
- @fails_leakcheck
- def test_issue251_issue252_need_to_collect_in_background_cleanup_disabled(self):
- self.expect_greenlet_leak = True
- greenlet._greenlet.enable_optional_cleanup(False)
- try:
- self._check_issue251(manually_collect_background=False)
- finally:
- greenlet._greenlet.enable_optional_cleanup(True)
-
- @fails_leakcheck
- def test_issue251_issue252_explicit_reference_not_collectable(self):
- self._check_issue251(
- manually_collect_background=False,
- explicit_reference_to_switch=True)
-
- UNTRACK_ATTEMPTS = 100
-
- def _only_test_some_versions(self):
- # We're only looking for this problem specifically on 3.11,
- # and this set of tests is relatively fragile, depending on
- # OS and memory management details. So we want to run it on 3.11+
- # (obviously) but not every older 3.x version in order to reduce
- # false negatives. At the moment, those false results seem to have
- # resolved, so we are actually running this on 3.8+
- assert sys.version_info[0] >= 3
- if sys.version_info[:2] < (3, 8):
- self.skipTest('Only observed on 3.11')
- if RUNNING_ON_MANYLINUX:
- self.skipTest("Slow and not worth repeating here")
-
- @ignores_leakcheck
- # Because we're just trying to track raw memory, not objects, and running
- # the leakcheck makes an already slow test slower.
- def test_untracked_memory_doesnt_increase(self):
- # See https://github.com/gevent/gevent/issues/1924
- # and https://github.com/python-greenlet/greenlet/issues/328
- self._only_test_some_versions()
- def f():
- return 1
-
- ITER = 10000
- def run_it():
- for _ in range(ITER):
- greenlet.greenlet(f).switch()
-
- # Establish baseline
- for _ in range(3):
- run_it()
-
- # uss: (Linux, macOS, Windows): aka "Unique Set Size", this is
- # the memory which is unique to a process and which would be
- # freed if the process was terminated right now.
- uss_before = self.get_process_uss()
-
- for count in range(self.UNTRACK_ATTEMPTS):
- uss_before = max(uss_before, self.get_process_uss())
- run_it()
-
- uss_after = self.get_process_uss()
- if uss_after <= uss_before and count > 1:
- break
-
- self.assertLessEqual(uss_after, uss_before)
-
- def _check_untracked_memory_thread(self, deallocate_in_thread=True):
- self._only_test_some_versions()
- # Like the above test, but what if there are a bunch of
- # unfinished greenlets in a thread that dies?
- # Does it matter if we deallocate in the thread or not?
- EXIT_COUNT = [0]
-
- def f():
- try:
- greenlet.getcurrent().parent.switch()
- except greenlet.GreenletExit:
- EXIT_COUNT[0] += 1
- raise
- return 1
-
- ITER = 10000
- def run_it():
- glets = []
- for _ in range(ITER):
- # Greenlet starts, switches back to us.
- # We keep a strong reference to the greenlet though so it doesn't
- # get a GreenletExit exception.
- g = greenlet.greenlet(f)
- glets.append(g)
- g.switch()
-
- return glets
-
- test = self
-
- class ThreadFunc:
- uss_before = uss_after = 0
- glets = ()
- ITER = 2
- def __call__(self):
- self.uss_before = test.get_process_uss()
-
- for _ in range(self.ITER):
- self.glets += tuple(run_it())
-
- for g in self.glets:
- test.assertIn('suspended active', str(g))
- # Drop them.
- if deallocate_in_thread:
- self.glets = ()
- self.uss_after = test.get_process_uss()
-
- # Establish baseline
- uss_before = uss_after = None
- for count in range(self.UNTRACK_ATTEMPTS):
- EXIT_COUNT[0] = 0
- thread_func = ThreadFunc()
- t = threading.Thread(target=thread_func)
- t.start()
- t.join(30)
- self.assertFalse(t.is_alive())
-
- if uss_before is None:
- uss_before = thread_func.uss_before
-
- uss_before = max(uss_before, thread_func.uss_before)
- if deallocate_in_thread:
- self.assertEqual(thread_func.glets, ())
- self.assertEqual(EXIT_COUNT[0], ITER * thread_func.ITER)
-
- del thread_func # Deallocate the greenlets; but this won't raise into them
- del t
- if not deallocate_in_thread:
- self.assertEqual(EXIT_COUNT[0], 0)
- if deallocate_in_thread:
- self.wait_for_pending_cleanups()
-
- uss_after = self.get_process_uss()
- # See if we achieve a non-growth state at some point. Break when we do.
- if uss_after <= uss_before and count > 1:
- break
-
- self.wait_for_pending_cleanups()
- uss_after = self.get_process_uss()
- self.assertLessEqual(uss_after, uss_before, "after attempts %d" % (count,))
-
- @ignores_leakcheck
- # Because we're just trying to track raw memory, not objects, and running
- # the leakcheck makes an already slow test slower.
- def test_untracked_memory_doesnt_increase_unfinished_thread_dealloc_in_thread(self):
- self._check_untracked_memory_thread(deallocate_in_thread=True)
-
- @ignores_leakcheck
- # Because the main greenlets from the background threads do not exit in a timely fashion,
- # we fail the object-based leakchecks.
- def test_untracked_memory_doesnt_increase_unfinished_thread_dealloc_in_main(self):
- self._check_untracked_memory_thread(deallocate_in_thread=False)
-
-if __name__ == '__main__':
- __import__('unittest').main()
diff --git a/venv/lib/python3.11/site-packages/greenlet/tests/test_stack_saved.py b/venv/lib/python3.11/site-packages/greenlet/tests/test_stack_saved.py
deleted file mode 100644
index b362bf9..0000000
--- a/venv/lib/python3.11/site-packages/greenlet/tests/test_stack_saved.py
+++ /dev/null
@@ -1,19 +0,0 @@
-import greenlet
-from . import TestCase
-
-
-class Test(TestCase):
-
- def test_stack_saved(self):
- main = greenlet.getcurrent()
- self.assertEqual(main._stack_saved, 0)
-
- def func():
- main.switch(main._stack_saved)
-
- g = greenlet.greenlet(func)
- x = g.switch()
- self.assertGreater(x, 0)
- self.assertGreater(g._stack_saved, 0)
- g.switch()
- self.assertEqual(g._stack_saved, 0)
diff --git a/venv/lib/python3.11/site-packages/greenlet/tests/test_throw.py b/venv/lib/python3.11/site-packages/greenlet/tests/test_throw.py
deleted file mode 100644
index f4f9a14..0000000
--- a/venv/lib/python3.11/site-packages/greenlet/tests/test_throw.py
+++ /dev/null
@@ -1,128 +0,0 @@
-import sys
-
-
-from greenlet import greenlet
-from . import TestCase
-
-def switch(*args):
- return greenlet.getcurrent().parent.switch(*args)
-
-
-class ThrowTests(TestCase):
- def test_class(self):
- def f():
- try:
- switch("ok")
- except RuntimeError:
- switch("ok")
- return
- switch("fail")
- g = greenlet(f)
- res = g.switch()
- self.assertEqual(res, "ok")
- res = g.throw(RuntimeError)
- self.assertEqual(res, "ok")
-
- def test_val(self):
- def f():
- try:
- switch("ok")
- except RuntimeError:
- val = sys.exc_info()[1]
- if str(val) == "ciao":
- switch("ok")
- return
- switch("fail")
-
- g = greenlet(f)
- res = g.switch()
- self.assertEqual(res, "ok")
- res = g.throw(RuntimeError("ciao"))
- self.assertEqual(res, "ok")
-
- g = greenlet(f)
- res = g.switch()
- self.assertEqual(res, "ok")
- res = g.throw(RuntimeError, "ciao")
- self.assertEqual(res, "ok")
-
- def test_kill(self):
- def f():
- switch("ok")
- switch("fail")
- g = greenlet(f)
- res = g.switch()
- self.assertEqual(res, "ok")
- res = g.throw()
- self.assertTrue(isinstance(res, greenlet.GreenletExit))
- self.assertTrue(g.dead)
- res = g.throw() # immediately eaten by the already-dead greenlet
- self.assertTrue(isinstance(res, greenlet.GreenletExit))
-
- def test_throw_goes_to_original_parent(self):
- main = greenlet.getcurrent()
-
- def f1():
- try:
- main.switch("f1 ready to catch")
- except IndexError:
- return "caught"
- return "normal exit"
-
- def f2():
- main.switch("from f2")
-
- g1 = greenlet(f1)
- g2 = greenlet(f2, parent=g1)
- with self.assertRaises(IndexError):
- g2.throw(IndexError)
- self.assertTrue(g2.dead)
- self.assertTrue(g1.dead)
-
- g1 = greenlet(f1)
- g2 = greenlet(f2, parent=g1)
- res = g1.switch()
- self.assertEqual(res, "f1 ready to catch")
- res = g2.throw(IndexError)
- self.assertEqual(res, "caught")
- self.assertTrue(g2.dead)
- self.assertTrue(g1.dead)
-
- g1 = greenlet(f1)
- g2 = greenlet(f2, parent=g1)
- res = g1.switch()
- self.assertEqual(res, "f1 ready to catch")
- res = g2.switch()
- self.assertEqual(res, "from f2")
- res = g2.throw(IndexError)
- self.assertEqual(res, "caught")
- self.assertTrue(g2.dead)
- self.assertTrue(g1.dead)
-
- def test_non_traceback_param(self):
- with self.assertRaises(TypeError) as exc:
- greenlet.getcurrent().throw(
- Exception,
- Exception(),
- self
- )
- self.assertEqual(str(exc.exception),
- "throw() third argument must be a traceback object")
-
- def test_instance_of_wrong_type(self):
- with self.assertRaises(TypeError) as exc:
- greenlet.getcurrent().throw(
- Exception(),
- BaseException()
- )
-
- self.assertEqual(str(exc.exception),
- "instance exception may not have a separate value")
-
- def test_not_throwable(self):
- with self.assertRaises(TypeError) as exc:
- greenlet.getcurrent().throw(
- "abc"
- )
- self.assertEqual(str(exc.exception),
- "exceptions must be classes, or instances, not str")
diff --git a/venv/lib/python3.11/site-packages/greenlet/tests/test_tracing.py b/venv/lib/python3.11/site-packages/greenlet/tests/test_tracing.py
deleted file mode 100644
index c044d4b..0000000
--- a/venv/lib/python3.11/site-packages/greenlet/tests/test_tracing.py
+++ /dev/null
@@ -1,291 +0,0 @@
-from __future__ import print_function
-import sys
-import greenlet
-import unittest
-
-from . import TestCase
-from . import PY312
-
-# https://discuss.python.org/t/cpython-3-12-greenlet-and-tracing-profiling-how-to-not-crash-and-get-correct-results/33144/2
-DEBUG_BUILD_PY312 = (
- PY312 and hasattr(sys, 'gettotalrefcount'),
- "Broken on debug builds of Python 3.12"
-)
-
-class SomeError(Exception):
- pass
-
-class GreenletTracer(object):
- oldtrace = None
-
- def __init__(self, error_on_trace=False):
- self.actions = []
- self.error_on_trace = error_on_trace
-
- def __call__(self, *args):
- self.actions.append(args)
- if self.error_on_trace:
- raise SomeError
-
- def __enter__(self):
- self.oldtrace = greenlet.settrace(self)
- return self.actions
-
- def __exit__(self, *args):
- greenlet.settrace(self.oldtrace)
-
-
-class TestGreenletTracing(TestCase):
- """
- Tests of ``greenlet.settrace()``
- """
-
- def test_a_greenlet_tracing(self):
- main = greenlet.getcurrent()
- def dummy():
- pass
- def dummyexc():
- raise SomeError()
-
- with GreenletTracer() as actions:
- g1 = greenlet.greenlet(dummy)
- g1.switch()
- g2 = greenlet.greenlet(dummyexc)
- self.assertRaises(SomeError, g2.switch)
-
- self.assertEqual(actions, [
- ('switch', (main, g1)),
- ('switch', (g1, main)),
- ('switch', (main, g2)),
- ('throw', (g2, main)),
- ])
-
- def test_b_exception_disables_tracing(self):
- main = greenlet.getcurrent()
- def dummy():
- main.switch()
- g = greenlet.greenlet(dummy)
- g.switch()
- with GreenletTracer(error_on_trace=True) as actions:
- self.assertRaises(SomeError, g.switch)
- self.assertEqual(greenlet.gettrace(), None)
-
- self.assertEqual(actions, [
- ('switch', (main, g)),
- ])
-
- def test_set_same_tracer_twice(self):
- # https://github.com/python-greenlet/greenlet/issues/332
- # Our logic in asserting that the tracefunction should
- # gain a reference was incorrect if the same tracefunction was set
- # twice.
- tracer = GreenletTracer()
- with tracer:
- greenlet.settrace(tracer)
-
-
-class PythonTracer(object):
- oldtrace = None
-
- def __init__(self):
- self.actions = []
-
- def __call__(self, frame, event, arg):
- # Record the co_name so we have an idea what function we're in.
- self.actions.append((event, frame.f_code.co_name))
-
- def __enter__(self):
- self.oldtrace = sys.setprofile(self)
- return self.actions
-
- def __exit__(self, *args):
- sys.setprofile(self.oldtrace)
-
-def tpt_callback():
- return 42
-
-class TestPythonTracing(TestCase):
- """
- Tests of the interaction of ``sys.settrace()``
- with greenlet facilities.
-
- NOTE: Most of this is probably CPython specific.
- """
-
- maxDiff = None
-
- def test_trace_events_trivial(self):
- with PythonTracer() as actions:
- tpt_callback()
- # If we use the sys.settrace instead of setprofile, we get
- # this:
-
- # self.assertEqual(actions, [
- # ('call', 'tpt_callback'),
- # ('call', '__exit__'),
- # ])
-
- self.assertEqual(actions, [
- ('return', '__enter__'),
- ('call', 'tpt_callback'),
- ('return', 'tpt_callback'),
- ('call', '__exit__'),
- ('c_call', '__exit__'),
- ])
-
- def _trace_switch(self, glet):
- with PythonTracer() as actions:
- glet.switch()
- return actions
-
- def _check_trace_events_func_already_set(self, glet):
- actions = self._trace_switch(glet)
- self.assertEqual(actions, [
- ('return', '__enter__'),
- ('c_call', '_trace_switch'),
- ('call', 'run'),
- ('call', 'tpt_callback'),
- ('return', 'tpt_callback'),
- ('return', 'run'),
- ('c_return', '_trace_switch'),
- ('call', '__exit__'),
- ('c_call', '__exit__'),
- ])
-
- def test_trace_events_into_greenlet_func_already_set(self):
- def run():
- return tpt_callback()
-
- self._check_trace_events_func_already_set(greenlet.greenlet(run))
-
- def test_trace_events_into_greenlet_subclass_already_set(self):
- class X(greenlet.greenlet):
- def run(self):
- return tpt_callback()
- self._check_trace_events_func_already_set(X())
-
- def _check_trace_events_from_greenlet_sets_profiler(self, g, tracer):
- g.switch()
- tpt_callback()
- tracer.__exit__()
- self.assertEqual(tracer.actions, [
- ('return', '__enter__'),
- ('call', 'tpt_callback'),
- ('return', 'tpt_callback'),
- ('return', 'run'),
- ('call', 'tpt_callback'),
- ('return', 'tpt_callback'),
- ('call', '__exit__'),
- ('c_call', '__exit__'),
- ])
-
-
- def test_trace_events_from_greenlet_func_sets_profiler(self):
- tracer = PythonTracer()
- def run():
- tracer.__enter__()
- return tpt_callback()
-
- self._check_trace_events_from_greenlet_sets_profiler(greenlet.greenlet(run),
- tracer)
-
- def test_trace_events_from_greenlet_subclass_sets_profiler(self):
- tracer = PythonTracer()
- class X(greenlet.greenlet):
- def run(self):
- tracer.__enter__()
- return tpt_callback()
-
- self._check_trace_events_from_greenlet_sets_profiler(X(), tracer)
-
- @unittest.skipIf(*DEBUG_BUILD_PY312)
- def test_trace_events_multiple_greenlets_switching(self):
- tracer = PythonTracer()
-
- g1 = None
- g2 = None
-
- def g1_run():
- tracer.__enter__()
- tpt_callback()
- g2.switch()
- tpt_callback()
- return 42
-
- def g2_run():
- tpt_callback()
- tracer.__exit__()
- tpt_callback()
- g1.switch()
-
- g1 = greenlet.greenlet(g1_run)
- g2 = greenlet.greenlet(g2_run)
-
- x = g1.switch()
- self.assertEqual(x, 42)
- tpt_callback() # ensure not in the trace
- self.assertEqual(tracer.actions, [
- ('return', '__enter__'),
- ('call', 'tpt_callback'),
- ('return', 'tpt_callback'),
- ('c_call', 'g1_run'),
- ('call', 'g2_run'),
- ('call', 'tpt_callback'),
- ('return', 'tpt_callback'),
- ('call', '__exit__'),
- ('c_call', '__exit__'),
- ])
-
- @unittest.skipIf(*DEBUG_BUILD_PY312)
- def test_trace_events_multiple_greenlets_switching_siblings(self):
- # Like the first version, but get both greenlets running first
- # as "siblings" and then establish the tracing.
- tracer = PythonTracer()
-
- g1 = None
- g2 = None
-
- def g1_run():
- greenlet.getcurrent().parent.switch()
- tracer.__enter__()
- tpt_callback()
- g2.switch()
- tpt_callback()
- return 42
-
- def g2_run():
- greenlet.getcurrent().parent.switch()
-
- tpt_callback()
- tracer.__exit__()
- tpt_callback()
- g1.switch()
-
- g1 = greenlet.greenlet(g1_run)
- g2 = greenlet.greenlet(g2_run)
-
- # Start g1
- g1.switch()
- # And it immediately returns control to us.
- # Start g2
- g2.switch()
- # Which also returns. Now kick of the real part of the
- # test.
- x = g1.switch()
- self.assertEqual(x, 42)
-
- tpt_callback() # ensure not in the trace
- self.assertEqual(tracer.actions, [
- ('return', '__enter__'),
- ('call', 'tpt_callback'),
- ('return', 'tpt_callback'),
- ('c_call', 'g1_run'),
- ('call', 'tpt_callback'),
- ('return', 'tpt_callback'),
- ('call', '__exit__'),
- ('c_call', '__exit__'),
- ])
-
-
-if __name__ == '__main__':
- unittest.main()
diff --git a/venv/lib/python3.11/site-packages/greenlet/tests/test_version.py b/venv/lib/python3.11/site-packages/greenlet/tests/test_version.py
deleted file mode 100644
index 96c17cf..0000000
--- a/venv/lib/python3.11/site-packages/greenlet/tests/test_version.py
+++ /dev/null
@@ -1,41 +0,0 @@
-#! /usr/bin/env python
-from __future__ import absolute_import
-from __future__ import print_function
-
-import sys
-import os
-from unittest import TestCase as NonLeakingTestCase
-
-import greenlet
-
-# No reason to run this multiple times under leakchecks,
-# it doesn't do anything.
-class VersionTests(NonLeakingTestCase):
- def test_version(self):
- def find_dominating_file(name):
- if os.path.exists(name):
- return name
-
- tried = []
- here = os.path.abspath(os.path.dirname(__file__))
- for i in range(10):
- up = ['..'] * i
- path = [here] + up + [name]
- fname = os.path.join(*path)
- fname = os.path.abspath(fname)
- tried.append(fname)
- if os.path.exists(fname):
- return fname
- raise AssertionError("Could not find file " + name + "; checked " + str(tried))
-
- try:
- setup_py = find_dominating_file('setup.py')
- except AssertionError as e:
- self.skipTest("Unable to find setup.py; must be out of tree. " + str(e))
-
-
- invoke_setup = "%s %s --version" % (sys.executable, setup_py)
- with os.popen(invoke_setup) as f:
- sversion = f.read().strip()
-
- self.assertEqual(sversion, greenlet.__version__)
diff --git a/venv/lib/python3.11/site-packages/greenlet/tests/test_weakref.py b/venv/lib/python3.11/site-packages/greenlet/tests/test_weakref.py
deleted file mode 100644
index 05a38a7..0000000
--- a/venv/lib/python3.11/site-packages/greenlet/tests/test_weakref.py
+++ /dev/null
@@ -1,35 +0,0 @@
-import gc
-import weakref
-
-
-import greenlet
-from . import TestCase
-
-class WeakRefTests(TestCase):
- def test_dead_weakref(self):
- def _dead_greenlet():
- g = greenlet.greenlet(lambda: None)
- g.switch()
- return g
- o = weakref.ref(_dead_greenlet())
- gc.collect()
- self.assertEqual(o(), None)
-
- def test_inactive_weakref(self):
- o = weakref.ref(greenlet.greenlet())
- gc.collect()
- self.assertEqual(o(), None)
-
- def test_dealloc_weakref(self):
- seen = []
- def worker():
- try:
- greenlet.getcurrent().parent.switch()
- finally:
- seen.append(g())
- g = greenlet.greenlet(worker)
- g.switch()
- g2 = greenlet.greenlet(lambda: None, g)
- g = weakref.ref(g2)
- g2 = None
- self.assertEqual(seen, [None])