8000 gh-97696 Add documentation for get_coro() behavior with eager tasks by jbower-fb · Pull Request #104189 · python/cpython · GitHub
[go: up one dir, main page]

Skip to content

gh-97696 Add documentation for get_coro() behavior with eager tasks #104189

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 62 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
62 commits
Select commit Hold shift + click to select a range
5c30058
gh-97696 Add documentation for get_coro() behavior with eager tasks
jbower-fb May 5, 2023
248b78b
Update asyncio-task.rst
jbower-fb May 5, 2023
3205457
gh-104190: fix ubsan crash (#104191)
sunmy2019 May 5, 2023
4126669
gh-104051: fix crash in test_xxtestfuzz with -We (#104052)
iritkatriel May 5, 2023
992dead
GH-103092: port `_asyncio` freelist to module state (#104196)
kumaraditya303 May 5, 2023
be60d71
gh-64658: Expand Argument Clinic return converter docs (#104175)
erlend-aasland May 5, 2023
582fe9a
gh-68395: Avoid naming conflicts by mangling variable names in Argume…
erlend-aasland May 5, 2023
78dc058
gh-64631: Test exception messages in cloned Argument Clinic funcs (#1…
erlend-aasland May 5, 2023
d3192a2
gh-64595: Argument Clinic: Touch source file if any output file chang…
erlend-aasland May 5, 2023
5405b60
GH-96803: Add three C-API functions to make _PyInterpreterFrame less …
markshannon May 5, 2023
21fb990
gh-103533: Use PEP 669 APIs for cprofile (GH-103534)
gaogaotiantian May 5, 2023
ef989ab
gh-69152: Add _proxy_response_headers attribute to HTTPConnection (#2…
nametkin May 5, 2023
0b62e96
GH-100479: Add `pathlib.PurePath.with_segments()` (GH-103975)
barneygale May 5, 2023
0826f80
gh-99113: Share the GIL via PyInterpreterState.ceval.gil (gh-104203)
ericsnowcurrently May 5, 8000 2023
efc84cd
gh-104108: Add the Py_mod_multiple_interpreters Module Def Slot (gh-1…
ericsnowcurrently May 5, 2023
7192a46
gh-99113: Add Py_MOD_PER_INTERPRETER_GIL_SUPPORTED (gh-104205)
ericsnowcurrently May 5, 2023
c205faa
gh-104146: Remove unused var 'parser_body_declarations' from clinic.p…
erlend-aasland May 5, 2023
b057233
gh-99113: Add PyInterpreterConfig.own_gil (gh-104204)
ericsnowcurrently May 5, 2023
0b9d0b2
gh-104144: Skip scheduling a done callback if a TaskGroup task comple…
itamaro May 5, 2023
8df75f2
gh-97696: Remove redundant #include (#104216)
jbower-fb May 5, 2023
88482c7
gh-101819: Prepare to modernize the _io extension (#104178)
vstinner May 5, 2023
810e47b
gh-102215: importlib documentation cleanups
yrro May 6, 2023
cf8ee0b
GH-97950: Use new-style index directive ('builtin') (#104164)
AA-Turner May 6, 2023
b2c254d
gh-104233: Fix "unused variable" warning in `ceval_gil.c` (#104234)
sobolevn May 6, 2023
6ab9a42
gh-65772: Clean-up turtle module (#104218)
terryjreedy May 6, 2023
b4f3496
Rewrite the turtledemo makeGraphFrame method (#104224)
terryjreedy May 6, 2023
cb70222
gh-104144: Optimize gather to finish eagerly when all futures complet…
itamaro May 6, 2023
1173ce2
gh-90953: Emit deprecation warnings for `ast` features deprecated in …
AlexWaygood May 6, 2023
a719df1
GH-103548: Improve performance of `pathlib.Path.[is_]absolute()` (GH-…
barneygale May 6, 2023
060a31e
gh-101819: Remove unused 'locale_module' from _io state (#104246)
erlend-aasland May 6, 2023
fc1e63f
gh-99113: Add a check for Py_MOD_PER_INTERPRETER_GIL_SUPPORTED (gh-10…
ericsnowcurrently May 6, 2023
74d38ea
gh-99113: Make Sure the GIL is Acquired at the Right Places (gh-104208)
ericsnowcurrently May 6, 2023
de9f9dd
gh-101640: Make argparse _print_message catch any write error (#101802)
arhadthedev May 6, 2023
fe13226
gh-104254: Document the optional keyword-only "context" argument to T…
itamaro May 7, 2023
33e8bdb
gh-103886: Improve `builtins.__doc__` (#104179)
tomasr8 May 7, 2023
44b081d
gh-97696: Use `PyObject_CallMethodNoArgs` and inline is_loop_running …
itamaro May 7, 2023
06707b9
gh-104018: remove unused format "z" handling in string formatfloat() …
belm0 May 7, 2023
7e11146
Re-enable commented-out test in test_generators.py (#104130)
ymki4360 May 7, 2023
c66f1b6
gh-101819: Port _io.PyIncrementalNewlineDecoder_Type to heap type (#1…
erlend-aasland May 7, 2023
e63898e
gh-101819: Adapt _io.PyWindowsConsoleIO_Type to heap type (#104197)
erlend-aasland May 7, 2023
18babf4
gh-100370: fix OverflowError in sqlite3.Connection.blobopen for 32-bi…
erlend-aasland May 7, 2023
b61f7d2
gh-101819: Port _io.PyBytesIOBuffer_Type to heap type (#104264)
erlend-aasland May 7, 2023
f06a11c
GH-100479: Fix pathlib test failure on WASI (#104215)
barneygale May 7, 2023
86ca8d2
gh-103193: cache calls to `inspect._shadowed_dict` in `inspect.getatt…
AlexWaygood May 7, 2023
c195a2c
gh-104240: make _PyCompile_CodeGen support different compilation mode…
iritkatriel May 7, 2023
3145c0f
GH-89812: Churn `pathlib.Path` methods (GH-104243)
barneygale May 7, 2023
44914e0
gh-103650: Fix perf maps address format (#103651)
art049 May 7, 2023
f6943eb
GH-102613: Improve performance of `pathlib.Path.rglob()` (GH-104244)
barneygale May 7, 2023
8e76e2d
gh-104265 Disallow instantiation of `_csv.Reader` and `_csv.Writer` (…
chgnrdv May 7, 2023
67b4b55
gh-64660: Don't hardcode Argument Clinic return converter result vari…
erlend-aasland May 7, 2023
52539f0
gh-104273: Remove redundant len() calls in argparse function (#104274)
buraksaler May 7, 2023
82a37a4
gh-99108: Replace SHA3 implementation HACL* version (#103597)
msprotz May 8, 2023
2745006
gh-97696: Improve and fix documentation for asyncio eager tasks (#104…
itamaro May 8, 2023
013469f
gh-102500: Remove mention of bytes shorthand (#104281)
hauntsaninja May 8, 2023
ffa4d19
8000 Trim trailing whitespace and test on CI (#104275)
hugovk May 8, 2023
7714382
gh-103193: Improve `getattr_static` test coverage (#104286)
AlexWaygood May 8, 2023
a7e9a63
GH-104145: Use fully-qualified cross reference types for the bisect m…
AA-Turner May 8, 2023
82bc549
gh-99108: fix typo in Modules/Setup (#104293)
msprotz May 8, 2023
b28c5f2
gh-104223: Fix issues with inheriting from buffer classes (#104227)
JelleZijlstra May 8, 2023
a49c8a8
gh-89550: Buffer GzipFile.write to reduce execution time by ~15% (#10…
CCLDArjun May 8, 2023
b8116d8
GH-104284: Fix documentation gettext build (#104296)
AA-Turner May 8, 2023
9a51482
get_coro versionchanged info and cross-reference
jbower-fb May 8, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
gh-104223: Fix issues with inheriting from buffer classes (#104227)
Co-authored-by: Kumar Aditya <59607654+kumaraditya303@users.noreply.github.com>
  • Loading branch information
2 people authored and jbower-fb committed May 8, 2023
commit b28c5f2332183d8d4626b9c98571a44ab96485c5
1 change: 1 addition & 0 deletions Include/cpython/memoryobject.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ typedef struct {
#define _Py_MEMORYVIEW_FORTRAN 0x004 /* Fortran contiguous layout */
#define _Py_MEMORYVIEW_SCALAR 0x008 /* scalar: ndim = 0 */
#define _Py_MEMORYVIEW_PIL 0x010 /* PIL-style layout */
#define _Py_MEMORYVIEW_RESTRICTED 0x020 /* Disallow new references to the memoryview's buffer */

typedef struct {
PyObject_VAR_HEAD
Expand Down
3 changes: 2 additions & 1 deletion Include/internal/pycore_memoryobject.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ extern "C" {
#endif

PyObject *
PyMemoryView_FromObjectAndFlags(PyObject *v, int flags);
_PyMemoryView_FromBufferProc(PyObject *v, int flags,
getbufferproc bufferproc);

#ifdef __cplusplus
}
Expand Down
170 changes: 170 additions & 0 deletions Lib/test/test_buffer.py
8000
Original file line number Diff line number Diff line change
Expand Up @@ -4579,6 +4579,176 @@ def test_c_buffer(self):
buf.__release_buffer__(mv)
self.assertEqual(buf.references, 0)

def test_inheritance(self):
class A(bytearray):
def __buffer__(self, flags):
return super().__buffer__(flags)

a = A(b"hello")
mv = memoryview(a)
self.assertEqual(mv.tobytes(), b"hello")

def test_inheritance_releasebuffer(self):
rb_call_count = 0
class B(bytearray):
def __buffer__(self, flags):
return super().__buffer__(flags)
def __release_buffer__(self, view):
nonlocal rb_call_count
rb_call_count += 1
super().__release_buffer__(view)

b = B(b"hello")
with memoryview(b) as mv:
self.assertEqual(mv.tobytes(), b"hello")
self.assertEqual(rb_call_count, 0)
self.assertEqual(rb_call_count, 1)

def test_inherit_but_return_something_else(self):
class A(bytearray):
def __buffer__(self, flags):
return memoryview(b"hello")

a = A(b"hello")
with memoryview(a) as mv:
self.assertEqual(mv.tobytes(), b"hello")

rb_call_count = 0
rb_raised = False
class B(bytearray):
def __buffer__(self, flags):
return memoryview(b"hello")
def __release_buffer__(self, view):
nonlocal rb_call_count
rb_call_count += 1
try:
super().__release_buffer__(view)
except ValueError:
nonlocal rb_raised
rb_raised = True

b = B(b"hello")
with memoryview(b) as mv:
self.assertEqual(mv.tobytes(), b"hello")
self.assertEqual(rb_call_count, 0)
self.assertEqual(rb_call_count, 1)
self.assertIs(rb_raised, True)

def test_override_only_release(self):
class C(bytearray):
def __release_buffer__(self, buffer):
super().__release_buffer__(buffer)

c = C(b"hello")
with memoryview(c) as mv:
self.assertEqual(mv.tobytes(), b"hello")

def test_release_saves_reference(self):
smuggled_buffer = None

class C(bytearray):
def __release_buffer__(s, buffer: memoryview):
with self.assertRaises(ValueError):
memoryview(buffer)
with self.assertRaises(ValueError):
buffer.cast("b")
with self.assertRaises(ValueError):
buffer.toreadonly()
with self.assertRaises(ValueError):
buffer[:1]
with self.assertRaises(ValueError):
buffer.__buffer__(0)
nonlocal smuggled_buffer
smuggled_buffer = buffer
self.assertEqual(buffer.tobytes(), b"hello")
super().__release_buffer__(buffer)

c = C(b"hello")
with memoryview(c) as mv:
self.assertEqual(mv.tobytes(), b"hello")
c.clear()
with self.assertRaises(ValueError):
smuggled_buffer.tobytes()

def test_release_saves_reference_no_subclassing(self):
ba = bytearray(b"hello")

class C:
def __buffer__(self, flags):
return memoryview(ba)

def __release_buffer__(self, buffer):
self.buffer = buffer

c = C()
with memoryview(c) as mv:
self.assertEqual(mv.tobytes(), b"hello")
self.assertEqual(c.buffer.tobytes(), b"hello")

with self.assertRaises(BufferError):
ba.clear()
c.buffer.release()
ba.clear()

def test_multiple_inheritance_buffer_last(self):
class A:
def __buffer__(self, flags):
return memoryview(b"hello A")

class B(A, bytearray):
def __buffer__(self, flags):
return super().__buffer__(flags)

b = B(b"hello")
with memoryview(b) as mv:
self.assertEqual(mv.tobytes(), b"hello A")

class Releaser:
def __release_buffer__(self, buffer):
self.buffer = buffer

class C(Releaser, bytearray):
def __buffer__(self, flags):
return super().__buffer__(flags)

c = C(b"hello C")
with memoryview(c) as mv:
self.assertEqual(mv.tobytes(), b"hello C")
c.clear()
with self.assertRaises(ValueError):
c.buffer.tobytes()

def test_multiple_inheritance_buffer_last(self):
class A:
def __buffer__(self, flags):
raise RuntimeError("should not be called")

def __release_buffer__(self, buffer):
raise RuntimeError("should not be called")

class B(bytearray, A):
def __buffer__(self, flags):
return super().__buffer__(flags)

b = B(b"hello")
with memoryview(b) as mv:
self.assertEqual(mv.tobytes(), b"hello")

class Releaser:
buffer = None
def __release_buffer__(self, buffer):
self.buffer = buffer

class C(bytearray, Releaser):
def __buffer__(self, flags):
return super().__buffer__(flags)

c = C(b"hello")
with memoryview(c) as mv:
self.assertEqual(mv.tobytes(), b"hello")
c.clear()
self.assertIs(c.buffer, None)


if __name__ == "__main__":
unittest.main()
1 change: 1 addition & 0 deletions Objects/bytearrayobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ static void
bytearray_releasebuffer(PyByteArrayObject *obj, Py_buffer *view)
{
obj->ob_exports--;
assert(obj->ob_exports >= 0);
}

static int
Expand Down
45 changes: 44 additions & 1 deletion Objects/memoryobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,20 @@ PyTypeObject _PyManagedBuffer_Type = {
return -1; \
}

#define CHECK_RESTRICTED(mv) \
if (((PyMemoryViewObject *)(mv))->flags & _Py_MEMORYVIEW_RESTRICTED) { \
PyErr_SetString(PyExc_ValueError, \
"cannot create new view on restricted memoryview"); \
return NULL; \
}

#define CHECK_RESTRICTED_INT(mv) \
if (((PyMemoryViewObject *)(mv))->flags & _Py_MEMORYVIEW_RESTRICTED) { \
PyErr_SetString(PyExc_ValueError, \
"cannot create new view on restricted memoryview"); \
return -1; \
}

/* See gh-92888. These macros signal that we need to check the memoryview
again due to possible read after frees. */
#define CHECK_RELEASED_AGAIN(mv) CHECK_RELEASED(mv)
Expand Down Expand Up @@ -781,14 +795,15 @@ PyMemoryView_FromBuffer(const Py_buffer *info)
using the given flags.
If the object is a memoryview, the new memoryview must be registered
with the same managed buffer. Otherwise, a new managed buffer is created. */
PyObject *
static PyObject *
PyMemoryView_FromObjectAndFlags(PyObject *v, int flags)
{
_PyManagedBufferObject *mbuf;

if (PyMemoryView_Check(v)) {
PyMemoryViewObject *mv = (PyMemoryViewObject *)v;
CHECK_RELEASED(mv);
CHECK_RESTRICTED(mv);
return mbuf_add_view(mv->mbuf, &mv->view);
}
else if (PyObject_CheckBuffer(v)) {
Expand All @@ -806,6 +821,30 @@ PyMemoryView_FromObjectAndFlags(PyObject *v, int flags)
Py_TYPE(v)->tp_name);
return NULL;
}

/* Create a memoryview from an object that implements the buffer protocol,
using the given flags.
If the object is a memoryview, the new memoryview must be registered
with the same managed buffer. Otherwise, a new managed buffer is created. */
PyObject *
_PyMemoryView_FromBufferProc(PyObject *v, int flags, getbufferproc bufferproc)
{
_PyManagedBufferObject *mbuf = mbuf_alloc();
if (mbuf == NULL)
return NULL;

int res = bufferproc(v, &mbuf->master, flags);
if (res < 0) {
mbuf->master.obj = NULL;
Py_DECREF(mbuf);
return NULL;
}

PyObject *ret = mbuf_add_view(mbuf, NULL);
Py_DECREF(mbuf);
return ret;
}

/* Create a memoryview from an object that implements the buffer protocol.
If the object is a memoryview, the new memoryview must be registered
with the same managed buffer. Otherwise, a new managed buffer is created. */
Expand Down Expand Up @@ -1397,6 +1436,7 @@ memoryview_cast_impl(PyMemoryViewObject *self, PyObject *format,
Py_ssize_t ndim = 1;

CHECK_RELEASED(self);
CHECK_RESTRICTED(self);

if (!MV_C_CONTIGUOUS(self->flags)) {
PyErr_SetString(PyExc_TypeError,
Expand Down Expand Up @@ -1452,6 +1492,7 @@ memoryview_toreadonly_impl(PyMemoryViewObject *self)
/*[clinic end generated code: output=2c7e056f04c99e62 input=dc06d20f19ba236f]*/
{
CHECK_RELEASED(self);
CHECK_RESTRICTED(self);
/* Even if self is already readonly, we still need to create a new
* object for .release() to work correctly.
*/
Expand All @@ -1474,6 +1515,7 @@ memory_getbuf(PyMemoryViewObject *self, Py_buffer *view, int flags)
int baseflags = self->flags;

CHECK_RELEASED_INT(self);
CHECK_RESTRICTED_INT(self);

/* start with complete information */
*view = *base;
Expand Down Expand Up @@ -2535,6 +2577,7 @@ memory_subscript(PyMemoryViewObject *self, PyObject *key)
return memory_item(self, index);
}
else if (PySlice_Check(key)) {
CHECK_RESTRICTED(self);
PyMemoryViewObject *sliced;

sliced = (PyMemoryViewObject *)mbuf_add_view(self->mbuf, view);
Expand Down
Loading
0