Загрузить файлы в «venv/Lib/site-packages/greenlet»
This commit is contained in:
76
venv/Lib/site-packages/greenlet/greenlet_allocator.hpp
Normal file
76
venv/Lib/site-packages/greenlet/greenlet_allocator.hpp
Normal file
@@ -0,0 +1,76 @@
|
||||
#ifndef GREENLET_ALLOCATOR_HPP
|
||||
#define GREENLET_ALLOCATOR_HPP
|
||||
|
||||
#define PY_SSIZE_T_CLEAN
|
||||
#include <Python.h>
|
||||
#include <memory>
|
||||
#include "greenlet_compiler_compat.hpp"
|
||||
#include "greenlet_cpython_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) {
|
||||
#ifdef Py_GIL_DISABLED
|
||||
p = PyMem_Malloc(sizeof(T) * number_objects);
|
||||
#else
|
||||
p = PyObject_Malloc(sizeof(T));
|
||||
#endif
|
||||
}
|
||||
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) {
|
||||
#ifdef Py_GIL_DISABLED
|
||||
PyMem_Free(p);
|
||||
#else
|
||||
PyObject_Free(p);
|
||||
#endif
|
||||
}
|
||||
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
|
||||
98
venv/Lib/site-packages/greenlet/greenlet_compiler_compat.hpp
Normal file
98
venv/Lib/site-packages/greenlet/greenlet_compiler_compat.hpp
Normal file
@@ -0,0 +1,98 @@
|
||||
/* -*- 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>
|
||||
|
||||
# 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
|
||||
|
||||
#if defined(__GNUC__) && defined(__POWERPC__) && defined(__APPLE__)
|
||||
// 32-bit PPC/MacOSX. Only known to be tested on unreleased versions
|
||||
// of macOS 10.6 using a macports build gcc 14. It appears that
|
||||
// running C++ destructors of thread-local variables is broken.
|
||||
|
||||
// See https://github.com/python-greenlet/greenlet/pull/419
|
||||
# define GREENLET_BROKEN_THREAD_LOCAL_CLEANUP_JUST_LEAK 1
|
||||
#else
|
||||
# define GREENLET_BROKEN_THREAD_LOCAL_CLEANUP_JUST_LEAK 0
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
117
venv/Lib/site-packages/greenlet/greenlet_cpython_compat.hpp
Normal file
117
venv/Lib/site-packages/greenlet/greenlet_cpython_compat.hpp
Normal file
@@ -0,0 +1,117 @@
|
||||
/* -*- 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"
|
||||
|
||||
/*
|
||||
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.
|
||||
|
||||
Python 3.13 removed PyThreadState.cframe (GH-108035).
|
||||
*/
|
||||
#if PY_VERSION_HEX < 0x30D0000
|
||||
# define GREENLET_USE_CFRAME 1
|
||||
#else
|
||||
# define GREENLET_USE_CFRAME 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
|
||||
|
||||
#if PY_VERSION_HEX >= 0x30D0000
|
||||
# define GREENLET_PY313 1
|
||||
#else
|
||||
# define GREENLET_PY313 0
|
||||
#endif
|
||||
|
||||
#if PY_VERSION_HEX >= 0x30E0000
|
||||
# define GREENLET_PY314 1
|
||||
#else
|
||||
# define GREENLET_PY314 0
|
||||
#endif
|
||||
|
||||
#if PY_VERSION_HEX >= 0x30F0000
|
||||
# define GREENLET_PY315 1
|
||||
#else
|
||||
# define GREENLET_PY315 0
|
||||
#endif
|
||||
|
||||
|
||||
/* _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.
|
||||
*/
|
||||
#if defined(Py_REF_DEBUG) && !GREENLET_PY312
|
||||
# define GREENLET_Py_DEC_REFTOTAL _Py_RefTotal--
|
||||
#else
|
||||
# define GREENLET_Py_DEC_REFTOTAL
|
||||
#endif
|
||||
|
||||
|
||||
#define G_TPFLAGS_DEFAULT Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_VERSION_TAG | Py_TPFLAGS_HAVE_GC
|
||||
|
||||
|
||||
// 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++;
|
||||
tstate->cframe->use_tracing = 0;
|
||||
}
|
||||
#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);
|
||||
tstate->cframe->use_tracing = use_tracing;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(Py_C_RECURSION_LIMIT) && defined(C_RECURSION_LIMIT)
|
||||
# define Py_C_RECURSION_LIMIT C_RECURSION_LIMIT
|
||||
#endif
|
||||
|
||||
// Py_IsFinalizing() became a public API in Python 3.13. Map it to the
|
||||
// private _Py_IsFinalizing() on older versions so all call sites can
|
||||
// use the standard name. Remove this once greenlet drops support for
|
||||
// Python < 3.13.
|
||||
#if !GREENLET_PY313
|
||||
# define Py_IsFinalizing() _Py_IsFinalizing()
|
||||
#endif
|
||||
|
||||
#endif /* GREENLET_CPYTHON_COMPAT_H */
|
||||
171
venv/Lib/site-packages/greenlet/greenlet_exceptions.hpp
Normal file
171
venv/Lib/site-packages/greenlet/greenlet_exceptions.hpp
Normal file
@@ -0,0 +1,171 @@
|
||||
#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());
|
||||
}
|
||||
|
||||
PyErrOccurred(PyObject* exc_kind,
|
||||
const std::string msg, //This is the format
|
||||
//string; that's not
|
||||
//usually safe!
|
||||
|
||||
PyObject* borrowed_obj_one, PyObject* borrowed_obj_two)
|
||||
: std::runtime_error(msg)
|
||||
{
|
||||
|
||||
//This is designed specifically for the
|
||||
//``check_switch_allowed`` function.
|
||||
|
||||
// PyObject_Str and PyObject_Repr are safe to call with
|
||||
// NULL pointers; they return the string "<NULL>" in that
|
||||
// case.
|
||||
// This function always returns null.
|
||||
PyErr_Format(exc_kind,
|
||||
msg.c_str(),
|
||||
borrowed_obj_one, borrowed_obj_two);
|
||||
}
|
||||
};
|
||||
|
||||
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
|
||||
109
venv/Lib/site-packages/greenlet/greenlet_internal.hpp
Normal file
109
venv/Lib/site-packages/greenlet/greenlet_internal.hpp
Normal file
@@ -0,0 +1,109 @@
|
||||
/* -*- 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"
|
||||
#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 "TGreenlet.hpp"
|
||||
#include "greenlet_allocator.hpp"
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#define GREENLET_MODULE
|
||||
struct _greenlet;
|
||||
typedef struct _greenlet PyGreenlet;
|
||||
namespace greenlet {
|
||||
|
||||
class ThreadState;
|
||||
// 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;
|
||||
};
|
||||
|
||||
|
||||
#define implementation_ptr_t greenlet::Greenlet*
|
||||
|
||||
|
||||
#include "greenlet.h"
|
||||
|
||||
void
|
||||
greenlet::refs::MainGreenletExactChecker(void *p)
|
||||
{
|
||||
if (!p) {
|
||||
return;
|
||||
}
|
||||
if (greenlet::IsShuttingDown()) {
|
||||
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 = static_cast<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 PyObject* green_switch(PyGreenlet* self, PyObject* args, PyObject* kwargs);
|
||||
|
||||
|
||||
#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:
|
||||
Reference in New Issue
Block a user