class_docstr: Generic GPU buffer.
  
  A generic buffer is an interface used to upload data to a GPU array buffer
  (ARRAY_BUFFER or ELEMENT_ARRAY_BUFFER). It keeps track of
  buffer size but does not have any CPU storage. You can consider it as
  write-only.
  
  The `set_data` is a deferred operation: you can call it even if an OpenGL
  context is not available. The `update` function is responsible to upload
  pending data to GPU memory and requires an active GL context.
  
  The Buffer class only deals with data in terms of bytes; it is not
  aware of data type or element size.
  
  Parameters
  ----------
  data : ndarray | None
      Buffer data.
  nbytes : int | None
      Buffer byte size.
class_docstr_tok: ["Generic","GPU","buffer",".","A","generic","buffer","is","an","interface","used","to","upload","data","to","a","GPU","array","buffer","(","ARRAY_BUFFER","or","ELEMENT_ARRAY_BUFFER",")",".","It","keeps","track","of","buffer","size","but","does","not","have","any","CPU","storage",".","You","can","consider","it","as","write-only",".","The","`","set_data","`","is","a","deferred","operation",":","you","can","call","it","even","if","an","OpenGL","context","is","not","available",".","The","`","update","`","function","is","responsible","to","upload","pending","data","to","GPU","memory","and","requires","an","active","GL","context",".","The","Buffer","class","only","deals","with","data","in","terms","of","bytes",";","it","is","not","aware","of","data","type","or","element","size",".","Parameters","--","--","--","--","--","data",":","ndarray","|","None","Buffer","data",".","nbytes",":","int","|","None","Buffer","byte","size","."]
code: def __init__(self, data=None, nbytes=None):
      GLObject.__init__(self)
      self._views = weakref.WeakSet()  # Views on this buffer
      self._valid = True  # To invalidate buffer views
      self._nbytes = 0  # Bytesize in bytes, set in resize_bytes()
  
      # Set data
      if data is not None:
          if nbytes is not None:
              raise ValueError("Cannot specify both data and nbytes.")
          self.set_data(data, copy=False)
      elif nbytes is not None:
          self.resize_bytes(nbytes)
  
imports: import numpy
  from os import path
  from traceback import extract_stack, format_list
  import weakref
  from .globject import GLObject
  from ..util import logger
label_desc: Use image node_id 1 to create a new Buffer object from inherited base classes: GLObject with example: obj = Buffer(data, nbytes)