mirror of
https://github.com/panda3d/panda3d.git
synced 2025-09-26 22:53:16 -04:00
Merge branch 'release/1.10.x'
This commit is contained in:
commit
8cbe36b352
@ -151,7 +151,7 @@ PUBLISHED:
|
||||
|
||||
void obstacle_avoidance(float feeler_length = 1.0);
|
||||
|
||||
void path_follow(float follow_wt);
|
||||
void path_follow(float follow_wt = 1.0f);
|
||||
void add_to_path(LVecBase3 pos);
|
||||
void start_follow(std::string type = "normal");
|
||||
|
||||
|
@ -331,7 +331,7 @@ update_motion_trail (PN_stdfloat current_time, LMatrix4 *transform) {
|
||||
|
||||
frame_iterator = _frame_list.begin ( );
|
||||
motion_trail_frame = *frame_iterator;
|
||||
if (*transform == motion_trail_frame._transform) {
|
||||
if (motion_trail_frame._transform == UnalignedLMatrix4(*transform)) {
|
||||
// duplicate transform
|
||||
return;
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ pallocator_single(TypeHandle type_handle) noexcept :
|
||||
|
||||
template<class Type>
|
||||
INLINE Type *pallocator_single<Type>::
|
||||
allocate(typename pallocator_single<Type>::size_type n, typename std::allocator<void>::const_pointer) {
|
||||
allocate(typename pallocator_single<Type>::size_type n, const void *) {
|
||||
TAU_PROFILE("pallocator_single:allocate()", " ", TAU_USER);
|
||||
// This doesn't support allocating arrays.
|
||||
assert(n == 1);
|
||||
@ -30,7 +30,7 @@ allocate(typename pallocator_single<Type>::size_type n, typename std::allocator<
|
||||
|
||||
template<class Type>
|
||||
INLINE void pallocator_single<Type>::
|
||||
deallocate(typename pallocator_single<Type>::pointer p, typename pallocator_single<Type>::size_type) {
|
||||
deallocate(Type *p, typename pallocator_single<Type>::size_type) {
|
||||
TAU_PROFILE("pallocator_single:deallocate()", " ", TAU_USER);
|
||||
StaticDeletedChain<Type>::deallocate(p, _type_handle);
|
||||
}
|
||||
@ -44,13 +44,13 @@ pallocator_array(TypeHandle type_handle) noexcept :
|
||||
|
||||
template<class Type>
|
||||
INLINE Type *pallocator_array<Type>::
|
||||
allocate(typename pallocator_array<Type>::size_type n, typename std::allocator<void>::const_pointer) {
|
||||
return (typename pallocator_array<Type>::pointer)
|
||||
allocate(typename pallocator_array<Type>::size_type n, const void *) {
|
||||
return (Type *)
|
||||
ASSUME_ALIGNED(_type_handle.allocate_array(n * sizeof(Type)), MEMORY_HOOK_ALIGNMENT);
|
||||
}
|
||||
|
||||
template<class Type>
|
||||
INLINE void pallocator_array<Type>::
|
||||
deallocate(typename pallocator_array<Type>::pointer p, typename pallocator_array<Type>::size_type) {
|
||||
deallocate(Type *p, typename pallocator_array<Type>::size_type) {
|
||||
_type_handle.deallocate_array((void *)p);
|
||||
}
|
||||
|
@ -46,10 +46,10 @@ class pallocator_single : public std::allocator<Type> {
|
||||
public:
|
||||
// Nowadays we cannot implicitly inherit typedefs from base classes in a
|
||||
// template class; we must explicitly copy them here.
|
||||
typedef typename std::allocator<Type>::pointer pointer;
|
||||
typedef typename std::allocator<Type>::reference reference;
|
||||
typedef typename std::allocator<Type>::const_pointer const_pointer;
|
||||
typedef typename std::allocator<Type>::const_reference const_reference;
|
||||
typedef Type *pointer;
|
||||
typedef Type &reference;
|
||||
typedef const Type *const_pointer;
|
||||
typedef const Type &const_reference;
|
||||
typedef typename std::allocator<Type>::size_type size_type;
|
||||
|
||||
INLINE pallocator_single(TypeHandle type_handle) noexcept;
|
||||
@ -59,9 +59,9 @@ public:
|
||||
INLINE pallocator_single(const pallocator_single<U> ©) noexcept :
|
||||
_type_handle(copy._type_handle) { }
|
||||
|
||||
INLINE Type *allocate(size_type n, std::allocator<void>::const_pointer hint = 0)
|
||||
INLINE Type *allocate(size_type n, const void *hint = 0)
|
||||
RETURNS_ALIGNED(MEMORY_HOOK_ALIGNMENT);
|
||||
INLINE void deallocate(pointer p, size_type n);
|
||||
INLINE void deallocate(Type *p, size_type n);
|
||||
|
||||
template<class U> struct rebind {
|
||||
typedef pallocator_single<U> other;
|
||||
@ -75,10 +75,10 @@ class pallocator_array : public std::allocator<Type> {
|
||||
public:
|
||||
// Nowadays we cannot implicitly inherit typedefs from base classes in a
|
||||
// template class; we must explicitly copy them here.
|
||||
typedef typename std::allocator<Type>::pointer pointer;
|
||||
typedef typename std::allocator<Type>::reference reference;
|
||||
typedef typename std::allocator<Type>::const_pointer const_pointer;
|
||||
typedef typename std::allocator<Type>::const_reference const_reference;
|
||||
typedef Type *pointer;
|
||||
typedef Type &reference;
|
||||
typedef const Type *const_pointer;
|
||||
typedef const Type &const_reference;
|
||||
typedef typename std::allocator<Type>::size_type size_type;
|
||||
|
||||
INLINE pallocator_array(TypeHandle type_handle = TypeHandle::none()) noexcept;
|
||||
@ -88,9 +88,9 @@ public:
|
||||
INLINE pallocator_array(const pallocator_array<U> ©) noexcept :
|
||||
_type_handle(copy._type_handle) { }
|
||||
|
||||
INLINE Type *allocate(size_type n, std::allocator<void>::const_pointer hint = 0)
|
||||
INLINE Type *allocate(size_type n, const void *hint = 0)
|
||||
RETURNS_ALIGNED(MEMORY_HOOK_ALIGNMENT);
|
||||
INLINE void deallocate(pointer p, size_type n);
|
||||
INLINE void deallocate(Type *p, size_type n);
|
||||
|
||||
template<class U> struct rebind {
|
||||
typedef pallocator_array<U> other;
|
||||
|
@ -4306,18 +4306,19 @@ int get_type_sort(CPPType *type) {
|
||||
TypeManager::is_struct(type)) {
|
||||
answer = 20;
|
||||
int deepest = 0;
|
||||
TypeIndex type_index = builder.get_type(TypeManager::unwrap(TypeManager::resolve_type(type)), false);
|
||||
InterrogateDatabase *idb = InterrogateDatabase::get_ptr();
|
||||
const InterrogateType &itype = idb->get_type(type_index);
|
||||
|
||||
if (itype.is_class() || itype.is_struct()) {
|
||||
int num_derivations = itype.number_of_derivations();
|
||||
for (int di = 0; di < num_derivations; di++) {
|
||||
TypeIndex d_type_Index = itype.get_derivation(di);
|
||||
const InterrogateType &d_itype = idb->get_type(d_type_Index);
|
||||
int this_one = get_type_sort(d_itype._cpptype);
|
||||
if (this_one > deepest) {
|
||||
deepest = this_one;
|
||||
// Sort such that more derived classes come first.
|
||||
type = TypeManager::unwrap(TypeManager::resolve_type(type));
|
||||
if (type != nullptr) {
|
||||
CPPStructType *struct_type = type->as_struct_type();
|
||||
if (struct_type != nullptr) {
|
||||
for (const CPPStructType::Base &base : struct_type->_derivation) {
|
||||
if (base._base != nullptr) {
|
||||
int this_one = get_type_sort(base._base);
|
||||
if (this_one > deepest) {
|
||||
deepest = this_one;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -137,6 +137,11 @@ typedef long Py_hash_t;
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Python 3.4 */
|
||||
#if PY_VERSION_HEX < 0x03040000
|
||||
#define PyGILState_Check() (PyGILState_GetThisThreadState() == _PyThreadState_Current)
|
||||
#endif
|
||||
|
||||
/* Python 3.6 */
|
||||
|
||||
#if PY_VERSION_HEX < 0x03080000 && !defined(_PyObject_CallNoArg)
|
||||
|
@ -84,13 +84,14 @@ PUBLISHED:
|
||||
BLOCKING void wait();
|
||||
BLOCKING void wait(double timeout);
|
||||
|
||||
EXTENSION(void set_result(PyObject *));
|
||||
|
||||
public:
|
||||
INLINE void set_result(std::nullptr_t);
|
||||
INLINE void set_result(TypedObject *result);
|
||||
INLINE void set_result(TypedReferenceCount *result);
|
||||
INLINE void set_result(TypedWritableReferenceCount *result);
|
||||
INLINE void set_result(const EventParameter &result);
|
||||
|
||||
public:
|
||||
void set_result(TypedObject *ptr, ReferenceCount *ref_ptr);
|
||||
|
||||
INLINE TypedObject *get_result() const;
|
||||
|
@ -15,14 +15,20 @@
|
||||
#include "asyncTaskSequence.h"
|
||||
#include "eventParameter.h"
|
||||
#include "paramValue.h"
|
||||
#include "paramPyObject.h"
|
||||
#include "pythonTask.h"
|
||||
#include "asyncTaskManager.h"
|
||||
#include "config_event.h"
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
|
||||
#ifndef CPPPARSER
|
||||
extern struct Dtool_PyTypedObject Dtool_AsyncFuture;
|
||||
extern struct Dtool_PyTypedObject Dtool_EventParameter;
|
||||
extern struct Dtool_PyTypedObject Dtool_ParamValueBase;
|
||||
extern struct Dtool_PyTypedObject Dtool_TypedObject;
|
||||
extern struct Dtool_PyTypedObject Dtool_TypedReferenceCount;
|
||||
extern struct Dtool_PyTypedObject Dtool_TypedWritableReferenceCount;
|
||||
#endif
|
||||
|
||||
/**
|
||||
@ -90,20 +96,24 @@ static PyObject *get_done_result(const AsyncFuture *future) {
|
||||
// EventStoreInt and Double are not exposed to Python for some reason.
|
||||
if (type == EventStoreInt::get_class_type()) {
|
||||
return Dtool_WrapValue(((EventStoreInt *)ptr)->get_value());
|
||||
} else if (type == EventStoreDouble::get_class_type()) {
|
||||
}
|
||||
else if (type == EventStoreDouble::get_class_type()) {
|
||||
return Dtool_WrapValue(((EventStoreDouble *)ptr)->get_value());
|
||||
}
|
||||
else if (type == ParamPyObject::get_class_type()) {
|
||||
return ((ParamPyObject *)ptr)->get_value();
|
||||
}
|
||||
|
||||
ParamValueBase *value = (ParamValueBase *)ptr;
|
||||
PyObject *wrap = DTool_CreatePyInstanceTyped
|
||||
((void *)value, Dtool_ParamValueBase, false, false, type.get_index());
|
||||
if (wrap != nullptr) {
|
||||
PyObject *value = PyObject_GetAttrString(wrap, "value");
|
||||
Py_DECREF(wrap);
|
||||
if (value != nullptr) {
|
||||
return value;
|
||||
}
|
||||
PyErr_Clear();
|
||||
Py_DECREF(wrap);
|
||||
}
|
||||
}
|
||||
|
||||
@ -154,6 +164,58 @@ __await__(PyObject *self) {
|
||||
return Dtool_NewGenerator(self, &gen_next);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets this future's result. Can only be called if done() returns false.
|
||||
*/
|
||||
void Extension<AsyncFuture>::
|
||||
set_result(PyObject *result) {
|
||||
if (result == Py_None) {
|
||||
_this->set_result(nullptr);
|
||||
return;
|
||||
}
|
||||
else if (DtoolInstance_Check(result)) {
|
||||
void *ptr;
|
||||
if ((ptr = DtoolInstance_UPCAST(result, Dtool_EventParameter))) {
|
||||
_this->set_result(*(const EventParameter *)ptr);
|
||||
return;
|
||||
}
|
||||
if ((ptr = DtoolInstance_UPCAST(result, Dtool_TypedWritableReferenceCount))) {
|
||||
_this->set_result((TypedWritableReferenceCount *)ptr);
|
||||
return;
|
||||
}
|
||||
if ((ptr = DtoolInstance_UPCAST(result, Dtool_TypedReferenceCount))) {
|
||||
_this->set_result((TypedReferenceCount *)ptr);
|
||||
return;
|
||||
}
|
||||
if ((ptr = DtoolInstance_UPCAST(result, Dtool_TypedObject))) {
|
||||
_this->set_result((TypedObject *)ptr);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (PyUnicode_Check(result)) {
|
||||
Py_ssize_t result_len;
|
||||
wchar_t *result_str = PyUnicode_AsWideCharString(result, &result_len);
|
||||
_this->set_result(new EventStoreWstring(std::wstring(result_str, result_len)));
|
||||
PyMem_Free(result_str);
|
||||
return;
|
||||
}
|
||||
else if (PyLongOrInt_Check(result)) {
|
||||
long result_val = PyLongOrInt_AS_LONG(result);
|
||||
if (result_val >= INT_MIN && result_val <= INT_MAX) {
|
||||
_this->set_result(new EventStoreInt((int)result_val));
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (PyNumber_Check(result)) {
|
||||
_this->set_result(new EventStoreDouble(PyFloat_AsDouble(result)));
|
||||
return;
|
||||
}
|
||||
|
||||
// If we don't recognize the type, store it as a generic PyObject pointer.
|
||||
ParamPyObject::init_type();
|
||||
_this->set_result(new ParamPyObject(result));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the result of this future, unless it was cancelled, in which case
|
||||
* it returns CancelledError.
|
||||
@ -285,8 +347,19 @@ gather(PyObject *args) {
|
||||
}
|
||||
} else if (PyCoro_CheckExact(item)) {
|
||||
// We allow passing in a coroutine instead of a future. This causes it
|
||||
// to be scheduled as a task.
|
||||
futures.push_back(new PythonTask(item));
|
||||
// to be scheduled as a task on the current task manager.
|
||||
PT(AsyncTask) task = new PythonTask(item);
|
||||
Thread *current_thread = Thread::get_current_thread();
|
||||
AsyncTask *current_task = (AsyncTask *)current_thread->get_current_task();
|
||||
if (current_task != nullptr) {
|
||||
task->set_task_chain(current_task->get_task_chain());
|
||||
current_task->get_manager()->add(task);
|
||||
}
|
||||
else {
|
||||
event_cat.warning()
|
||||
<< "gather() with coroutine not called from within a task; not scheduling with task manager.\n";
|
||||
}
|
||||
futures.push_back(task);
|
||||
continue;
|
||||
}
|
||||
return Dtool_Raise_ArgTypeError(item, i, "gather", "coroutine, task or future");
|
||||
|
@ -29,6 +29,7 @@ public:
|
||||
static PyObject *__await__(PyObject *self);
|
||||
static PyObject *__iter__(PyObject *self) { return __await__(self); }
|
||||
|
||||
void set_result(PyObject *result);
|
||||
PyObject *result(PyObject *timeout = Py_None) const;
|
||||
|
||||
PyObject *add_done_callback(PyObject *self, PyObject *fn);
|
||||
|
@ -84,7 +84,6 @@ PythonTask(PyObject *func_or_coro, const std::string &name) :
|
||||
*/
|
||||
PythonTask::
|
||||
~PythonTask() {
|
||||
#ifndef NDEBUG
|
||||
// If the coroutine threw an exception, and there was no opportunity to
|
||||
// handle it, let the user know.
|
||||
if (_exception != nullptr && !_retrieved_exception) {
|
||||
@ -97,7 +96,6 @@ PythonTask::
|
||||
_exc_value = nullptr;
|
||||
_exc_traceback = nullptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
Py_XDECREF(_function);
|
||||
Py_DECREF(_args);
|
||||
|
@ -3054,6 +3054,37 @@ glsl_report_program_errors(GLuint program, bool fatal) {
|
||||
if (strcmp(info_log, "Success.\n") != 0 &&
|
||||
strcmp(info_log, "No errors.\n") != 0 &&
|
||||
strcmp(info_log, "Validation successful.\n") != 0) {
|
||||
|
||||
#ifdef __APPLE__
|
||||
// Filter out these unhelpful warnings that Apple always generates.
|
||||
while (true) {
|
||||
if (info_log[0] == '\n') {
|
||||
++info_log;
|
||||
continue;
|
||||
}
|
||||
if (info_log[0] == '\0') {
|
||||
// We reached the end without finding anything interesting.
|
||||
return;
|
||||
}
|
||||
int linelen = 0;
|
||||
if ((sscanf(info_log, "WARNING: Could not find vertex shader attribute %*s to match BindAttributeLocation request.%*[\n]%n", &linelen) == 0 && linelen > 0) ||
|
||||
(sscanf(info_log, "WARNING: Could not find fragment shader output %*s to match FragDataBinding request.%*[\n]%n", &linelen) == 0 && linelen > 0)) {
|
||||
info_log += linelen;
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
|
||||
info_log = strchr(info_log, '\n');
|
||||
if (info_log == nullptr) {
|
||||
// We reached the end without finding anything interesting.
|
||||
return;
|
||||
}
|
||||
++info_log;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!fatal) {
|
||||
GLCAT.warning()
|
||||
<< "Shader " << _shader->get_filename() << " produced the "
|
||||
|
@ -258,7 +258,9 @@ call_python_func(PyObject *function, PyObject *args) {
|
||||
|
||||
PyGILState_Release(gstate);
|
||||
|
||||
PyErr_Restore(exc, val, tb);
|
||||
if (PyGILState_Check()) {
|
||||
PyErr_Restore(exc, val, tb);
|
||||
}
|
||||
} else {
|
||||
// No exception. Restore the thread state normally.
|
||||
PyGILState_Release(gstate);
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include "bamReader_ext.cxx"
|
||||
#include "bitArray_ext.cxx"
|
||||
#include "paramPyObject.cxx"
|
||||
#include "pythonCallbackObject.cxx"
|
||||
#include "sparseArray_ext.cxx"
|
||||
#include "typedWritable_ext.cxx"
|
||||
|
31
panda/src/putil/paramPyObject.I
Normal file
31
panda/src/putil/paramPyObject.I
Normal file
@ -0,0 +1,31 @@
|
||||
/**
|
||||
* PANDA 3D SOFTWARE
|
||||
* Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||
*
|
||||
* All use of this software is subject to the terms of the revised BSD
|
||||
* license. You should have received a copy of this license along
|
||||
* with this source code in a file named "LICENSE."
|
||||
*
|
||||
* @file paramPyObject.I
|
||||
* @author rdb
|
||||
* @date 2021-03-01
|
||||
*/
|
||||
|
||||
#include "paramPyObject.h"
|
||||
|
||||
/**
|
||||
* Increments the reference count. Assumes the GIL is held.
|
||||
*/
|
||||
INLINE ParamPyObject::
|
||||
ParamPyObject(PyObject *value) : _value(value) {
|
||||
Py_INCREF(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new reference to the stored value.
|
||||
*/
|
||||
INLINE PyObject *ParamPyObject::
|
||||
get_value() const {
|
||||
Py_INCREF(_value);
|
||||
return _value;
|
||||
}
|
42
panda/src/putil/paramPyObject.cxx
Normal file
42
panda/src/putil/paramPyObject.cxx
Normal file
@ -0,0 +1,42 @@
|
||||
/**
|
||||
* PANDA 3D SOFTWARE
|
||||
* Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||
*
|
||||
* All use of this software is subject to the terms of the revised BSD
|
||||
* license. You should have received a copy of this license along
|
||||
* with this source code in a file named "LICENSE."
|
||||
*
|
||||
* @file paramPyObject.cxx
|
||||
* @author rdb
|
||||
* @date 2021-03-01
|
||||
*/
|
||||
|
||||
#include "paramPyObject.h"
|
||||
|
||||
TypeHandle ParamPyObject::_type_handle;
|
||||
|
||||
/**
|
||||
* Decrements the reference count.
|
||||
*/
|
||||
ParamPyObject::
|
||||
~ParamPyObject() {
|
||||
#if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS)
|
||||
PyGILState_STATE gstate;
|
||||
gstate = PyGILState_Ensure();
|
||||
#endif
|
||||
|
||||
Py_DECREF(_value);
|
||||
|
||||
#if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS)
|
||||
PyGILState_Release(gstate);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
void ParamPyObject::
|
||||
output(std::ostream &out) const {
|
||||
out << "<" << Py_TYPE(_value)->tp_name
|
||||
<< " object at " << (void *)_value << ">";
|
||||
}
|
61
panda/src/putil/paramPyObject.h
Normal file
61
panda/src/putil/paramPyObject.h
Normal file
@ -0,0 +1,61 @@
|
||||
/**
|
||||
* PANDA 3D SOFTWARE
|
||||
* Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||
*
|
||||
* All use of this software is subject to the terms of the revised BSD
|
||||
* license. You should have received a copy of this license along
|
||||
* with this source code in a file named "LICENSE."
|
||||
*
|
||||
* @file paramPyObject.h
|
||||
* @author rdb
|
||||
* @date 2021-03-01
|
||||
*/
|
||||
|
||||
#ifndef PARAMPYOBJECT_H
|
||||
#define PARAMPYOBJECT_H
|
||||
|
||||
#include "pandabase.h"
|
||||
#include "paramValue.h"
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
|
||||
#include "py_panda.h"
|
||||
|
||||
/**
|
||||
* A class object for storing an arbitrary Python object.
|
||||
*/
|
||||
class ParamPyObject final : public ParamValueBase {
|
||||
public:
|
||||
INLINE ParamPyObject(PyObject *value);
|
||||
virtual ~ParamPyObject();
|
||||
|
||||
INLINE PyObject *get_value() const;
|
||||
|
||||
void output(std::ostream &out) const override;
|
||||
|
||||
public:
|
||||
PyObject *_value;
|
||||
|
||||
public:
|
||||
virtual TypeHandle get_type() const override {
|
||||
return get_class_type();
|
||||
}
|
||||
virtual TypeHandle force_init_type() override {init_type(); return get_class_type();}
|
||||
static TypeHandle get_class_type() {
|
||||
return _type_handle;
|
||||
}
|
||||
static void init_type() {
|
||||
ParamValueBase::init_type();
|
||||
register_type(_type_handle, "ParamPyObject",
|
||||
ParamValueBase::get_class_type());
|
||||
}
|
||||
|
||||
private:
|
||||
static TypeHandle _type_handle;
|
||||
};
|
||||
|
||||
#include "paramPyObject.I"
|
||||
|
||||
#endif // HAVE_PYTHON
|
||||
|
||||
#endif
|
@ -163,6 +163,71 @@ def test_coro_exception():
|
||||
task.result()
|
||||
|
||||
|
||||
def test_future_result():
|
||||
# Cancelled
|
||||
fut = core.AsyncFuture()
|
||||
assert not fut.done()
|
||||
fut.cancel()
|
||||
with pytest.raises(CancelledError):
|
||||
fut.result()
|
||||
|
||||
# None
|
||||
fut = core.AsyncFuture()
|
||||
fut.set_result(None)
|
||||
assert fut.done()
|
||||
assert fut.result() is None
|
||||
|
||||
# Store int
|
||||
fut = core.AsyncFuture()
|
||||
fut.set_result(123)
|
||||
assert fut.result() == 123
|
||||
|
||||
# Store string
|
||||
fut = core.AsyncFuture()
|
||||
fut.set_result("test\000\u1234")
|
||||
assert fut.result() == "test\000\u1234"
|
||||
|
||||
# Store TypedWritableReferenceCount
|
||||
tex = core.Texture()
|
||||
rc = tex.get_ref_count()
|
||||
fut = core.AsyncFuture()
|
||||
fut.set_result(tex)
|
||||
assert tex.get_ref_count() == rc + 1
|
||||
assert fut.result() == tex
|
||||
assert tex.get_ref_count() == rc + 1
|
||||
assert fut.result() == tex
|
||||
assert tex.get_ref_count() == rc + 1
|
||||
fut = None
|
||||
assert tex.get_ref_count() == rc
|
||||
|
||||
# Store EventParameter (gets unwrapped)
|
||||
ep = core.EventParameter(0.5)
|
||||
fut = core.AsyncFuture()
|
||||
fut.set_result(ep)
|
||||
assert fut.result() == 0.5
|
||||
assert fut.result() == 0.5
|
||||
|
||||
# Store TypedObject
|
||||
dg = core.Datagram(b"test")
|
||||
fut = core.AsyncFuture()
|
||||
fut.set_result(dg)
|
||||
assert fut.result() == dg
|
||||
assert fut.result() == dg
|
||||
|
||||
# Store arbitrary Python object
|
||||
obj = object()
|
||||
rc = sys.getrefcount(obj)
|
||||
fut = core.AsyncFuture()
|
||||
fut.set_result(obj)
|
||||
assert sys.getrefcount(obj) == rc + 1
|
||||
assert fut.result() is obj
|
||||
assert sys.getrefcount(obj) == rc + 1
|
||||
assert fut.result() is obj
|
||||
assert sys.getrefcount(obj) == rc + 1
|
||||
fut = None
|
||||
assert sys.getrefcount(obj) == rc
|
||||
|
||||
|
||||
def test_future_gather():
|
||||
fut1 = core.AsyncFuture()
|
||||
fut2 = core.AsyncFuture()
|
||||
|
Loading…
x
Reference in New Issue
Block a user