Lenard Lindstrom avatar Lenard Lindstrom committed 8610c95

Add class pygame.BufferProxy to Pygame's public Python API

Add extension type pygame.bufferproxy.BufferProxy to the root Pygame namespace
and the Pygame docs. The pygame._view.View derived BufferProxy is backward
compatible with the original BufferProxy object. Also, since Python's
memoryview object is inadequate for exporting Surface views, BufferProxy
is a permanent Pygame fixture.

Comments (0)

Files changed (5)

docs/reST/index.rst

 :ref:`genindex`
   A list of all functions, classes, and methods in the Pygame package.
 
+:doc:`ref/bufferproxy`
+  An array protocol view of surface pixels
+
 :doc:`ref/cdrom`
   How to access and control the CD audio devices.
 

docs/reST/ref/bufferproxy.rst

+.. include:: common.txt
+
+.. default-domain:: py
+
+:class:`pygame.BufferProxy`
+===========================
+
+.. currentmodule:: pygame
+
+.. class:: BufferProxy
+
+   | :sl:`pygame object to export a surface buffer through an array protocol`
+   | :sg:`BufferProxy(<parent>) -> BufferProxy instance`
+
+   :class:`BufferProxy` is a Pygame support type, designed as the return value
+   of the :meth:`Surface.get_buffer` and :meth:`Surface.get_view` methods.
+   For all Python versions a :class:`BufferProxy` object exports a C struct
+   and Python level array interface on behalf of its parent object's buffer.
+   For CPython 2.6 and later a new buffer interface is also exported.
+   In Pygame, :class:`BufferProxy` is key to implementing the
+   :mod:`pygame.surfarray` module.
+
+   :class:`BufferProxy` instances can be created directly from Python code,
+   either for a parent that exports an interface, or from a Python ``dict``
+   describing an object's buffer layout. The dict entries are based on the
+   Python level array interface mapping. The following keys are recognized:
+
+      ``"shape"`` : tuple
+         The length of each array dimension as a tuple of integers. The
+         length of the tuple is the number of dimensions in the array.
+
+      ``"typestr"`` : string
+         The array element type as a length 3 string. The first character
+         gives byteorder, '<' for little-endian, '>' for big-endian, and
+         '\|' for not applicable. The second character is the element type,
+         'i' for signed integer, 'u' for unsigned integer, 'f' for floating
+         point, and 'V' for an chunk of bytes. The third character gives the
+         bytesize of the element, from '1' to '9' bytes. So, for example,
+         "<u4" is an unsigned 4 byte little-endian integer, such as a
+         32 bit pixel on a PC, while "\|V3" would represent a 24 bit pixel,
+         which has no integer equivalent.
+
+      ``"data"`` : tuple
+         The physical buffer start address and a read-only flag as a length
+         2 tuple. The address is an integer value, while the read-only flag
+         is a bool—``False`` for writable, ``True`` for read-only.
+
+      ``"strides"`` : tuple : (optional)
+         Array stride information as a tuple of integers. It is required
+	 only of non C-contiguous arrays. The tuple length must match
+	 that of ``"shape"``.
+
+      ``"parent"`` : object : (optional)
+         The exporting object. It can be used to keep the parent object
+         alive while its buffer is visible.
+
+      ``"before"`` : callable : (optional)
+         Callback invoked when the :class:`BufferProxy` instance
+         exports the buffer. The callback is given one argument, the
+	 ``"parent"`` object if given, otherwise ``None``.
+         The callback is useful for setting a lock on the parent.
+
+      ``"after"`` : callable : (optional)
+         Callback invoked when an exported buffer is released.
+         The callback is passed on argument, the ``"parent"`` object if given,
+         otherwise None. The callback is useful for releasing a lock on the
+         parent.
+      
+   The BufferProxy class supports subclassing, instance variables, and weak
+   references.
+
+   New in Pygame 1.8.0, extended in Pygame 1.9.2
+
+   .. attribute:: parent
+
+      | :sl:`Return wrapped exporting object.`
+      | :sg:`parent -> Surface`
+      | :sg:`parent -> <parent>`
+
+      The :class:`Surface` which returned the :class:`BufferProxy` object or
+      the object passed to a :class:`BufferProxy` call.
+
+   .. attribute:: length
+
+      | :sl:`The size, in bytes, of the exported buffer.`
+      | :sg:`length -> Int`
+
+      The number of valid bytes of data exported. For discontinuous data,
+      that is data which is not a single block of memory, the bytes within
+      the gaps are excluded from the count. This property is equivalent to
+      the ``Py_buffer`` C struct ``len`` field.
+
+   .. attribute:: raw
+
+      | :sl:`A copy of the exported buffer as a single block of bytes.`
+      | :sg:`raw -> bytes`
+
+      The buffer data as a ``str``/``bytes`` object.
+      Any gaps in the exported data are removed.
+
+   .. method:: write
+
+      | :sl:`Write raw bytes to object buffer.`
+      | :sg:`write(buffer, offset=0) -> None`
+
+      Overwrite bytes in the parent object's data. The data must be C or F
+      contiguous, otherwise a ValueError is raised. Argument `buffer` is a
+      ``str``/``bytes`` object. An optional offset gives a
+      start position, in bytes, within the buffer where overwriting begins.
+      If the offset is negative or greater that or equal to the buffer proxy's
+      :attr:`length` value, an ``IndexException`` is raised.
+      If ``len(buffer) > proxy.length + offset``, a ``ValueError`` is raised.
 import pygame.color
 Color = color.Color
 import pygame.bufferproxy
+BufferProxy = bufferproxy.BufferProxy
 
 __version__ = ver
 

src/bufferproxy.c

 #include "pygame.h"
 #include "pgcompat.h"
 #include "pgbufferproxy.h"
+#include "doc/bufferproxy_doc.h"
 
 
 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
 
 #define PROXY_MODNAME "bufferproxy"
 #define PROXY_TYPE_NAME "BufferProxy"
-#define PROXY_TYPE_FULLNAME (IMPPREFIX PROXY_MODNAME "." PROXY_TYPE_NAME)
+#define PROXY_TYPE_FULLNAME (IMPPREFIX PROXY_TYPE_NAME)
 
 typedef struct PgBufproxyObject_s {
     PyObject_HEAD
 
 static struct PyMethodDef proxy_methods[] = {
     {"write", (PyCFunction)proxy_write, METH_VARARGS | METH_KEYWORDS,
-     "write raw bytes to object buffer"},
+     DOC_BUFFERPROXYWRITE},
     {0, 0, 0, 0}
 };
 
  */
 static PyGetSetDef proxy_getsets[] =
 {
-    {"__array_struct__", (getter)proxy_get_arraystruct, 0, 0, 0},
-    {"__array_interface__", (getter)proxy_get_arrayinterface, 0, 0, 0},
-    {"parent", (getter)proxy_get_parent, 0, 0, 0},
-    {"__dict__", (getter)proxy_get___dict__, 0, 0, 0},
-    {"raw", (getter)proxy_get_raw, 0, 0, 0},
-    {"length", (getter)proxy_get_length, 0, 0, 0},
+    {"__array_struct__", (getter)proxy_get_arraystruct, 0,
+     "Version 3 array interface, C level", 0},
+    {"__array_interface__", (getter)proxy_get_arrayinterface, 0,
+     "Version 3 array interface, Python level", 0},
+    {"parent", (getter)proxy_get_parent, 0,
+     DOC_BUFFERPROXYPARENT, 0},
+    {"__dict__", (getter)proxy_get___dict__, 0,
+     "The object's attribute dictionary, read-only", 0},
+    {"raw", (getter)proxy_get_raw, 0,
+     DOC_BUFFERPROXYRAW, 0},
+    {"length", (getter)proxy_get_length, 0,
+     DOC_BUFFERPROXYLENGTH, 0},
     {0, 0, 0, 0, 0}
 };
 
     0,                          /* tp_setattro */
     PROXY_BUFFERPROCS,          /* tp_as_buffer */
     PROXY_TPFLAGS,              /* tp_flags */
-    "Object bufproxy as an array struct\n",
+    DOC_PYGAMEBUFFERPROXY,
     (traverseproc)proxy_traverse,  /* tp_traverse */
     0,                          /* tp_clear */
     0,                          /* tp_richcompare */
     return _proxy_get_view((PgBufproxyObject *)obj) ? 0 : -1;
 }
 
-/*DOC*/ static char bufferproxy_doc[] =
-/*DOC*/    "exports BufferProxy, a generic wrapper object for an py_buffer";
+/*DOC*/ static char bufferproxy_doc[] = DOC_PYGAMEBUFFERPROXY;
 
 MODINIT_DEFINE(bufferproxy)
 {

src/doc/bufferproxy_doc.h

+/* Auto generated file: with makeref.py .  Docs go in src/ *.doc . */
+#define DOC_PYGAMEBUFFERPROXY "BufferProxy(<parent>) -> BufferProxy instance\npygame object to export a surface buffer through an array protocol"
+
+#define DOC_BUFFERPROXYPARENT "parent -> Surface\nparent -> <parent>\nReturn wrapped exporting object."
+
+#define DOC_BUFFERPROXYLENGTH "length -> Int\nThe size, in bytes, of the exported buffer."
+
+#define DOC_BUFFERPROXYRAW "raw -> bytes\nA copy of the exported buffer as a single block of bytes."
+
+#define DOC_BUFFERPROXYWRITE "write(buffer, offset=0) -> None\nWrite raw bytes to object buffer."
+
+
+
+/* Docs in a comment... slightly easier to read. */
+
+/*
+
+pygame.BufferProxy
+ BufferProxy(<parent>) -> BufferProxy instance
+pygame object to export a surface buffer through an array protocol
+
+pygame.BufferProxy.parent
+ parent -> Surface
+ parent -> <parent>
+Return wrapped exporting object.
+
+pygame.BufferProxy.length
+ length -> Int
+The size, in bytes, of the exported buffer.
+
+pygame.BufferProxy.raw
+ raw -> bytes
+A copy of the exported buffer as a single block of bytes.
+
+pygame.BufferProxy.write
+ write(buffer, offset=0) -> None
+Write raw bytes to object buffer.
+
+*/
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.