# Path: luma/core/render.py
# class canvas(object):
#     """
#     A canvas returns a properly-sized :py:mod:`PIL.ImageDraw` object onto
#     which the caller can draw upon. As soon as the with-block completes, the
#     resultant image is flushed onto the device.
# 
#     By default, any color (other than black) will be `generally` treated as
#     white when displayed on monochrome devices. However, this behaviour can be
#     changed by adding ``dither=True`` and the image will be converted from RGB
#     space into a 1-bit monochrome image where dithering is employed to
#     differentiate colors at the expense of resolution.
#     If a ``background`` parameter is provided, the canvas is based on the given
#     background. This is useful to e.g. write text on a given background image.
#     """
#     def __init__(self, device, background=None, dither=False):
#         self.draw = None
#         if background is None:
#             self.image = Image.new("RGB" if dither else device.mode, device.size)
#         else:
#             assert(background.size == device.size)
#             self.image = background.copy()
#         self.device = device
#         self.dither = dither
# 
#     def __enter__(self):
#         self.draw = ImageDraw.Draw(self.image)
#         return self.draw
# 
#     def __exit__(self, type, value, traceback):
#         if type is None:
# 
#             if self.dither:
#                 self.image = self.image.convert(self.device.mode)
# 
#             # do the drawing onto the device
#             self.device.display(self.image)
# 
#         del self.draw   # Tidy up the resources
#         return False    # Never suppress exceptions
# 
# Path: luma/core/device.py
# class dummy(device):
#     """
#     Pseudo-device that acts like a physical display, except that it does nothing
#     other than retain a copy of the displayed image. It is mostly useful for
#     testing. Supports 24-bit color depth.
#     """
# 
#     def __init__(self, width=128, height=64, rotate=0, mode="RGB", **kwargs):
#         super(dummy, self).__init__(serial_interface=noop())
#         self.capabilities(width, height, rotate, mode)
#         self.image = None
# 
#     def display(self, image):
#         """
#         Takes a :py:mod:`PIL.Image` and makes a copy of it for later
#         use/inspection.
# 
#         :param image: Image to display.
#         :type image: PIL.Image.Image
#         """
#         assert image.size == self.size
# 
#         self.image = self.preprocess(image).copy()
# 
# Path: luma/core/virtual.py
# class history(mixin.capabilities):
#     """
#     Wraps a device (or emulator) to provide a facility to be able to make a
#     savepoint (a point at which the screen display can be "rolled-back" to).
# 
#     This is mostly useful for displaying transient error/dialog messages
#     which could be subsequently dismissed, reverting back to the previous
#     display.
#     """
#     def __init__(self, device):
#         self.capabilities(device.width, device.height, rotate=0,
#             mode=device.mode)
#         if hasattr(device, "segment_mapper"):
#             self.segment_mapper = device.segment_mapper
#         self._savepoints = []
#         self._device = device
#         self._last_image = None
# 
#     def display(self, image):
#         self._last_image = image.copy()
#         self._device.display(image)
# 
#     def savepoint(self):
#         """
#         Copies the last displayed image.
#         """
#         if self._last_image:
#             self._savepoints.append(self._last_image)
#             self._last_image = None
# 
#     def restore(self, drop=0):
#         """
#         Restores the last savepoint. If ``drop`` is supplied and greater than
#         zero, then that many savepoints are dropped, and the next savepoint is
#         restored.
# 
#         :param drop:
#         :type drop: int
#         """
#         assert(drop >= 0)
#         while drop > 0:
#             self._savepoints.pop()
#             drop -= 1
# 
#         img = self._savepoints.pop()
#         self.display(img)
# 
#     def __len__(self):
#         """
#         Indication of the number of savepoints retained.
#         """
#         return len(self._savepoints)


import pytest
import baseline_data
from luma.core.render import canvas
from luma.core.device import dummy
from luma.core.virtual import history
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Copyright (c) 2017-2020 Richard Hull and contributors
# See LICENSE.rst for details.






def test_restore_throws_error_when_empty():
    device = dummy()
    hist = history(device)
    assert len(hist) == 0
    with pytest.raises(IndexError):
        hist.restore()


def test_save_and_restore_reverts_image():
    device = dummy()

# Path: luma/core/render.py
# class canvas(object):
#     """
#     A canvas returns a properly-sized :py:mod:`PIL.ImageDraw` object onto
#     which the caller can draw upon. As soon as the with-block completes, the
#     resultant image is flushed onto the device.
# 
#     By default, any color (other than black) will be `generally` treated as
#     white when displayed on monochrome devices. However, this behaviour can be
#     changed by adding ``dither=True`` and the image will be converted from RGB
#     space into a 1-bit monochrome image where dithering is employed to
#     differentiate colors at the expense of resolution.
#     If a ``background`` parameter is provided, the canvas is based on the given
#     background. This is useful to e.g. write text on a given background image.
#     """
#     def __init__(self, device, background=None, dither=False):
#         self.draw = None
#         if background is None:
#             self.image = Image.new("RGB" if dither else device.mode, device.size)
#         else:
#             assert(background.size == device.size)
#             self.image = background.copy()
#         self.device = device
#         self.dither = dither
# 
#     def __enter__(self):
#         self.draw = ImageDraw.Draw(self.image)
#         return self.draw
# 
#     def __exit__(self, type, value, traceback):
#         if type is None:
# 
#             if self.dither:
#                 self.image = self.image.convert(self.device.mode)
# 
#             # do the drawing onto the device
#             self.device.display(self.image)
# 
#         del self.draw   # Tidy up the resources
#         return False    # Never suppress exceptions
# 
# Path: luma/core/device.py
# class dummy(device):
#     """
#     Pseudo-device that acts like a physical display, except that it does nothing
#     other than retain a copy of the displayed image. It is mostly useful for
#     testing. Supports 24-bit color depth.
#     """
# 
#     def __init__(self, width=128, height=64, rotate=0, mode="RGB", **kwargs):
#         super(dummy, self).__init__(serial_interface=noop())
#         self.capabilities(width, height, rotate, mode)
#         self.image = None
# 
#     def display(self, image):
#         """
#         Takes a :py:mod:`PIL.Image` and makes a copy of it for later
#         use/inspection.
# 
#         :param image: Image to display.
#         :type image: PIL.Image.Image
#         """
#         assert image.size == self.size
# 
#         self.image = self.preprocess(image).copy()
# 
# Path: luma/core/virtual.py
# class history(mixin.capabilities):
#     """
#     Wraps a device (or emulator) to provide a facility to be able to make a
#     savepoint (a point at which the screen display can be "rolled-back" to).
# 
#     This is mostly useful for displaying transient error/dialog messages
#     which could be subsequently dismissed, reverting back to the previous
#     display.
#     """
#     def __init__(self, device):
#         self.capabilities(device.width, device.height, rotate=0,
#             mode=device.mode)
#         if hasattr(device, "segment_mapper"):
#             self.segment_mapper = device.segment_mapper
#         self._savepoints = []
#         self._device = device
#         self._last_image = None
# 
#     def display(self, image):
#         self._last_image = image.copy()
#         self._device.display(image)
# 
#     def savepoint(self):
#         """
#         Copies the last displayed image.
#         """
#         if self._last_image:
#             self._savepoints.append(self._last_image)
#             self._last_image = None
# 
#     def restore(self, drop=0):
#         """
#         Restores the last savepoint. If ``drop`` is supplied and greater than
#         zero, then that many savepoints are dropped, and the next savepoint is
#         restored.
# 
#         :param drop:
#         :type drop: int
#         """
#         assert(drop >= 0)
#         while drop > 0:
#             self._savepoints.pop()
#             drop -= 1
# 
#         img = self._savepoints.pop()
#         self.display(img)
# 
#     def __len__(self):
#         """
#         Indication of the number of savepoints retained.
#         """
#         return len(self._savepoints)


# Path: tests/test_history.py
import pytest
import baseline_data
from luma.core.render import canvas
from luma.core.device import dummy
from luma.core.virtual import history

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Copyright (c) 2017-2020 Richard Hull and contributors
# See LICENSE.rst for details.






def test_restore_throws_error_when_empty():
    device = dummy()
    hist = history(device)
    assert len(hist) == 0
    with pytest.raises(IndexError):
        hist.restore()


def test_save_and_restore_reverts_image():
    device = dummy()

    hist = history(device)