diff --git a/move-to-python3.patch b/move-to-python3.patch new file mode 100644 index 0000000..f3f899a --- /dev/null +++ b/move-to-python3.patch @@ -0,0 +1,3277 @@ +From 961fdc754e655c68835aee1e7f71af1fdc677668 Mon Sep 17 00:00:00 2001 +From: Steve Kowalik +Date: Mon, 11 Sep 2023 13:18:54 +1000 +Subject: [PATCH] Move to Python 3 only + +With setup.py declaring Python 3.8 and above is supported, use pyupgrade +to reformat the code for that version, along with removing use of mock +and future modules. + +Fixes #347 +--- + asciimatics/constants.py | 5 - + asciimatics/effects.py | 48 ++++---- + asciimatics/event.py | 6 +- + asciimatics/exceptions.py | 13 +- + asciimatics/parsers.py | 15 +-- + asciimatics/particles.py | 46 ++++--- + asciimatics/paths.py | 16 +-- + asciimatics/renderers/base.py | 16 +-- + asciimatics/renderers/box.py | 7 +- + asciimatics/renderers/charts.py | 12 +- + asciimatics/renderers/figlettext.py | 8 +- + asciimatics/renderers/fire.py | 9 +- + asciimatics/renderers/images.py | 14 +-- + asciimatics/renderers/kaleidoscope.py | 9 +- + asciimatics/renderers/plasma.py | 9 +- + asciimatics/renderers/players.py | 12 +- + asciimatics/renderers/rainbow.py | 8 +- + asciimatics/renderers/rotatedduplicate.py | 8 +- + asciimatics/renderers/scales.py | 11 +- + asciimatics/renderers/speechbubble.py | 8 +- + asciimatics/scene.py | 9 +- + asciimatics/screen.py | 54 ++++----- + asciimatics/sprites.py | 10 +- + asciimatics/strings.py | 4 +- + asciimatics/utilities.py | 64 +++++----- + asciimatics/widgets/baselistbox.py | 11 +- + asciimatics/widgets/button.py | 11 +- + asciimatics/widgets/checkbox.py | 9 +- + asciimatics/widgets/datepicker.py | 17 +-- + asciimatics/widgets/divider.py | 11 +- + asciimatics/widgets/dropdownlist.py | 11 +- + asciimatics/widgets/filebrowser.py | 19 ++- + asciimatics/widgets/frame.py | 10 +- + asciimatics/widgets/label.py | 8 +- + asciimatics/widgets/layout.py | 9 +- + asciimatics/widgets/listbox.py | 9 +- + asciimatics/widgets/multicolumnlistbox.py | 11 +- + asciimatics/widgets/popupdialog.py | 7 +- + asciimatics/widgets/popupmenu.py | 9 +- + asciimatics/widgets/radiobuttons.py | 11 +- + asciimatics/widgets/scrollbar.py | 14 +-- + asciimatics/widgets/temppopup.py | 9 +- + asciimatics/widgets/text.py | 10 +- + asciimatics/widgets/textbox.py | 9 +- + asciimatics/widgets/timepicker.py | 16 +-- + asciimatics/widgets/utilities.py | 11 +- + asciimatics/widgets/verticaldivider.py | 10 +- + asciimatics/widgets/widget.py | 12 +- + doc/source/troubleshooting.rst | 7 -- + doc/source/widgets.rst | 2 +- + requirements/base.txt | 3 - + requirements/dev.txt | 1 - + samples/256colour.py | 1 - + samples/basics.py | 2 - + samples/bg_colours.py | 1 - + samples/cogs.py | 1 - + samples/contact_list.py | 2 +- + samples/credits.py | 1 - + samples/images.py | 1 - + samples/maps.py | 2 - + samples/quick_model.py | 2 +- + samples/ray_casting.py | 10 +- + samples/simple.py | 1 - + samples/xmas.py | 1 - + setup.py | 7 -- + tests/mock_objects.py | 2 +- + tests/renderers/test_base.py | 6 - + tests/renderers/test_charts.py | 6 - + tests/renderers/test_images.py | 5 - + tests/renderers/test_other.py | 16 +-- + tests/renderers/test_players.py | 6 - + tests/test_effects.py | 3 +- + tests/test_events.py | 2 +- + tests/test_parsers.py | 5 - + tests/test_particles.py | 2 +- + tests/test_screen.py | 39 +++--- + tests/test_strings.py | 5 - + tests/test_utilities.py | 5 - + tests/test_widgets.py | 139 ++++++++++------------ + 79 files changed, 293 insertions(+), 668 deletions(-) + +Index: asciimatics-1.14.0/asciimatics/constants.py +=================================================================== +--- asciimatics-1.14.0.orig/asciimatics/constants.py ++++ asciimatics-1.14.0/asciimatics/constants.py +@@ -1,11 +1,6 @@ +- + """ + This module is just a collection of simple helper functions. + """ +-from __future__ import division +-from __future__ import absolute_import +-from __future__ import print_function +-from __future__ import unicode_literals + + #: Attribute conversion table for the ${c,a} form of attributes for + #: :py:obj:`~.Screen.paint`. +Index: asciimatics-1.14.0/asciimatics/effects.py +=================================================================== +--- asciimatics-1.14.0.orig/asciimatics/effects.py ++++ asciimatics-1.14.0/asciimatics/effects.py +@@ -1,16 +1,8 @@ +-# -*- coding: utf-8 -*- + """ + This module defines `Effects` which can be used for animations. For more details see + http://asciimatics.readthedocs.io/en/latest/animation.html + """ +-from __future__ import division +-from __future__ import absolute_import +-from __future__ import print_function +-from __future__ import unicode_literals +-from builtins import chr +-from builtins import object +-from builtins import range +-from future.utils import with_metaclass ++ + from abc import ABCMeta, abstractmethod, abstractproperty + from random import randint, random, choice + from math import sin, cos, pi +@@ -19,7 +11,7 @@ from asciimatics.screen import Screen + import datetime + + +-class Effect(with_metaclass(ABCMeta, object)): ++class Effect(metaclass=ABCMeta): + """ + Abstract class to handle a special effect on the screen. An Effect can + cover anything from a static image at the start of the Scene through to +@@ -175,7 +167,7 @@ class Scroll(Effect): + + Also see the common keyword arguments in :py:obj:`.Effect`. + """ +- super(Scroll, self).__init__(screen, **kwargs) ++ super().__init__(screen, **kwargs) + self._rate = rate + self._last_frame = None + +@@ -207,7 +199,7 @@ class Cycle(Effect): + + Also see the common keyword arguments in :py:obj:`.Effect`. + """ +- super(Cycle, self).__init__(screen, **kwargs) ++ super().__init__(screen, **kwargs) + self._renderer = renderer + self._y = y + self._colour = 0 +@@ -249,7 +241,7 @@ class BannerText(Effect): + + Also see the common keyword arguments in :py:obj:`.Effect`. + """ +- super(BannerText, self).__init__(screen, **kwargs) ++ super().__init__(screen, **kwargs) + self._renderer = renderer + self._y = y + self._colour = colour +@@ -314,7 +306,7 @@ class Print(Effect): + + Also see the common keyword arguments in :py:obj:`.Effect`. + """ +- super(Print, self).__init__(screen, **kwargs) ++ super().__init__(screen, **kwargs) + self._renderer = renderer + self._transparent = transparent + self._y = y +@@ -373,7 +365,7 @@ class Mirage(Effect): + + Also see the common keyword arguments in :py:obj:`.Effect`. + """ +- super(Mirage, self).__init__(screen, **kwargs) ++ super().__init__(screen, **kwargs) + self._renderer = renderer + self._y = y + self._colour = colour +@@ -407,7 +399,7 @@ class Mirage(Effect): + return self._stop_frame + + +-class _Star(object): ++class _Star(): + """ + Simple class to represent a single star for the Stars special effect. + """ +@@ -473,7 +465,7 @@ class Stars(Effect): + + Also see the common keyword arguments in :py:obj:`.Effect`. + """ +- super(Stars, self).__init__(screen, **kwargs) ++ super().__init__(screen, **kwargs) + self._pattern = pattern + self._max = count + self._stars = [] +@@ -490,7 +482,7 @@ class Stars(Effect): + return 0 + + +-class _Trail(object): ++class _Trail(): + """ + Track a single trail for a falling character effect (a la Matrix). + """ +@@ -564,7 +556,7 @@ class Matrix(Effect): + + Also see the common keyword arguments in :py:obj:`.Effect`. + """ +- super(Matrix, self).__init__(screen, **kwargs) ++ super().__init__(screen, **kwargs) + self._chars = [] + + def reset(self): +@@ -594,7 +586,7 @@ class Wipe(Effect): + + Also see the common keyword arguments in :py:obj:`.Effect`. + """ +- super(Wipe, self).__init__(screen, **kwargs) ++ super().__init__(screen, **kwargs) + self._bg = bg + self._y = None + +@@ -630,7 +622,7 @@ class Sprite(Effect): + + Also see the common keyword arguments in :py:obj:`.Effect`. + """ +- super(Sprite, self).__init__(screen, **kwargs) ++ super().__init__(screen, **kwargs) + self._renderer_dict = renderer_dict + self._path = path + self._index = None +@@ -754,7 +746,7 @@ class Sprite(Effect): + return event + + +-class _Flake(object): ++class _Flake(): + """ + Track a single snow flake. + """ +@@ -828,7 +820,7 @@ class Snow(Effect): + + Also see the common keyword arguments in :py:obj:`.Effect`. + """ +- super(Snow, self).__init__(screen, **kwargs) ++ super().__init__(screen, **kwargs) + self._chars = [] + + def reset(self): +@@ -864,7 +856,7 @@ class Clock(Effect): + + Also see the common keyword arguments in :py:obj:`.Effect`. + """ +- super(Clock, self).__init__(screen, **kwargs) ++ super().__init__(screen, **kwargs) + self._x = x + self._y = y + self._r = r +@@ -946,7 +938,7 @@ class Cog(Effect): + + Also see the common keyword arguments in :py:obj:`.Effect`. + """ +- super(Cog, self).__init__(screen, **kwargs) ++ super().__init__(screen, **kwargs) + self._x = x + self._y = y + self._radius = radius +@@ -1004,7 +996,7 @@ class RandomNoise(Effect): + + Also see the common keyword arguments in :py:obj:`.Effect`. + """ +- super(RandomNoise, self).__init__(screen, **kwargs) ++ super().__init__(screen, **kwargs) + self._signal = signal + self._strength = 0.0 + self._step = 0.0 +@@ -1076,7 +1068,7 @@ class Julia(Effect): + + Also see the common keyword arguments in :py:obj:`.Effect`. + """ +- super(Julia, self).__init__(screen, **kwargs) ++ super().__init__(screen, **kwargs) + self._width = screen.width + self._height = screen.height + self._centre = [0.0, 0.0] +@@ -1135,7 +1127,7 @@ class Background(Effect): + + Also see the common keyword arguments in :py:obj:`.Effect`. + """ +- super(Background, self).__init__(screen, **kwargs) ++ super().__init__(screen, **kwargs) + self._bg = bg + + def reset(self): +Index: asciimatics-1.14.0/asciimatics/event.py +=================================================================== +--- asciimatics-1.14.0.orig/asciimatics/event.py ++++ asciimatics-1.14.0/asciimatics/event.py +@@ -4,7 +4,7 @@ http://asciimatics.readthedocs.io/en/lat + """ + + +-class Event(object): ++class Event(): + """ + A class to hold information about an input event. + +@@ -31,7 +31,7 @@ class KeyboardEvent(Event): + """ + :returns: a string representation of the keyboard event. + """ +- return "KeyboardEvent: {}".format(self.key_code) ++ return f"KeyboardEvent: {self.key_code}" + + + class MouseEvent(Event): +@@ -61,4 +61,4 @@ class MouseEvent(Event): + """ + :returns: a string representation of the mouse event. + """ +- return "MouseEvent ({}, {}) {}".format(self.x, self.y, self.buttons) ++ return f"MouseEvent ({self.x}, {self.y}) {self.buttons}" +Index: asciimatics-1.14.0/asciimatics/exceptions.py +=================================================================== +--- asciimatics-1.14.0.orig/asciimatics/exceptions.py ++++ asciimatics-1.14.0/asciimatics/exceptions.py +@@ -1,11 +1,6 @@ + """ + This module defines the exceptions used by asciimatics. + """ +-from __future__ import division +-from __future__ import absolute_import +-from __future__ import print_function +-from __future__ import unicode_literals +- + + class ResizeScreenError(Exception): + """ +@@ -18,7 +13,7 @@ class ResizeScreenError(Exception): + :param message: Error message for this exception. + :param scene: Scene that was active at time of resize. + """ +- super(ResizeScreenError, self).__init__() ++ super().__init__() + self._scene = scene + self._message = message + +@@ -48,7 +43,7 @@ class StopApplication(Exception): + """ + :param message: Error message for this exception. + """ +- super(StopApplication, self).__init__() ++ super().__init__() + self._message = message + + def __str__(self): +@@ -68,7 +63,7 @@ class NextScene(Exception): + """ + :param name: Next Scene to invoke. Defaults to next in the list. + """ +- super(NextScene, self).__init__() ++ super().__init__() + self._name = name + + @property +@@ -90,7 +85,7 @@ class InvalidFields(Exception): + """ + :param fields: The list of the fields that are invalid. + """ +- super(InvalidFields, self).__init__() ++ super().__init__() + self._fields = fields + + @property +Index: asciimatics-1.14.0/asciimatics/parsers.py +=================================================================== +--- asciimatics-1.14.0.orig/asciimatics/parsers.py ++++ asciimatics-1.14.0/asciimatics/parsers.py +@@ -1,14 +1,8 @@ +- + """ + This module provides parsers to create ColouredText objects from embedded control strings. + """ +-from __future__ import division +-from __future__ import absolute_import +-from __future__ import print_function +-from __future__ import unicode_literals ++ + import re +-from builtins import str +-from future.utils import with_metaclass + from abc import ABCMeta, abstractmethod + from logging import getLogger + import asciimatics.constants as constants +@@ -19,7 +13,7 @@ from asciimatics.utilities import _DotDi + logger = getLogger(__name__) + + +-class Parser(with_metaclass(ABCMeta, object)): ++class Parser(metaclass=ABCMeta): + """ + Abstract class to represent text parsers that extract colour control codes from raw text and + convert them to displayable text and associated colour maps. +@@ -171,7 +165,7 @@ class AnsiTerminalParser(Parser): + :param text: raw text to process. + :param colours: colour tuple to initialise the colour map. + """ +- super(AnsiTerminalParser, self).reset(text, colours) ++ super().reset(text, colours) + if self._state.attributes is None: + self._state.init_colours = False + self._state.attributes = [None, None, None] +@@ -382,8 +376,7 @@ class AnsiTerminalParser(Parser): + if new_offset == -1: + break + if results is not None: +- for result in results: +- yield result ++ yield from results + else: + logger.debug("Ignoring character: %d", char) + yield (self._state.last_offset, Parser.DISPLAY_TEXT, " ") +Index: asciimatics-1.14.0/asciimatics/particles.py +=================================================================== +--- asciimatics-1.14.0.orig/asciimatics/particles.py ++++ asciimatics-1.14.0/asciimatics/particles.py +@@ -2,22 +2,16 @@ + This module implements a particle system for complex animcation effects. For more details, see + http://asciimatics.readthedocs.io/en/latest/animation.html + """ +-from __future__ import division +-from __future__ import absolute_import +-from __future__ import print_function +-from __future__ import unicode_literals ++ + from abc import ABCMeta, abstractmethod +-from builtins import object +-from builtins import range + from copy import copy + from math import pi, sin, cos, sqrt + from random import uniform, randint +-from future.utils import with_metaclass + from asciimatics.effects import Effect + from asciimatics.screen import Screen + + +-class Particle(object): ++class Particle(): + """ + A single particle in a Particle Effect. + """ +@@ -117,7 +111,7 @@ class Particle(object): + return self._last + + +-class ParticleEmitter(object): ++class ParticleEmitter(): + """ + An emitter for a particle system to create a set of :py:obj:`._Particle` + objects for a :py:obj:`.ParticleEffect`. After initialization, the +@@ -140,7 +134,7 @@ class ParticleEmitter(object): + Each Particle individually as they are drawn. + Defaults to False. + """ +- super(ParticleEmitter, self).__init__() ++ super().__init__() + self._screen = screen + self._x = x + self._y = y +@@ -201,7 +195,7 @@ class ParticleEmitter(object): + self.particles.remove(particle) + + +-class ParticleEffect(with_metaclass(ABCMeta, Effect)): ++class ParticleEffect(Effect, metaclass=ABCMeta): + """ + An Effect that uses a :py:obj:`.ParticleEmitter` to create the animation. + +@@ -219,7 +213,7 @@ class ParticleEffect(with_metaclass(ABCM + + Also see the common keyword arguments in :py:obj:`.Effect`. + """ +- super(ParticleEffect, self).__init__(screen, **kwargs) ++ super().__init__(screen, **kwargs) + self._x = x + self._y = y + self._life_time = life_time +@@ -259,7 +253,7 @@ class Rocket(ParticleEmitter): + :param life_time: The life time of the rocket. + :param on_destroy: The function to call when the rocket explodes. + """ +- super(Rocket, self).__init__( ++ super().__init__( + screen, x, screen.height - 1, 1, self._next_particle, 1, life_time) + self._end_y = y + self._acceleration = (self._end_y - self._y) // life_time +@@ -299,7 +293,7 @@ class RingExplosion(ParticleEmitter): + :param y: The line (y coordinate) for the origin of this explosion. + :param life_time: The life time of this explosion. + """ +- super(RingExplosion, self).__init__( ++ super().__init__( + screen, x, y, 30, self._next_particle, 1, life_time) + self._colour = randint(1, 7) + self._acceleration = 1.0 - (1.0 / life_time) +@@ -339,7 +333,7 @@ class SerpentExplosion(ParticleEmitter): + :param y: The line (y coordinate) for the origin of this explosion. + :param life_time: The life time of this explosion. + """ +- super(SerpentExplosion, self).__init__( ++ super().__init__( + screen, x, y, 8, self._next_particle, 2, life_time) + self._colour = randint(1, 7) + +@@ -383,7 +377,7 @@ class StarExplosion(ParticleEmitter): + :param points: Number of points the explosion should have. + :param on_each: The function to call to spawn a trail. + """ +- super(StarExplosion, self).__init__( ++ super().__init__( + screen, x, y, points, self._next_particle, 1, life_time) + self._colour = randint(1, 7) + self._acceleration = 1.0 - (1.0 / life_time) +@@ -427,7 +421,7 @@ class StarTrail(ParticleEmitter): + :param life_time: The life time of this trail. + :param colour: The colour of this trail. + """ +- super(StarTrail, self).__init__( ++ super().__init__( + screen, x, y, 1, self._next_particle, 1, life_time) + self._colour = colour + +@@ -465,7 +459,7 @@ class PalmExplosion(ParticleEmitter): + :param life_time: The life time of this explosion. + :param on_each: The function to call to spawn a trail. + """ +- super(PalmExplosion, self).__init__( ++ super().__init__( + screen, x, y, 6, self._next_particle, 2, life_time) + self._colour = randint(1, 7) + self._on_each = on_each +@@ -507,7 +501,7 @@ class ExplosionFlames(ParticleEmitter): + :param y: The line (y coordinate) for the origin of this explosion. + :param life_time: The life time of this explosion. + """ +- super(ExplosionFlames, self).__init__( ++ super().__init__( + screen, x, y, 30, self._next_particle, life_time - 10, life_time, + blend=True) + +@@ -553,7 +547,7 @@ class DropEmitter(ParticleEmitter): + :param screen: The Screen being used for this particle system. + :param life_time: The life time of this particle system. + """ +- super(DropEmitter, self).__init__( ++ super().__init__( + screen, 0, 0, 20, self._next_particle, life_time, life_time) + self._particles = None + self._full_count = 0 +@@ -603,7 +597,7 @@ class ShotEmitter(ParticleEmitter): + :param diameter: The diameter of the explosion. + :param life_time: The life time of this particle system. + """ +- super(ShotEmitter, self).__init__( ++ super().__init__( + screen, x, y, 50, self._next_particle, life_time, life_time) + self._particles = None + self._diameter = diameter +@@ -669,7 +663,7 @@ class RainSource(ParticleEmitter): + :param life_time: The life time of this particle system. + :param on_each: Function to call on each iteration of the particle. + """ +- super(RainSource, self).__init__( ++ super().__init__( + screen, 0, 0, 4, self._next_particle, life_time, life_time) + self._particles = None + self._on_each = on_each +@@ -701,7 +695,7 @@ class Splash(ParticleEmitter): + """ + :param screen: The Screen being used for this particle system. + """ +- super(Splash, self).__init__( ++ super().__init__( + screen, x, y, 1, self._next_particle, 1, 3) + + def _next_particle(self): +@@ -819,7 +813,7 @@ class DropScreen(ParticleEffect): + See :py:obj:`.ParticleEffect` for details of the parameters. + """ + # No need for an origin as this uses the whole screen. +- super(DropScreen, self).__init__(screen, 0, 0, life_time, **kwargs) ++ super().__init__(screen, 0, 0, life_time, **kwargs) + + def reset(self): + self._active_systems = [] +@@ -840,7 +834,7 @@ class ShootScreen(ParticleEffect): + """ + # Need to set the field first because the underlying constructor calls reset. + self._diameter = diameter +- super(ShootScreen, self).__init__(screen, x, y, life_time, **kwargs) ++ super().__init__(screen, x, y, life_time, **kwargs) + + def reset(self): + self._active_systems = [] +@@ -858,7 +852,7 @@ class Rain(ParticleEffect): + See :py:obj:`.ParticleEffect` for details of the parameters. + """ + # No need for an origin as this uses the whole screen. +- super(Rain, self).__init__(screen, 0, 0, life_time, **kwargs) ++ super().__init__(screen, 0, 0, life_time, **kwargs) + + def reset(self): + self._active_systems = [] +Index: asciimatics-1.14.0/asciimatics/paths.py +=================================================================== +--- asciimatics-1.14.0.orig/asciimatics/paths.py ++++ asciimatics-1.14.0/asciimatics/paths.py +@@ -2,14 +2,8 @@ + This module provides `Paths` to create animation effects with Sprites. For more details see + http://asciimatics.readthedocs.io/en/latest/animation.html + """ +-from __future__ import division +-from __future__ import absolute_import +-from __future__ import print_function +-from __future__ import unicode_literals +-from future.utils import with_metaclass ++ + from abc import ABCMeta, abstractmethod +-from builtins import object +-from builtins import range + + + def _spline(t, p0, p1, p2, p3): +@@ -29,7 +23,7 @@ def _spline(t, p0, p1, p2, p3): + (t - 1) * t * t * p3) / 2 + + +-class _AbstractPath(with_metaclass(ABCMeta, object)): ++class _AbstractPath(metaclass=ABCMeta): + """ + Class to represent the motion of a Sprite. + +@@ -81,7 +75,7 @@ class Path(_AbstractPath): + To define a Path, use the methods to jump to a location, wait or move + between points. + """ +- super(Path, self).__init__() ++ super().__init__() + self._steps = [] + self._index = 0 + self._rec_x = 0 +@@ -184,7 +178,7 @@ class Path(_AbstractPath): + self._add_step((x, int(y))) + + +-class DynamicPath(with_metaclass(ABCMeta, _AbstractPath)): ++class DynamicPath(_AbstractPath, metaclass=ABCMeta): + """ + Class to create a dynamic path that reacts to events + +@@ -198,7 +192,7 @@ class DynamicPath(with_metaclass(ABCMeta + To implement a DynamicPath, override the :py:meth:`.process_event()` + method to react to any user input. + """ +- super(DynamicPath, self).__init__() ++ super().__init__() + self._screen = screen + self._x = self._start_x = x + self._y = self._start_y = y +Index: asciimatics-1.14.0/asciimatics/renderers/base.py +=================================================================== +--- asciimatics-1.14.0.orig/asciimatics/renderers/base.py ++++ asciimatics-1.14.0/asciimatics/renderers/base.py +@@ -1,14 +1,8 @@ +-# -*- coding: utf-8 -*- + """ + This module provides common code for all Renderers. + """ +-from __future__ import division +-from __future__ import absolute_import +-from __future__ import print_function +-from __future__ import unicode_literals +-from builtins import object ++ + from abc import ABCMeta, abstractproperty, abstractmethod +-from future.utils import with_metaclass + import re + + from wcwidth.wcwidth import wcswidth +@@ -26,7 +20,7 @@ ATTRIBUTES = { + } + + +-class Renderer(with_metaclass(ABCMeta, object)): ++class Renderer(metaclass=ABCMeta): + """ + A Renderer is simply a class that will return one or more text renderings + for display by an Effect. +@@ -90,7 +84,7 @@ class StaticRenderer(Renderer): + :param animation: A function to pick the image (from images) to be + rendered for any given frame. + """ +- super(StaticRenderer, self).__init__() ++ super().__init__() + self._images = images if images is not None else [] + self._index = 0 + self._max_width = 0 +@@ -195,7 +189,7 @@ class StaticRenderer(Renderer): + return self._max_width + + +-class DynamicRenderer(with_metaclass(ABCMeta, Renderer)): ++class DynamicRenderer(Renderer, metaclass=ABCMeta): + """ + A DynamicRenderer is a Renderer that creates each image as requested. It + has a defined maximum size on construction. +@@ -206,7 +200,7 @@ class DynamicRenderer(with_metaclass(ABC + :param height: The max height of the rendered image. + :param width: The max width of the rendered image. + """ +- super(DynamicRenderer, self).__init__() ++ super().__init__() + self._must_clear = clear + self._canvas = TemporaryCanvas(height, width) + +Index: asciimatics-1.14.0/asciimatics/renderers/box.py +=================================================================== +--- asciimatics-1.14.0.orig/asciimatics/renderers/box.py ++++ asciimatics-1.14.0/asciimatics/renderers/box.py +@@ -1,11 +1,6 @@ +-# -*- coding: utf-8 -*- + """ + This module implements an ASCII box renderer. + """ +-from __future__ import division +-from __future__ import absolute_import +-from __future__ import print_function +-from __future__ import unicode_literals + + from asciimatics.constants import SINGLE_LINE + from asciimatics.renderers.base import StaticRenderer +@@ -29,5 +24,5 @@ class Box(StaticRenderer): + `DOUBLE_LINE`. `uni` parameter takes precedence and the style will be + ignored if `uni==False` + """ +- super(Box, self).__init__() ++ super().__init__() + self._images = [BoxTool(uni, style).box(width, height)] +Index: asciimatics-1.14.0/asciimatics/renderers/charts.py +=================================================================== +--- asciimatics-1.14.0.orig/asciimatics/renderers/charts.py ++++ asciimatics-1.14.0/asciimatics/renderers/charts.py +@@ -1,11 +1,7 @@ +-# -*- coding: utf-8 -*- + """ + This module implements bar chart renderers. + """ +-from __future__ import division +-from __future__ import absolute_import +-from __future__ import print_function +-from __future__ import unicode_literals ++ + from abc import abstractmethod + + from asciimatics.constants import DOUBLE_LINE, SINGLE_LINE +@@ -33,7 +29,7 @@ class _BarChartBase(DynamicRenderer): + bg=Screen.COLOUR_BLACK, gradient=None, scale=None, axes=Y_AXIS, intervals=None, + labels=False, border=True, keys=None, gap=None): + ### See children BarChart and VBarChart for argument descriptions and pydocs +- super(_BarChartBase, self).__init__(height, width) ++ super().__init__(height, width) + self._functions = functions + self._char = char + self._colours = [colour] if isinstance(colour, int) else colour +@@ -174,7 +170,7 @@ class BarChart(_BarChartBase): + * A Y_AXIS uses a width of 1 + """ + # Have to have a call to super as the defaults for the class are different than the parent +- super(BarChart, self).__init__( ++ super().__init__( + height, width, functions, char, colour, bg, gradient, scale, axes, intervals, labels, border, + keys, gap) + +@@ -325,7 +321,7 @@ class VBarChart(_BarChartBase): + * An X_AXIS uses a height of 1 + * A Y_AXIS uses a width of 1 + """ +- super(VBarChart, self).__init__( ++ super().__init__( + height, width, functions, char, colour, bg, gradient, scale, axes, intervals, labels, border, + keys, gap) + +Index: asciimatics-1.14.0/asciimatics/renderers/figlettext.py +=================================================================== +--- asciimatics-1.14.0.orig/asciimatics/renderers/figlettext.py ++++ asciimatics-1.14.0/asciimatics/renderers/figlettext.py +@@ -1,11 +1,7 @@ +-# -*- coding: utf-8 -*- + """ + This module implements Figlet text renderer. + """ +-from __future__ import division +-from __future__ import absolute_import +-from __future__ import print_function +-from __future__ import unicode_literals ++ + from pyfiglet import Figlet, DEFAULT_FONT + + from asciimatics.renderers.base import StaticRenderer +@@ -23,5 +19,5 @@ class FigletText(StaticRenderer): + :param font: The Figlet font to use (optional). + :param width: The maximum width for this text in characters. + """ +- super(FigletText, self).__init__() ++ super().__init__() + self._images = [Figlet(font=font, width=width).renderText(text)] +Index: asciimatics-1.14.0/asciimatics/renderers/fire.py +=================================================================== +--- asciimatics-1.14.0.orig/asciimatics/renderers/fire.py ++++ asciimatics-1.14.0/asciimatics/renderers/fire.py +@@ -1,12 +1,7 @@ +-# -*- coding: utf-8 -*- + """ + This module implements a fire effect renderer. + """ +-from __future__ import division +-from __future__ import absolute_import +-from __future__ import print_function +-from __future__ import unicode_literals +-from builtins import range ++ + import copy + from random import randint, random + +@@ -77,7 +72,7 @@ class Fire(DynamicRenderer): + :param colours: Number of colours the screen supports. + :param bg: (Optional) Whether to render background colours only. + """ +- super(Fire, self).__init__(height, width) ++ super().__init__(height, width) + self._emitter = emitter + self._intensity = intensity + self._spot_heat = spot +Index: asciimatics-1.14.0/asciimatics/renderers/images.py +=================================================================== +--- asciimatics-1.14.0.orig/asciimatics/renderers/images.py ++++ asciimatics-1.14.0/asciimatics/renderers/images.py +@@ -1,20 +1,14 @@ +-# -*- coding: utf-8 -*- + """ + This module implements renderers that produce content based on image files. + """ +-from __future__ import division +-from __future__ import absolute_import +-from __future__ import print_function +-from __future__ import unicode_literals +-from builtins import object +-from builtins import range ++ + from PIL import Image + + from asciimatics.renderers.base import StaticRenderer + from asciimatics.screen import Screen + + +-class _ImageSequence(object): ++class _ImageSequence(): + """ + Simple class to make an iterator for a PIL Image object. + """ +@@ -46,7 +40,7 @@ class ImageFile(StaticRenderer): + :param height: The height of the text rendered image. + :param colours: The number of colours the terminal supports. + """ +- super(ImageFile, self).__init__() ++ super().__init__() + with Image.open(filename) as image: + background = image.info['background'] if 'background' in \ + image.info else None +@@ -101,7 +95,7 @@ class ColourImageFile(StaticRenderer): + :param uni: Whether to use unicode box characters or not. + :param dither: Whether to dither the rendered image or not. + """ +- super(ColourImageFile, self).__init__() ++ super().__init__() + with Image.open(filename) as image: + # Find any PNG or GIF background colour. + background = None +Index: asciimatics-1.14.0/asciimatics/renderers/kaleidoscope.py +=================================================================== +--- asciimatics-1.14.0.orig/asciimatics/renderers/kaleidoscope.py ++++ asciimatics-1.14.0/asciimatics/renderers/kaleidoscope.py +@@ -1,12 +1,7 @@ +-# -*- coding: utf-8 -*- + """ + This module implements a kaeldioscope effect renderer. + """ +-from __future__ import division +-from __future__ import absolute_import +-from __future__ import print_function +-from __future__ import unicode_literals +-from builtins import range ++ + from math import sin, cos, pi, atan2 + + from asciimatics.renderers.base import DynamicRenderer +@@ -38,7 +33,7 @@ class Kaleidoscope(DynamicRenderer): + :param cell: A Renderer to use as the backing cell for the kaleidoscope. + :param symmetry: The desired rotational symmetry. Must be a non-negative integer. + """ +- super(Kaleidoscope, self).__init__(height, width) ++ super().__init__(height, width) + self._symmetry = symmetry + self._rotation = 0 + self._cell = cell +Index: asciimatics-1.14.0/asciimatics/renderers/plasma.py +=================================================================== +--- asciimatics-1.14.0.orig/asciimatics/renderers/plasma.py ++++ asciimatics-1.14.0/asciimatics/renderers/plasma.py +@@ -1,12 +1,7 @@ +-# -*- coding: utf-8 -*- + """ + This module implements a plasma effect renderer. + """ +-from __future__ import division +-from __future__ import absolute_import +-from __future__ import print_function +-from __future__ import unicode_literals +-from builtins import range ++ + from math import sin, pi, sqrt + + from asciimatics.renderers.base import DynamicRenderer +@@ -57,7 +52,7 @@ class Plasma(DynamicRenderer): + :param width: Width of the box to contain the plasma. + :param colours: Number of colours the screen supports. + """ +- super(Plasma, self).__init__(height, width) ++ super().__init__(height, width) + self._palette = self._palette_256 if colours >= 256 else self._palette_8 + self._t = 0 + +Index: asciimatics-1.14.0/asciimatics/renderers/players.py +=================================================================== +--- asciimatics-1.14.0.orig/asciimatics/renderers/players.py ++++ asciimatics-1.14.0/asciimatics/renderers/players.py +@@ -1,13 +1,7 @@ +-# -*- coding: utf-8 -*- + """ + This module implements renderers that play content to the screen. + """ +-from __future__ import division +-from __future__ import absolute_import +-from __future__ import print_function +-from __future__ import unicode_literals + from abc import abstractmethod +-from builtins import range + import json + + from asciimatics.renderers.base import DynamicRenderer +@@ -25,7 +19,7 @@ class AbstractScreenPlayer(DynamicRender + :param height: required height of the renderer. + :param width: required width of the renderer. + """ +- super(AbstractScreenPlayer, self).__init__(height, width, clear=False) ++ super().__init__(height, width, clear=False) + self._parser = AnsiTerminalParser() + self._current_colours = [Screen.COLOUR_WHITE, Screen.A_NORMAL, Screen.COLOUR_BLACK] + self._show_cursor = False +@@ -157,7 +151,7 @@ class AnsiArtPlayer(AbstractScreenPlayer + :param strip: whether to strip CRLF from the file content. + :param rate: number of lines to render on each update. + """ +- super(AnsiArtPlayer, self).__init__(height, width) ++ super().__init__(height, width) + self._file = open(filename, "rb") + self._strip = strip + self._rate = rate +@@ -216,7 +210,7 @@ class AsciinemaPlayer(AbstractScreenPlay + width = width if width else header["width"] + + # Construct the full player now we have all the details. +- super(AsciinemaPlayer, self).__init__(height, width) ++ super().__init__(height, width) + self._max_delay = max_delay + + def __enter__(self): +Index: asciimatics-1.14.0/asciimatics/renderers/rainbow.py +=================================================================== +--- asciimatics-1.14.0.orig/asciimatics/renderers/rainbow.py ++++ asciimatics-1.14.0/asciimatics/renderers/rainbow.py +@@ -1,12 +1,6 @@ +-# -*- coding: utf-8 -*- + """ + This module implements a rainbow effect renderer. + """ +-from __future__ import division +-from __future__ import absolute_import +-from __future__ import print_function +-from __future__ import unicode_literals +- + from asciimatics.renderers.base import StaticRenderer + + +@@ -33,7 +27,7 @@ class Rainbow(StaticRenderer): + :param screen: The screen object for this renderer. + :param renderer: The renderer to wrap. + """ +- super(Rainbow, self).__init__() ++ super().__init__() + palette = self._256_palette if screen.colours > 16 else self._16_palette + for image in renderer.images: + new_image = "" +Index: asciimatics-1.14.0/asciimatics/renderers/rotatedduplicate.py +=================================================================== +--- asciimatics-1.14.0.orig/asciimatics/renderers/rotatedduplicate.py ++++ asciimatics-1.14.0/asciimatics/renderers/rotatedduplicate.py +@@ -1,12 +1,6 @@ +-# -*- coding: utf-8 -*- + """ + This module implements a renderer that renders another renderer but rotated. + """ +-from __future__ import division +-from __future__ import absolute_import +-from __future__ import print_function +-from __future__ import unicode_literals +-from builtins import range + + from asciimatics.renderers.base import StaticRenderer + +@@ -23,7 +17,7 @@ class RotatedDuplicate(StaticRenderer): + :param height: The maximum height of the rendered text. + :param renderer: The renderer to wrap. + """ +- super(RotatedDuplicate, self).__init__() ++ super().__init__() + for image in renderer.images: + mx = (width - max([len(x) for x in image])) // 2 + my = height // 2 - len(image) +Index: asciimatics-1.14.0/asciimatics/renderers/scales.py +=================================================================== +--- asciimatics-1.14.0.orig/asciimatics/renderers/scales.py ++++ asciimatics-1.14.0/asciimatics/renderers/scales.py +@@ -1,13 +1,6 @@ +-# -*- coding: utf-8 -*- + """ + This module implements renderers that show measuring scales to the screen. + """ +-from __future__ import division +-from __future__ import absolute_import +-from __future__ import print_function +-from __future__ import unicode_literals +-from builtins import range +- + from asciimatics.renderers.base import StaticRenderer + + +@@ -21,7 +14,7 @@ class Scale(StaticRenderer): + """ + :param width: The width of the scale + """ +- super(Scale, self).__init__() ++ super().__init__() + + contents = [] + for x in range(1, width + 1): +@@ -47,7 +40,7 @@ class VScale(StaticRenderer): + """ + :param width: The width of the scale + """ +- super(VScale, self).__init__() ++ super().__init__() + + contents = [str(i)[-1] for i in range(1, height + 1)] + text = '\n'.join(contents) +Index: asciimatics-1.14.0/asciimatics/renderers/speechbubble.py +=================================================================== +--- asciimatics-1.14.0.orig/asciimatics/renderers/speechbubble.py ++++ asciimatics-1.14.0/asciimatics/renderers/speechbubble.py +@@ -1,12 +1,6 @@ +-# -*- coding: utf-8 -*- + """ + This module implements a speech-bubble effect renderer. + """ +-from __future__ import division +-from __future__ import absolute_import +-from __future__ import print_function +-from __future__ import unicode_literals +- + from wcwidth.wcwidth import wcswidth + + from asciimatics.renderers.base import StaticRenderer +@@ -23,7 +17,7 @@ class SpeechBubble(StaticRenderer): + :param tail: Where to put the bubble callout tail, specifying "L" or + "R" for left or right tails. Can be None for no tail. + """ +- super(SpeechBubble, self).__init__() ++ super().__init__() + max_len = max([wcswidth(x) for x in text.split("\n")]) + if uni: + bubble = "╭─" + "─" * max_len + "─╮\n" +Index: asciimatics-1.14.0/asciimatics/scene.py +=================================================================== +--- asciimatics-1.14.0.orig/asciimatics/scene.py ++++ asciimatics-1.14.0/asciimatics/scene.py +@@ -4,14 +4,7 @@ http://asciimatics.readthedocs.io/en/lat + """ + + +-from __future__ import division +-from __future__ import absolute_import +-from __future__ import print_function +-from __future__ import unicode_literals +-from builtins import object +- +- +-class Scene(object): ++class Scene(): + """ + Class to store the details of a single scene to be displayed. This is + made up of a set of :py:obj:`.Effect` objects. See the documentation for +Index: asciimatics-1.14.0/asciimatics/screen.py +=================================================================== +--- asciimatics-1.14.0.orig/asciimatics/screen.py ++++ asciimatics-1.14.0/asciimatics/screen.py +@@ -1,13 +1,7 @@ +-# -*- coding: utf-8 -*- + """ + This module defines common screen output function. For more details, see + http://asciimatics.readthedocs.io/en/latest/io.html + """ +-from __future__ import division +-from __future__ import absolute_import +-from __future__ import print_function +-from __future__ import unicode_literals +- + import os + import signal + import struct +@@ -15,17 +9,11 @@ import sys + import time + from abc import ABCMeta, abstractmethod + from functools import update_wrapper, partial ++from itertools import zip_longest + from locale import getlocale, getdefaultlocale + from logging import getLogger + from math import sqrt + +-from builtins import object +-from builtins import range +-from builtins import ord +-from builtins import chr +-from builtins import str +-from future.utils import with_metaclass +-from future.moves.itertools import zip_longest + from wcwidth import wcwidth, wcswidth + + from asciimatics.event import KeyboardEvent, MouseEvent +@@ -40,7 +28,7 @@ ENABLE_EXTENDED_FLAGS = 0x0080 + ENABLE_QUICK_EDIT_MODE = 0x0040 + + +-class _DoubleBuffer(object): ++class _DoubleBuffer(): + """ + Pure python Screen buffering. + """ +@@ -50,11 +38,11 @@ class _DoubleBuffer(object): + :param height: Height of the buffer to create. + :param width: Width of the buffer to create. + """ +- super(_DoubleBuffer, self).__init__() ++ super().__init__() + self._height = height + self._width = width + self._double_buffer = None +- line = [(u" ", Screen.COLOUR_WHITE, 0, 0, 1) for _ in range(self._width)] ++ line = [(" ", Screen.COLOUR_WHITE, 0, 0, 1) for _ in range(self._width)] + self._screen_buffer = [line[:] for _ in range(self._height)] + self.clear(Screen.COLOUR_WHITE, 0, 0) + +@@ -77,7 +65,7 @@ class _DoubleBuffer(object): + height = self._height if h is None else h + width = max(0, min(self._width - x, width)) + height = max(0, min(self._height - y, height)) +- line = [(u" ", fg, attr, bg, 1) for _ in range(width)] ++ line = [(" ", fg, attr, bg, 1) for _ in range(width)] + if x == 0 and y == 0 and w is None and h is None: + self._double_buffer = [line[:] for _ in range(height)] + else: +@@ -129,7 +117,7 @@ class _DoubleBuffer(object): + + :param lines: Number of lines to scroll. Negative numbers move the buffer up. + """ +- line = [(u" ", Screen.COLOUR_WHITE, 0, 0, 1) for _ in range(self._width)] ++ line = [(" ", Screen.COLOUR_WHITE, 0, 0, 1) for _ in range(self._width)] + if lines > 0: + # Limit to buffer size - this will just invalidate all the data + lines = min(lines, self._height) +@@ -213,7 +201,7 @@ class _DoubleBuffer(object): + return [[x[1:4] for x in self.slice(0, y, self.width)] for y in range(self.height)] + + +-class _AbstractCanvas(with_metaclass(ABCMeta, object)): ++class _AbstractCanvas(metaclass=ABCMeta): + """ + Abstract class to handle screen buffering. + """ +@@ -502,7 +490,7 @@ class _AbstractCanvas(with_metaclass(ABC + :param colours: Number of colours for this object. + :param unicode_aware: Force use of unicode options for this object. + """ +- super(_AbstractCanvas, self).__init__() ++ super().__init__() + + # Can we handle unicode environments? + self._unicode_aware = unicode_aware +@@ -1122,7 +1110,7 @@ class TemporaryCanvas(_AbstractCanvas): + :param width: The width of the screen buffer to be used. + """ + # Colours and unicode rendering are up to the user. Pick defaults that won't limit them. +- super(TemporaryCanvas, self).__init__(height, width, None, 256, True) ++ super().__init__(height, width, None, 256, True) + + @property + def plain_image(self): +@@ -1158,7 +1146,7 @@ class Canvas(_AbstractCanvas): + to centring within the current Screen for that location. + """ + # Save off the screen details. +- super(Canvas, self).__init__( ++ super().__init__( + height, width, None, screen.colours, screen.unicode_aware) + self._screen = screen + self._dx = (screen.width - width) // 2 if x is None else x +@@ -1184,7 +1172,7 @@ class Canvas(_AbstractCanvas): + return self._dx, self._dy + + +-class Screen(with_metaclass(ABCMeta, _AbstractCanvas)): ++class Screen(_AbstractCanvas, metaclass=ABCMeta): + """ + Class to track basic state of the screen. This constructs the necessary + resources to allow us to do the ASCII animations. +@@ -1283,7 +1271,7 @@ class Screen(with_metaclass(ABCMeta, _Ab + """ + Don't call this constructor directly. + """ +- super(Screen, self).__init__( ++ super().__init__( + height, width, buffer_height, 0, unicode_aware) + + # Initialize base class variables - e.g. those used for drawing. +@@ -1741,7 +1729,7 @@ class Screen(with_metaclass(ABCMeta, _Ab + break + else: + raise RuntimeError( +- "Could not find Scene: '{}'".format(e.name)) ++ f"Could not find Scene: '{e.name}'") + + # Reset the screen if needed. + scene = self._scenes[self._scene_index] +@@ -2021,7 +2009,7 @@ if sys.platform == "win32": + if unicode_aware is None: + # According to MSDN, 65001 is the Windows UTF-8 code page. + unicode_aware = win32console.GetConsoleCP() == 65001 +- super(_WindowsScreen, self).__init__( ++ super().__init__( + height, width, buffer_height, unicode_aware) + + # Save off the console details. +@@ -2333,7 +2321,7 @@ else: + encoding.lower() == "utf-8") + + # Save off the screen details. +- super(_CursesScreen, self).__init__( ++ super().__init__( + win.getmaxyx()[0], win.getmaxyx()[1], height, unicode_aware) + self._screen = win + self._screen.keypad(1) +@@ -2433,7 +2421,7 @@ else: + """ + try: + sys.stdout.write(msg) +- except IOError: ++ except OSError: + # Screen resize can throw IOErrors. These can be safely + # ignored as the screen will be shortly reset anyway. + pass +@@ -2481,10 +2469,10 @@ else: + """ + Refresh the screen. + """ +- super(_CursesScreen, self).refresh() ++ super().refresh() + try: + sys.stdout.flush() +- except IOError: ++ except OSError: + pass + + @staticmethod +@@ -2618,7 +2606,7 @@ else: + :param width: The width of the character (for dual-width glyphs in CJK languages). + """ + # Move the cursor if necessary +- cursor = u"" ++ cursor = "" + if x != self._cur_x or y != self._cur_y: + cursor = curses.tparm(self._move_y_x, y, x).decode("utf-8") + +@@ -2643,7 +2631,7 @@ else: + """ + try: + select.select([sys.stdin], [], [], timeout) +- except select.error: ++ except OSError: + # Any error will almost certainly result in a a Screen. Ignore. + pass + +@@ -2658,7 +2646,7 @@ else: + self._safe_write("{}{}{}".format(self._start_title, title, + self._end_title)) + +- class _SignalState(object): ++ class _SignalState(): + """ + Save previous user signal state while setting signals. + +Index: asciimatics-1.14.0/asciimatics/sprites.py +=================================================================== +--- asciimatics-1.14.0.orig/asciimatics/sprites.py ++++ asciimatics-1.14.0/asciimatics/sprites.py +@@ -2,10 +2,6 @@ + This module provides `Sprites` to create animation effects with Paths. For more details see + http://asciimatics.readthedocs.io/en/latest/animation.html + """ +-from __future__ import division +-from __future__ import absolute_import +-from __future__ import print_function +-from __future__ import unicode_literals + from asciimatics.effects import Sprite + from asciimatics.renderers import StaticRenderer + import random +@@ -128,7 +124,7 @@ class Sam(Sprite): + """ + See :py:obj:`.Sprite` for details. + """ +- super(Sam, self).__init__( ++ super().__init__( + screen, + renderer_dict={ + "default": StaticRenderer(images=sam_default, animation=_blink), +@@ -152,7 +148,7 @@ class Arrow(Sprite): + """ + See :py:obj:`.Sprite` for details. + """ +- super(Arrow, self).__init__( ++ super().__init__( + screen, + renderer_dict={ + "default": StaticRenderer(images=default_arrow, +@@ -179,7 +175,7 @@ class Plot(Sprite): + """ + See :py:obj:`.Sprite` for details. + """ +- super(Plot, self).__init__( ++ super().__init__( + screen, + renderer_dict={ + "default": StaticRenderer(images=["X"]) +Index: asciimatics-1.14.0/asciimatics/strings.py +=================================================================== +--- asciimatics-1.14.0.orig/asciimatics/strings.py ++++ asciimatics-1.14.0/asciimatics/strings.py +@@ -4,7 +4,7 @@ This module provides classes to handle e + from asciimatics.parsers import Parser + + +-class ColouredText(object): ++class ColouredText(): + """ + Unicode string-like object to store text and colour maps, using a parser to convert the raw text + passed in into visible text and an associated colour map. This only handles simple colour +@@ -23,7 +23,7 @@ class ColouredText(object): + The colour_map, offsets and text options are to optimize creation of substrings from an + existing ColouredText object and should not be used in general. + """ +- super(ColouredText, self).__init__() ++ super().__init__() + self._raw_text = raw_text + self._raw_offsets = [] + self._parser = parser +Index: asciimatics-1.14.0/asciimatics/utilities.py +=================================================================== +--- asciimatics-1.14.0.orig/asciimatics/utilities.py ++++ asciimatics-1.14.0/asciimatics/utilities.py +@@ -1,12 +1,6 @@ +-# -*- coding: utf-8 -*- + """ + This module is just a collection of simple helper functions. + """ +-from __future__ import division +-from __future__ import absolute_import +-from __future__ import print_function +-from __future__ import unicode_literals +-from builtins import str + from datetime import date, datetime + from logging import getLogger + +@@ -24,9 +18,9 @@ def readable_mem(mem): + """ + for suffix in ["", "K", "M", "G", "T"]: + if mem < 10000: +- return "{}{}".format(int(mem), suffix) ++ return f"{int(mem)}{suffix}" + mem /= 1024 +- return "{}P".format(int(mem)) ++ return f"{int(mem)}P" + + + def readable_timestamp(stamp): +@@ -52,7 +46,7 @@ class _DotDict(dict): + __delattr__ = dict.__delitem__ + + +-class BoxTool(object): ++class BoxTool(): + """ + Tool for building boxes out of characters. + +@@ -111,33 +105,33 @@ class BoxTool(object): + self._style = style + + if style == SINGLE_LINE and self.unicode_aware: +- self.down_right = u"┌" +- self.down_left = u"┐" +- self.up_right = u"└" +- self.up_left = u"┘" +- self.h = u"─" +- self.h_inside = u"─" +- self.v = u"│" +- self.v_inside = u"│" +- self.v_left = u"┤" +- self.v_right = u"├" +- self.h_up = u"┴" +- self.h_down = u"┬" +- self.cross = u"┼" ++ self.down_right = "┌" ++ self.down_left = "┐" ++ self.up_right = "└" ++ self.up_left = "┘" ++ self.h = "─" ++ self.h_inside = "─" ++ self.v = "│" ++ self.v_inside = "│" ++ self.v_left = "┤" ++ self.v_right = "├" ++ self.h_up = "┴" ++ self.h_down = "┬" ++ self.cross = "┼" + elif style == DOUBLE_LINE and self.unicode_aware: +- self.down_right = u"╔" +- self.down_left = u"╗" +- self.up_right = u"╚" +- self.up_left = u"╝" +- self.h = u"═" +- self.h_inside = u"═" +- self.v = u"║" +- self.v_inside = u"║" +- self.v_left = u"╣" +- self.v_right = u"╠" +- self.h_up = u"╩" +- self.h_down = u"╦" +- self.cross = u"╬" ++ self.down_right = "╔" ++ self.down_left = "╗" ++ self.up_right = "╚" ++ self.up_left = "╝" ++ self.h = "═" ++ self.h_inside = "═" ++ self.v = "║" ++ self.v_inside = "║" ++ self.v_left = "╣" ++ self.v_right = "╠" ++ self.h_up = "╩" ++ self.h_down = "╦" ++ self.cross = "╬" + else: + self.down_left = "+" + self.down_right = "+" +Index: asciimatics-1.14.0/asciimatics/widgets/baselistbox.py +=================================================================== +--- asciimatics-1.14.0.orig/asciimatics/widgets/baselistbox.py ++++ asciimatics-1.14.0/asciimatics/widgets/baselistbox.py +@@ -1,20 +1,13 @@ +-# -*- coding: utf-8 -*- + """This is the baseclass for list box types""" +-from __future__ import division +-from __future__ import absolute_import +-from __future__ import print_function +-from __future__ import unicode_literals +-from builtins import chr + from datetime import datetime, timedelta + from abc import ABCMeta, abstractmethod, abstractproperty +-from future.utils import with_metaclass + from asciimatics.event import KeyboardEvent, MouseEvent + from asciimatics.screen import Screen + from asciimatics.widgets.widget import Widget + from asciimatics.widgets.scrollbar import _ScrollBar + + +-class _BaseListBox(with_metaclass(ABCMeta, Widget)): ++class _BaseListBox(Widget, metaclass=ABCMeta): + """ + An Internal class to contain common function between list box types. + """ +@@ -35,7 +28,7 @@ class _BaseListBox(with_metaclass(ABCMet + this list - e.g. by double-clicking or pressing Enter. + :param validator: Optional function to validate selection for this widget. + """ +- super(_BaseListBox, self).__init__(name) ++ super().__init__(name) + self._titles = titles + self._label = label + self._parser = parser +Index: asciimatics-1.14.0/asciimatics/widgets/button.py +=================================================================== +--- asciimatics-1.14.0.orig/asciimatics/widgets/button.py ++++ asciimatics-1.14.0/asciimatics/widgets/button.py +@@ -1,9 +1,4 @@ +-# -*- coding: utf-8 -*- + """This module defines a button widget""" +-from __future__ import division +-from __future__ import absolute_import +-from __future__ import print_function +-from __future__ import unicode_literals + from asciimatics.event import KeyboardEvent, MouseEvent + from asciimatics.widgets.widget import Widget + +@@ -28,7 +23,7 @@ class Button(Widget): + + Also see the common keyword arguments in :py:obj:`.Widget`. + """ +- super(Button, self).__init__(name, **kwargs) ++ super().__init__(name, **kwargs) + self._add_box = add_box + self.text = text + self._on_click = on_click +@@ -37,7 +32,7 @@ class Button(Widget): + def set_layout(self, x, y, offset, w, h): + # Do the usual layout work. then recalculate exact x/w values for the + # rendered button. +- super(Button, self).set_layout(x, y, offset, w, h) ++ super().set_layout(x, y, offset, w, h) + text_width = self.string_len(self._text) + if self._add_box: + # Minimize widget to make a nice little button. Only centre it if there are no label offsets. +@@ -88,7 +83,7 @@ class Button(Widget): + @text.setter + def text(self, new_text): + self._text_raw = new_text +- self._text = "< {} >".format(new_text) if self._add_box else new_text ++ self._text = f"< {new_text} >" if self._add_box else new_text + + @property + def value(self): +Index: asciimatics-1.14.0/asciimatics/widgets/checkbox.py +=================================================================== +--- asciimatics-1.14.0.orig/asciimatics/widgets/checkbox.py ++++ asciimatics-1.14.0/asciimatics/widgets/checkbox.py +@@ -1,9 +1,4 @@ +-# -*- coding: utf-8 -*- + """This module defines a checkbox widget""" +-from __future__ import division +-from __future__ import absolute_import +-from __future__ import print_function +-from __future__ import unicode_literals + from asciimatics.event import KeyboardEvent, MouseEvent + from asciimatics.widgets.widget import Widget + +@@ -27,7 +22,7 @@ class CheckBox(Widget): + + Also see the common keyword arguments in :py:obj:`.Widget`. + """ +- super(CheckBox, self).__init__(name, **kwargs) ++ super().__init__(name, **kwargs) + self._text = text + self._label = label + self._on_change = on_change +@@ -36,7 +31,7 @@ class CheckBox(Widget): + self._draw_label() + + # Render this checkbox. +- check_char = u"✓" if self._frame.canvas.unicode_aware else "X" ++ check_char = "✓" if self._frame.canvas.unicode_aware else "X" + (colour, attr, bg) = self._pick_colours("control", self._has_focus) + self._frame.canvas.print_at( + "[{}] ".format(check_char if self._value else " "), +Index: asciimatics-1.14.0/asciimatics/widgets/datepicker.py +=================================================================== +--- asciimatics-1.14.0.orig/asciimatics/widgets/datepicker.py ++++ asciimatics-1.14.0/asciimatics/widgets/datepicker.py +@@ -1,12 +1,5 @@ +-# -*- coding: utf-8 -*- + """This module defines a datepicker widget""" +-from __future__ import division +-from __future__ import absolute_import +-from __future__ import print_function +-from __future__ import unicode_literals +-from builtins import range +-from datetime import date +-from datetime import datetime ++from datetime import date, datetime + from asciimatics.event import KeyboardEvent, MouseEvent + from asciimatics.exceptions import InvalidFields + from asciimatics.screen import Screen +@@ -32,7 +25,7 @@ class _DatePickerPopup(_TempPopup): + if year_range is None: + year_range = range(now.year - 50, now.year + 50) + self._days = ListBox(3, +- [("{:02}".format(x), x) for x in range(1, 32)], ++ [(f"{x:02}", x) for x in range(1, 32)], + centre=True, + validator=self._check_date) + self._months = ListBox(3, +@@ -41,13 +34,13 @@ class _DatePickerPopup(_TempPopup): + centre=True, + on_change=self._refresh_day) + self._years = ListBox(3, +- [("{:04}".format(x), x) for x in year_range], ++ [(f"{x:04}", x) for x in year_range], + centre=True, + on_change=self._refresh_day) + + # Construct the Frame + location = parent.get_location() +- super(_DatePickerPopup, self).__init__(parent.frame.screen, ++ super().__init__(parent.frame.screen, + parent, + location[0] - 1, location[1] - 2, + 13, 5) +@@ -102,7 +95,7 @@ class DatePicker(Widget): + + Also see the common keyword arguments in :py:obj:`.Widget`. + """ +- super(DatePicker, self).__init__(name, **kwargs) ++ super().__init__(name, **kwargs) + self._label = label + self._on_change = on_change + self._value = datetime.now().date() +Index: asciimatics-1.14.0/asciimatics/widgets/divider.py +=================================================================== +--- asciimatics-1.14.0.orig/asciimatics/widgets/divider.py ++++ asciimatics-1.14.0/asciimatics/widgets/divider.py +@@ -1,9 +1,4 @@ +-# -*- coding: utf-8 -*- + """This module defines a divider between widgets""" +-from __future__ import division +-from __future__ import absolute_import +-from __future__ import print_function +-from __future__ import unicode_literals + from asciimatics.widgets.widget import Widget + + +@@ -21,16 +16,16 @@ class Divider(Widget): + :param line_char: Optional character to use for drawing the line. + """ + # Dividers have no value and so should have no name for look-ups either. +- super(Divider, self).__init__(None, tab_stop=False) ++ super().__init__(None, tab_stop=False) + self._draw_line = draw_line + self._required_height = height + self._line_char = line_char + + def register_frame(self, frame): + # Update line drawing character if needed once we have a canvas to query. +- super(Divider, self).register_frame(frame) ++ super().register_frame(frame) + if self._line_char is None: +- self._line_char = u"─" if self._frame.canvas.unicode_aware else "-" ++ self._line_char = "─" if self._frame.canvas.unicode_aware else "-" + + def process_event(self, event): + # Dividers have no user interactions +Index: asciimatics-1.14.0/asciimatics/widgets/dropdownlist.py +=================================================================== +--- asciimatics-1.14.0.orig/asciimatics/widgets/dropdownlist.py ++++ asciimatics-1.14.0/asciimatics/widgets/dropdownlist.py +@@ -1,9 +1,4 @@ +-# -*- coding: utf-8 -*- + """This module defines a dropdown list widget""" +-from __future__ import division +-from __future__ import absolute_import +-from __future__ import print_function +-from __future__ import unicode_literals + from asciimatics.event import KeyboardEvent, MouseEvent + from asciimatics.screen import Screen + from asciimatics.widgets.divider import Divider +@@ -40,7 +35,7 @@ class _DropdownPopup(_TempPopup): + else: + width = parent.width + # Construct the Frame +- super(_DropdownPopup, self).__init__(parent.frame.screen, ++ super().__init__(parent.frame.screen, + parent, + location[0], start_line, + width, height) +@@ -53,7 +48,7 @@ class _DropdownPopup(_TempPopup): + divider = Divider() + divider.disabled = True + self._list = ListBox(Widget.FILL_FRAME, +- [(" {}".format(i[0]), i[1]) for i in parent.options], ++ [(f" {i[0]}", i[1]) for i in parent.options], + add_scroll_bar=len(parent.options) > height - 4, + on_select=self.close, on_change=self._link) + layout.add_widget(self._list if reverse else self._field, 0) +@@ -96,7 +91,7 @@ class DropdownList(Widget): + + Also see the common keyword arguments in :py:obj:`.Widget`. + """ +- super(DropdownList, self).__init__(name, **kwargs) ++ super().__init__(name, **kwargs) + self._label = label + self._on_change = on_change + self._child = None +Index: asciimatics-1.14.0/asciimatics/widgets/filebrowser.py +=================================================================== +--- asciimatics-1.14.0.orig/asciimatics/widgets/filebrowser.py ++++ asciimatics-1.14.0/asciimatics/widgets/filebrowser.py +@@ -1,9 +1,4 @@ +-# -*- coding: utf-8 -*- + """This module defines a file browser selection""" +-from __future__ import division +-from __future__ import absolute_import +-from __future__ import print_function +-from __future__ import unicode_literals + from re import compile as re_compile + import os + import unicodedata +@@ -31,7 +26,7 @@ class FileBrowser(MultiColumnListBox): + you must use a regex that matches to the end of the line - e.g. use ".*\.txt$" to find files ending + with ".txt". This ensures that you don't accidentally pick up files containing the filter. + """ +- super(FileBrowser, self).__init__( ++ super().__init__( + height, + [0, ">8", ">14"], + [], +@@ -55,7 +50,7 @@ class FileBrowser(MultiColumnListBox): + if not self._initialized: + self._populate_list(self._root) + self._initialized = True +- super(FileBrowser, self).update(frame_no) ++ super().update(frame_no) + + def _on_selection(self): + """ +@@ -118,16 +113,16 @@ class FileBrowser(MultiColumnListBox): + details = namedtuple("stat_type", "st_size st_mtime") + details.st_size = 0 + details.st_mtime = 0 +- name = "|-- {}".format(my_file) ++ name = f"|-- {my_file}" + tree = tree_files + if os.path.isdir(full_path): + tree = tree_dirs + if os.path.islink(full_path): + # Show links separately for directories + real_path = os.path.realpath(full_path) +- name = "|-+ {} -> {}".format(my_file, real_path) ++ name = f"|-+ {my_file} -> {real_path}" + else: +- name = "|-+ {}".format(my_file) ++ name = f"|-+ {my_file}" + elif self._file_filter and not self._file_filter.match(my_file): + # Skip files that don't match the filter (if present) + continue +@@ -141,11 +136,11 @@ class FileBrowser(MultiColumnListBox): + real_path = None + if real_path and os.path.exists(real_path): + details = os.stat(real_path) +- name = "|-- {} -> {}".format(my_file, real_path) ++ name = f"|-- {my_file} -> {real_path}" + else: + # Both broken directory and file links fall to this case. + # Actually using the files will cause a FileNotFound exception +- name = "|-- {} -> {}".format(my_file, real_path) ++ name = f"|-- {my_file} -> {real_path}" + + # Normalize names for MacOS and then add to the list. + tree.append(([unicodedata.normalize("NFC", name), +Index: asciimatics-1.14.0/asciimatics/widgets/frame.py +=================================================================== +--- asciimatics-1.14.0.orig/asciimatics/widgets/frame.py ++++ asciimatics-1.14.0/asciimatics/widgets/frame.py +@@ -1,10 +1,4 @@ +-# -*- coding: utf-8 -*- + """This module defines a class to display widgets""" +-from __future__ import division +-from __future__ import absolute_import +-from __future__ import print_function +-from __future__ import unicode_literals +-from builtins import range + from copy import copy, deepcopy + from logging import getLogger + from wcwidth import wcswidth +@@ -152,7 +146,7 @@ class Frame(Effect): + receiving input events. + :param can_scroll: Whether a scrollbar should be available on the border, or not. + """ +- super(Frame, self).__init__(screen) ++ super().__init__(screen) + self._focus = 0 + self._max_height = 0 + self._layouts = [] +@@ -601,7 +595,7 @@ class Frame(Effect): + self._focus = len(self._layouts) - 1 + if self._focus >= len(self._layouts): + self._focus = 0 +- logger.debug("Trying tab to layout {}".format(self._focus)) ++ logger.debug(f"Trying tab to layout {self._focus}") + try: + if direction > 0: + self._layouts[self._focus].focus(force_first=True) +Index: asciimatics-1.14.0/asciimatics/widgets/label.py +=================================================================== +--- asciimatics-1.14.0.orig/asciimatics/widgets/label.py ++++ asciimatics-1.14.0/asciimatics/widgets/label.py +@@ -1,10 +1,4 @@ +-# -*- coding: utf-8 -*- + """This mdoule implements a widget to give a text label""" +-from __future__ import division +-from __future__ import absolute_import +-from __future__ import print_function +-from __future__ import unicode_literals +-from builtins import str + from asciimatics.widgets.widget import Widget + from asciimatics.widgets.utilities import _split_text + +@@ -26,7 +20,7 @@ class Label(Widget): + + """ + # Labels have no value and so should have no name for look-ups either. +- super(Label, self).__init__(name, tab_stop=False) ++ super().__init__(name, tab_stop=False) + + # Although this is a label, we don't want it to contribute to the layout + # tab calculations, so leave internal `_label` value as None. +Index: asciimatics-1.14.0/asciimatics/widgets/layout.py +=================================================================== +--- asciimatics-1.14.0.orig/asciimatics/widgets/layout.py ++++ asciimatics-1.14.0/asciimatics/widgets/layout.py +@@ -1,11 +1,4 @@ +-# -*- coding: utf-8 -*- + """This module implements the displaying of widgets appropriately""" +-from __future__ import division +-from __future__ import absolute_import +-from __future__ import print_function +-from __future__ import unicode_literals +-from builtins import range +-from builtins import object + from logging import getLogger + from wcwidth import wcswidth + from asciimatics.event import KeyboardEvent, MouseEvent +@@ -19,7 +12,7 @@ from asciimatics.widgets.widget import W + logger = getLogger(__name__) + + +-class Layout(object): ++class Layout(): + """ + Widget layout handler. + +Index: asciimatics-1.14.0/asciimatics/widgets/listbox.py +=================================================================== +--- asciimatics-1.14.0.orig/asciimatics/widgets/listbox.py ++++ asciimatics-1.14.0/asciimatics/widgets/listbox.py +@@ -1,11 +1,4 @@ +-# -*- coding: utf-8 -*- + """This module implements the listbox widget""" +-from __future__ import division +-from __future__ import absolute_import +-from __future__ import print_function +-from __future__ import unicode_literals +-from builtins import str +-from builtins import range + from asciimatics.strings import ColouredText + from asciimatics.widgets.utilities import _enforce_width + from asciimatics.widgets.baselistbox import _BaseListBox +@@ -35,7 +28,7 @@ class ListBox(_BaseListBox): + + options=[("First option", 1), ("Second option", 2)] + """ +- super(ListBox, self).__init__( ++ super().__init__( + height, options, label=label, name=name, parser=parser, on_change=on_change, + on_select=on_select, validator=validator) + self._centre = centre +Index: asciimatics-1.14.0/asciimatics/widgets/multicolumnlistbox.py +=================================================================== +--- asciimatics-1.14.0.orig/asciimatics/widgets/multicolumnlistbox.py ++++ asciimatics-1.14.0/asciimatics/widgets/multicolumnlistbox.py +@@ -1,13 +1,6 @@ +-# -*- coding: utf-8 -*- + """This module implements the widget for a multiple column list box""" +-from __future__ import division +-from __future__ import absolute_import +-from __future__ import print_function +-from __future__ import unicode_literals +-from builtins import str +-from builtins import range + from re import match as re_match +-from future.moves.itertools import zip_longest ++from itertools import zip_longest + from asciimatics.strings import ColouredText + from asciimatics.widgets.utilities import _enforce_width + from asciimatics.widgets.baselistbox import _BaseListBox +Index: asciimatics-1.14.0/asciimatics/widgets/popupdialog.py +=================================================================== +--- asciimatics-1.14.0.orig/asciimatics/widgets/popupdialog.py ++++ asciimatics-1.14.0/asciimatics/widgets/popupdialog.py +@@ -1,9 +1,4 @@ +-# -*- coding: utf-8 -*- + """This module implements a Pop up dialog message box""" +-from __future__ import division +-from __future__ import absolute_import +-from __future__ import print_function +-from __future__ import unicode_literals + from inspect import isfunction + from functools import partial + from wcwidth import wcswidth +@@ -55,7 +50,7 @@ class PopUpDialog(Frame): + + # Construct the Frame + self._data = {"message": self._message} +- super(PopUpDialog, self).__init__( ++ super().__init__( + screen, height, width, self._data, has_shadow=has_shadow, is_modal=True) + + # Build up the message box +Index: asciimatics-1.14.0/asciimatics/widgets/popupmenu.py +=================================================================== +--- asciimatics-1.14.0.orig/asciimatics/widgets/popupmenu.py ++++ asciimatics-1.14.0/asciimatics/widgets/popupmenu.py +@@ -1,9 +1,4 @@ +-# -*- coding: utf-8 -*- + """This module implements a pop up menu widget""" +-from __future__ import division +-from __future__ import absolute_import +-from __future__ import print_function +-from __future__ import unicode_literals + from collections import defaultdict + from functools import partial + from asciimatics.event import KeyboardEvent, MouseEvent +@@ -42,7 +37,7 @@ class PopupMenu(Frame): + y -= h - 1 + + # Construct the Frame +- super(PopupMenu, self).__init__( ++ super().__init__( + screen, h, w, x=x, y=y, has_border=False, can_scroll=False, is_modal=True, hover_focus=True) + + # Build the widget to display the time selection. +@@ -72,4 +67,4 @@ class PopupMenu(Frame): + event = None + if event is None: + self._destroy() +- return super(PopupMenu, self).process_event(event) ++ return super().process_event(event) +Index: asciimatics-1.14.0/asciimatics/widgets/radiobuttons.py +=================================================================== +--- asciimatics-1.14.0.orig/asciimatics/widgets/radiobuttons.py ++++ asciimatics-1.14.0/asciimatics/widgets/radiobuttons.py +@@ -1,9 +1,4 @@ +-# -*- coding: utf-8 -*- + """This module implements the widget for radio buttons""" +-from __future__ import division +-from __future__ import absolute_import +-from __future__ import print_function +-from __future__ import unicode_literals + from asciimatics.event import KeyboardEvent, MouseEvent + from asciimatics.screen import Screen + from asciimatics.widgets.widget import Widget +@@ -27,7 +22,7 @@ class RadioButtons(Widget): + + Also see the common keyword arguments in :py:obj:`.Widget`. + """ +- super(RadioButtons, self).__init__(name, **kwargs) ++ super().__init__(name, **kwargs) + self._options = options + self._label = label + self._selection = 0 +@@ -38,7 +33,7 @@ class RadioButtons(Widget): + self._draw_label() + + # Decide on check char +- check_char = u"•" if self._frame.canvas.unicode_aware else "X" ++ check_char = "•" if self._frame.canvas.unicode_aware else "X" + + # Render the list of radio buttons. + for i, (text, _) in enumerate(self._options): +@@ -46,7 +41,7 @@ class RadioButtons(Widget): + fg2, attr2, bg2 = self._pick_colours("field", self._has_focus and i == self._selection) + check = check_char if i == self._selection else " " + self._frame.canvas.print_at( +- "({}) ".format(check), ++ f"({check}) ", + self._x + self._offset, + self._y + i, + fg, attr, bg) +Index: asciimatics-1.14.0/asciimatics/widgets/scrollbar.py +=================================================================== +--- asciimatics-1.14.0.orig/asciimatics/widgets/scrollbar.py ++++ asciimatics-1.14.0/asciimatics/widgets/scrollbar.py +@@ -1,14 +1,6 @@ +-# -*- coding: utf-8 -*- + """This module implements a scroll bar capability for widgets""" +-from __future__ import division +-from __future__ import absolute_import +-from __future__ import print_function +-from __future__ import unicode_literals +-from builtins import range +-from builtins import object + +- +-class _ScrollBar(object): ++class _ScrollBar(): + """ + Internal object to provide vertical scroll bars for widgets. + """ +@@ -48,8 +40,8 @@ class _ScrollBar(object): + Draw the scroll bar. + """ + # Sort out chars +- cursor = u"█" if self._canvas.unicode_aware else "O" +- back = u"░" if self._canvas.unicode_aware else "|" ++ cursor = "█" if self._canvas.unicode_aware else "O" ++ back = "░" if self._canvas.unicode_aware else "|" + + # Now draw... + try: +Index: asciimatics-1.14.0/asciimatics/widgets/temppopup.py +=================================================================== +--- asciimatics-1.14.0.orig/asciimatics/widgets/temppopup.py ++++ asciimatics-1.14.0/asciimatics/widgets/temppopup.py +@@ -1,9 +1,4 @@ +-# -*- coding: utf-8 -*- + """This module implements a base class for popups""" +-from __future__ import division +-from __future__ import absolute_import +-from __future__ import print_function +-from __future__ import unicode_literals + from collections import defaultdict + from abc import abstractmethod + from asciimatics.event import KeyboardEvent, MouseEvent +@@ -27,7 +22,7 @@ class _TempPopup(Frame): + :param h: The height of the desired pop-up. + """ + # Construct the Frame +- super(_TempPopup, self).__init__( ++ super().__init__( + screen, h, w, x=x, y=y, has_border=True, can_scroll=False, is_modal=True) + + # Set up the new palette for this Frame +@@ -63,7 +58,7 @@ class _TempPopup(Frame): + except InvalidFields: + # Nothing to do as we've already prevented the Effect from being removed. + pass +- return super(_TempPopup, self).process_event(event) ++ return super().process_event(event) + + def close(self, cancelled=False): + """ +Index: asciimatics-1.14.0/asciimatics/widgets/text.py +=================================================================== +--- asciimatics-1.14.0.orig/asciimatics/widgets/text.py ++++ asciimatics-1.14.0/asciimatics/widgets/text.py +@@ -1,10 +1,4 @@ +-# -*- coding: utf-8 -*- + """This widget implements a text based input field""" +-from __future__ import division +-from __future__ import absolute_import +-from __future__ import print_function +-from __future__ import unicode_literals +-from builtins import chr + from re import match + from asciimatics.event import KeyboardEvent, MouseEvent + from asciimatics.screen import Screen +@@ -38,7 +32,7 @@ class Text(Widget): + + Also see the common keyword arguments in :py:obj:`.Widget`. + """ +- super(Text, self).__init__(name, **kwargs) ++ super().__init__(name, **kwargs) + self._label = label + self._column = 0 + self._start_column = 0 +@@ -50,7 +44,7 @@ class Text(Widget): + + def set_layout(self, x, y, offset, w, h): + # Do the usual layout work. then apply max length to resulting dimensions. +- super(Text, self).set_layout(x, y, offset, w, h) ++ super().set_layout(x, y, offset, w, h) + if self._max_length: + # Allow extra char for cursor, so contents don't scroll at required length + self._w = min(self._w, self._max_length + self._offset + 1) +Index: asciimatics-1.14.0/asciimatics/widgets/textbox.py +=================================================================== +--- asciimatics-1.14.0.orig/asciimatics/widgets/textbox.py ++++ asciimatics-1.14.0/asciimatics/widgets/textbox.py +@@ -1,11 +1,4 @@ +-# -*- coding: utf-8 -*- + """This module implements a multi line editing text box""" +-from __future__ import division +-from __future__ import absolute_import +-from __future__ import print_function +-from __future__ import unicode_literals +-from builtins import chr +-from builtins import str + from copy import copy + from logging import getLogger + from asciimatics.event import KeyboardEvent, MouseEvent +@@ -44,7 +37,7 @@ class TextBox(Widget): + + Also see the common keyword arguments in :py:obj:`.Widget`. + """ +- super(TextBox, self).__init__(name, **kwargs) ++ super().__init__(name, **kwargs) + self._label = label + self._line = 0 + self._column = 0 +Index: asciimatics-1.14.0/asciimatics/widgets/timepicker.py +=================================================================== +--- asciimatics-1.14.0.orig/asciimatics/widgets/timepicker.py ++++ asciimatics-1.14.0/asciimatics/widgets/timepicker.py +@@ -1,11 +1,5 @@ +-# -*- coding: utf-8 -*- + """This module implements a time picker widget""" +-from __future__ import division +-from __future__ import absolute_import +-from __future__ import print_function +-from __future__ import unicode_literals + from datetime import datetime +-from builtins import range + + from asciimatics.event import KeyboardEvent, MouseEvent + from asciimatics.screen import Screen +@@ -27,15 +21,15 @@ class _TimePickerPopup(_TempPopup): + """ + # Construct the Frame + location = parent.get_location() +- super(_TimePickerPopup, self).__init__(parent.frame.screen, ++ super().__init__(parent.frame.screen, + parent, + location[0] - 1, location[1] - 2, + 10 if parent.include_seconds else 7, 5) + + # Build the widget to display the time selection. +- self._hours = ListBox(3, [("{:02}".format(x), x) for x in range(24)], centre=True) +- self._minutes = ListBox(3, [("{:02}".format(x), x) for x in range(60)], centre=True) +- self._seconds = ListBox(3, [("{:02}".format(x), x) for x in range(60)], centre=True) ++ self._hours = ListBox(3, [(f"{x:02}", x) for x in range(24)], centre=True) ++ self._minutes = ListBox(3, [(f"{x:02}", x) for x in range(60)], centre=True) ++ self._seconds = ListBox(3, [(f"{x:02}", x) for x in range(60)], centre=True) + if self._parent.include_seconds: + layout = Layout([2, 1, 2, 1, 2], fill_frame=True) + else: +@@ -77,7 +71,7 @@ class TimePicker(Widget): + + Also see the common keyword arguments in :py:obj:`.Widget`. + """ +- super(TimePicker, self).__init__(name, **kwargs) ++ super().__init__(name, **kwargs) + self._label = label + self._on_change = on_change + self._value = datetime.now().time() +Index: asciimatics-1.14.0/asciimatics/widgets/utilities.py +=================================================================== +--- asciimatics-1.14.0.orig/asciimatics/widgets/utilities.py ++++ asciimatics-1.14.0/asciimatics/widgets/utilities.py +@@ -1,18 +1,9 @@ +-# -*- coding: utf-8 -*- + """This module defines commonly used pieces for widgets""" +-from __future__ import division +-from __future__ import absolute_import +-from __future__ import print_function +-from __future__ import unicode_literals + from logging import getLogger + from math import sqrt +-from builtins import str + from collections import defaultdict + from wcwidth import wcswidth, wcwidth +-try: +- from functools import lru_cache +-except ImportError: +- from backports.functools_lru_cache import lru_cache ++from functools import lru_cache + from asciimatics.screen import Screen + + # Logging +Index: asciimatics-1.14.0/asciimatics/widgets/verticaldivider.py +=================================================================== +--- asciimatics-1.14.0.orig/asciimatics/widgets/verticaldivider.py ++++ asciimatics-1.14.0/asciimatics/widgets/verticaldivider.py +@@ -1,10 +1,4 @@ +-# -*- coding: utf-8 -*- + """This module implements a vertical division between widgets""" +-from __future__ import division +-from __future__ import absolute_import +-from __future__ import print_function +-from __future__ import unicode_literals +-from builtins import range + from asciimatics.widgets.widget import Widget + + +@@ -21,7 +15,7 @@ class VerticalDivider(Widget): + """ + :param height: The required height for this divider. + """ +- super(VerticalDivider, self).__init__(None, tab_stop=False) ++ super().__init__(None, tab_stop=False) + self._required_height = height + + def process_event(self, event): +@@ -29,7 +23,7 @@ class VerticalDivider(Widget): + + def update(self, frame_no): + (color, attr, background) = self._frame.palette["borders"] +- vert = u"│" if self._frame.canvas.unicode_aware else "|" ++ vert = "│" if self._frame.canvas.unicode_aware else "|" + for i in range(self._h): + self._frame.canvas.print_at(vert, self._x, self._y + i, color, attr, background) + +Index: asciimatics-1.14.0/asciimatics/widgets/widget.py +=================================================================== +--- asciimatics-1.14.0.orig/asciimatics/widgets/widget.py ++++ asciimatics-1.14.0/asciimatics/widgets/widget.py +@@ -1,17 +1,9 @@ +-# -*- coding: utf-8 -*- + """ + This module allows you to create interactive text user interfaces. For more details see + http://asciimatics.readthedocs.io/en/latest/widgets.html + """ +-from __future__ import division +-from __future__ import absolute_import +-from __future__ import print_function +-from __future__ import unicode_literals +- +-from builtins import object + from abc import ABCMeta, abstractmethod, abstractproperty + +-from future.utils import with_metaclass + from logging import getLogger + from wcwidth import wcswidth + from asciimatics.screen import Screen +@@ -21,7 +13,7 @@ from asciimatics.widgets.utilities impor + logger = getLogger(__name__) + + +-class Widget(with_metaclass(ABCMeta, object)): ++class Widget(metaclass=ABCMeta): + """ + A Widget is a re-usable component that can be used to create a simple GUI. + """ +@@ -47,7 +39,7 @@ class Widget(with_metaclass(ABCMeta, obj + :param on_focus: Optional callback whenever this widget gets the focus. + :param on_blur: Optional callback whenever this widget loses the focus. + """ +- super(Widget, self).__init__() ++ super().__init__() + # Internal properties + self._name = name + self._label = None +Index: asciimatics-1.14.0/doc/source/troubleshooting.rst +=================================================================== +--- asciimatics-1.14.0.orig/doc/source/troubleshooting.rst ++++ asciimatics-1.14.0/doc/source/troubleshooting.rst +@@ -288,13 +288,6 @@ It's just not working at all + Some people have reported truly strange issues where things simply don't start up at all. + Symptoms vary wildly from blank screens to other applications or tests running instead. + +-If you are hitting something like this, check that you haven't created a file called ``test.py`` +-in your project. This is because the ``future`` package, which asciimatics uses for +-compatibility with Python 2 and 3, imports the test package. If you happen to have a file called +-``test.py`` in your project, this import could pick up your file instead of the built-in package. +- +-Shout out to Andrew Penniman for spotting and solving this one! +- + It's too slow! + -------------- + When people say this, they either mean that asciimatics is using too much CPU, or that it is +Index: asciimatics-1.14.0/doc/source/widgets.rst +=================================================================== +--- asciimatics-1.14.0.orig/doc/source/widgets.rst ++++ asciimatics-1.14.0/doc/source/widgets.rst +@@ -91,7 +91,7 @@ basic classes: + + .. code-block:: python + +- class ContactModel(object): ++ class ContactModel(): + def __init__(self): + # Create a database in RAM + self._db = sqlite3.connect(':memory:') +Index: asciimatics-1.14.0/requirements/base.txt +=================================================================== +--- asciimatics-1.14.0.orig/requirements/base.txt ++++ asciimatics-1.14.0/requirements/base.txt +@@ -1,6 +1,3 @@ + wcwidth +-mock + pyfiglet >= 0.7.2 +-future + setuptools_scm +-backports.functools_lru_cache ; python_version < "3.0" +Index: asciimatics-1.14.0/samples/256colour.py +=================================================================== +--- asciimatics-1.14.0.orig/samples/256colour.py ++++ asciimatics-1.14.0/samples/256colour.py +@@ -1,6 +1,5 @@ + #!/usr/bin/env python3 + +-from __future__ import division + from asciimatics.effects import Print, Clock + from asciimatics.renderers import FigletText, Rainbow + from asciimatics.scene import Scene +Index: asciimatics-1.14.0/samples/basics.py +=================================================================== +--- asciimatics-1.14.0.orig/samples/basics.py ++++ asciimatics-1.14.0/samples/basics.py +@@ -1,7 +1,5 @@ + #!/usr/bin/env python3 + +-from __future__ import division +-from builtins import range + import copy + import math + from asciimatics.effects import Cycle, Print, Stars +Index: asciimatics-1.14.0/samples/bg_colours.py +=================================================================== +--- asciimatics-1.14.0.orig/samples/bg_colours.py ++++ asciimatics-1.14.0/samples/bg_colours.py +@@ -1,6 +1,5 @@ + #!/usr/bin/env python3 + +-from __future__ import division + from asciimatics.effects import Wipe, Print + from asciimatics.renderers import FigletText, SpeechBubble + from asciimatics.scene import Scene +Index: asciimatics-1.14.0/samples/cogs.py +=================================================================== +--- asciimatics-1.14.0.orig/samples/cogs.py ++++ asciimatics-1.14.0/samples/cogs.py +@@ -1,6 +1,5 @@ + #!/usr/bin/env python3 + +-from __future__ import division + from asciimatics.effects import Cog, Print + from asciimatics.renderers import FigletText + from asciimatics.scene import Scene +Index: asciimatics-1.14.0/samples/contact_list.py +=================================================================== +--- asciimatics-1.14.0.orig/samples/contact_list.py ++++ asciimatics-1.14.0/samples/contact_list.py +@@ -9,7 +9,7 @@ import sys + import sqlite3 + + +-class ContactModel(object): ++class ContactModel(): + def __init__(self): + # Create a database in RAM. + self._db = sqlite3.connect(':memory:') +Index: asciimatics-1.14.0/samples/credits.py +=================================================================== +--- asciimatics-1.14.0.orig/samples/credits.py ++++ asciimatics-1.14.0/samples/credits.py +@@ -1,6 +1,5 @@ + #!/usr/bin/env python3 + +-from __future__ import division + import sys + from pyfiglet import Figlet + +Index: asciimatics-1.14.0/samples/images.py +=================================================================== +--- asciimatics-1.14.0.orig/samples/images.py ++++ asciimatics-1.14.0/samples/images.py +@@ -1,6 +1,5 @@ + #!/usr/bin/env python3 + +-from __future__ import division + from asciimatics.effects import BannerText, Print, Scroll + from asciimatics.renderers import ColourImageFile, FigletText, ImageFile + from asciimatics.scene import Scene +Index: asciimatics-1.14.0/samples/maps.py +=================================================================== +--- asciimatics-1.14.0.orig/samples/maps.py ++++ asciimatics-1.14.0/samples/maps.py +@@ -1,8 +1,6 @@ + #!/usr/bin/env python3 + + # -*- coding: utf-8 -*- +-from __future__ import division +-from __future__ import print_function + import traceback + from math import pi, exp, atan, log, tan, sqrt + import sys +Index: asciimatics-1.14.0/samples/quick_model.py +=================================================================== +--- asciimatics-1.14.0.orig/samples/quick_model.py ++++ asciimatics-1.14.0/samples/quick_model.py +@@ -8,7 +8,7 @@ from asciimatics.exceptions import Resiz + import sys + + +-class ContactModel(object): ++class ContactModel(): + def __init__(self): + # Current contact when editing. + self.current_id = None +Index: asciimatics-1.14.0/samples/ray_casting.py +=================================================================== +--- asciimatics-1.14.0.orig/samples/ray_casting.py ++++ asciimatics-1.14.0/samples/ray_casting.py +@@ -1,10 +1,6 @@ + #!/usr/bin/env python3 + + # -*- coding: utf-8 -*- +-from __future__ import division +-from __future__ import absolute_import +-from __future__ import print_function +-from __future__ import unicode_literals + import sys + from math import sin, cos, pi, copysign, floor + from asciimatics.effects import Effect +@@ -43,7 +39,7 @@ XXXXXXXXXXXXXX X + IMAGE_HEIGHT = 64 + + +-class Image(object): ++class Image(): + """ + Class to handle image stripe rendering. + """ +@@ -77,7 +73,7 @@ class Image(object): + pass + + +-class Sprite(object): ++class Sprite(): + """ + Dynamically sized sprite. + """ +@@ -97,7 +93,7 @@ class Sprite(object): + self._state.screen, height, x, int(image_x * IMAGE_HEIGHT / height)) + + +-class GameState(object): ++class GameState(): + """ + Persistent state for this application. + """ +Index: asciimatics-1.14.0/samples/simple.py +=================================================================== +--- asciimatics-1.14.0.orig/samples/simple.py ++++ asciimatics-1.14.0/samples/simple.py +@@ -1,6 +1,5 @@ + #!/usr/bin/env python3 + +-from __future__ import division + from asciimatics.effects import Cycle, Stars + from asciimatics.renderers import FigletText + from asciimatics.scene import Scene +Index: asciimatics-1.14.0/samples/xmas.py +=================================================================== +--- asciimatics-1.14.0.orig/samples/xmas.py ++++ asciimatics-1.14.0/samples/xmas.py +@@ -1,6 +1,5 @@ + #!/usr/bin/env python3 + +-from __future__ import division + from asciimatics.effects import Cycle, Snow, Print + from asciimatics.renderers import FigletText, StaticRenderer + from asciimatics.scene import Scene +Index: asciimatics-1.14.0/tests/mock_objects.py +=================================================================== +--- asciimatics-1.14.0.orig/tests/mock_objects.py ++++ asciimatics-1.14.0/tests/mock_objects.py +@@ -15,7 +15,7 @@ class MockEffect(Effect): + :param next_scene: The next scene to move to (if stop=False) + :param frame_rate: The frame rate for updates. + """ +- super(MockEffect, self).__init__(None, **kwargs) ++ super().__init__(None, **kwargs) + self.stop_called = False + self.reset_called = False + self.event_called = False +Index: asciimatics-1.14.0/tests/renderers/test_base.py +=================================================================== +--- asciimatics-1.14.0.orig/tests/renderers/test_base.py ++++ asciimatics-1.14.0/tests/renderers/test_base.py +@@ -1,9 +1,3 @@ +-# -*- coding: utf-8 -*- +-from __future__ import division +-from __future__ import absolute_import +-from __future__ import print_function +-from __future__ import unicode_literals +-from builtins import str + import unittest + from asciimatics.renderers import StaticRenderer + from asciimatics.screen import Screen +Index: asciimatics-1.14.0/tests/renderers/test_charts.py +=================================================================== +--- asciimatics-1.14.0.orig/tests/renderers/test_charts.py ++++ asciimatics-1.14.0/tests/renderers/test_charts.py +@@ -1,9 +1,3 @@ +-# -*- coding: utf-8 -*- +-from __future__ import division +-from __future__ import absolute_import +-from __future__ import print_function +-from __future__ import unicode_literals +-from builtins import str + import unittest + from asciimatics.constants import ASCII_LINE, SINGLE_LINE + from asciimatics.renderers import BarChart, VBarChart +Index: asciimatics-1.14.0/tests/renderers/test_images.py +=================================================================== +--- asciimatics-1.14.0.orig/tests/renderers/test_images.py ++++ asciimatics-1.14.0/tests/renderers/test_images.py +@@ -1,8 +1,3 @@ +-# -*- coding: utf-8 -*- +-from __future__ import division +-from __future__ import absolute_import +-from __future__ import print_function +-from __future__ import unicode_literals + import unittest + import os + import sys +Index: asciimatics-1.14.0/tests/renderers/test_other.py +=================================================================== +--- asciimatics-1.14.0.orig/tests/renderers/test_other.py ++++ asciimatics-1.14.0/tests/renderers/test_other.py +@@ -1,9 +1,3 @@ +-# -*- coding: utf-8 -*- +-from __future__ import division +-from __future__ import absolute_import +-from __future__ import print_function +-from __future__ import unicode_literals +-from builtins import str + import unittest + import os + import sys +@@ -24,9 +18,9 @@ class TestRendererOthers(unittest.TestCa + str(renderer), + " _ _ _ \n" + + "| |__ ___| | | ___ \n" + +- "| '_ \ / _ \ | |/ _ \ \n" + ++ "| '_ \\ / _ \\ | |/ _ \\ \n" + + "| | | | __/ | | (_) |\n" + +- "|_| |_|\___|_|_|\___/ \n" + ++ "|_| |_|\\___|_|_|\\___/ \n" + + " \n") + + def test_bubble(self): +@@ -61,9 +55,9 @@ class TestRendererOthers(unittest.TestCa + # Unicode rendering. + renderer = SpeechBubble("hello", uni=True) + self.assertEqual(str(renderer), +- u"╭───────╮\n" +- u"│ hello │\n" +- u"╰───────╯") ++ "╭───────╮\n" ++ "│ hello │\n" ++ "╰───────╯") + + # Multiline text rendering + text = "Hello\n" \ +Index: asciimatics-1.14.0/tests/renderers/test_players.py +=================================================================== +--- asciimatics-1.14.0.orig/tests/renderers/test_players.py ++++ asciimatics-1.14.0/tests/renderers/test_players.py +@@ -1,9 +1,3 @@ +-# -*- coding: utf-8 -*- +-from __future__ import division +-from __future__ import absolute_import +-from __future__ import print_function +-from __future__ import unicode_literals +-from builtins import str + import unittest + import os + from asciimatics.renderers import AnsiArtPlayer, AsciinemaPlayer +Index: asciimatics-1.14.0/tests/test_effects.py +=================================================================== +--- asciimatics-1.14.0.orig/tests/test_effects.py ++++ asciimatics-1.14.0/tests/test_effects.py +@@ -1,7 +1,6 @@ +-from builtins import chr + import unittest + from datetime import datetime +-from mock.mock import MagicMock, patch ++from unittest.mock import MagicMock, patch + from random import randint + import os + import sys +Index: asciimatics-1.14.0/tests/test_events.py +=================================================================== +--- asciimatics-1.14.0.orig/tests/test_events.py ++++ asciimatics-1.14.0/tests/test_events.py +@@ -23,7 +23,7 @@ class TestEvents(unittest.TestCase): + self.assertEqual(event.x, x) + self.assertEqual(event.y, y) + self.assertEqual(event.buttons, buttons) +- self.assertIn("({}, {})".format(x, y), str(event)) ++ self.assertIn(f"({x}, {y})", str(event)) + self.assertIn(str(buttons), str(event)) + + +Index: asciimatics-1.14.0/tests/test_parsers.py +=================================================================== +--- asciimatics-1.14.0.orig/tests/test_parsers.py ++++ asciimatics-1.14.0/tests/test_parsers.py +@@ -1,8 +1,3 @@ +-# -*- coding: utf-8 -*- +-from __future__ import division +-from __future__ import absolute_import +-from __future__ import print_function +-from __future__ import unicode_literals + import unittest + from asciimatics.parsers import AsciimaticsParser, AnsiTerminalParser, ControlCodeParser, Parser + import asciimatics.constants as constants +Index: asciimatics-1.14.0/tests/test_screen.py +=================================================================== +--- asciimatics-1.14.0.orig/tests/test_screen.py ++++ asciimatics-1.14.0/tests/test_screen.py +@@ -1,18 +1,9 @@ +-# -*- coding: utf-8 -*- +-from __future__ import division +-from __future__ import absolute_import +-from __future__ import print_function +-from __future__ import unicode_literals +- + import os +-from mock import MagicMock + from random import randint + import unittest ++from unittest.mock import MagicMock + import sys + import time +-from builtins import str +-from builtins import chr +-from builtins import bytes + from asciimatics.event import KeyboardEvent, MouseEvent + from asciimatics.exceptions import StopApplication, NextScene + try: +@@ -64,7 +55,7 @@ class TestScreen(unittest.TestCase): + try: + char, _, _, _ = canvas.get_from(x, y) + except Exception: +- raise RuntimeError("{} {}".format(x, y)) ++ raise RuntimeError(f"{x} {y}") + output += chr(char) + output += "\n" + self.assertEqual(output, expected) +@@ -593,7 +584,7 @@ class TestScreen(unittest.TestCase): + # we don't catch interrupts). Still a good basic check for + # input, though. + event = win32console.PyINPUT_RECORDType(win32console.KEY_EVENT) +- event.Char = u"\03" ++ event.Char = "\03" + event.KeyDown = 1 + event.RepeatCount = 1 + event.ControlKeyState = win32con.LEFT_CTRL_PRESSED +@@ -656,8 +647,8 @@ class TestScreen(unittest.TestCase): + event.VirtualKeyCode = ord(chr(char).upper()) + else: + # Lookup in mapping dicts +- reverse = dict((v, k) for k, v in +- screen._EXTRA_KEY_MAP.items()) ++ reverse = {v: k for k, v in ++ screen._EXTRA_KEY_MAP.items()} + if char in reverse: + event.VirtualKeyCode = reverse[char] + else: +@@ -665,8 +656,8 @@ class TestScreen(unittest.TestCase): + if char == Screen.KEY_BACK_TAB: + char = Screen.KEY_TAB + event.ControlKeyState = win32con.SHIFT_PRESSED +- reverse = dict((v, k) for k, v in +- screen._KEY_MAP.items()) ++ reverse = {v: k for k, v in ++ screen._KEY_MAP.items()} + event.VirtualKeyCode = reverse[char] + event.KeyDown = 1 + screen._stdin.WriteConsoleInput([event]) +@@ -680,8 +671,8 @@ class TestScreen(unittest.TestCase): + for c in reversed(bytes(chr(char).encode("utf-8"))): + curses.ungetch(c) + else: +- reverse = dict((v, k) for k, v in +- screen._KEY_MAP.items()) ++ reverse = {v: k for k, v in ++ screen._KEY_MAP.items()} + curses.ungetch(reverse[char]) + + @staticmethod +@@ -736,15 +727,15 @@ class TestScreen(unittest.TestCase): + self.assertIsNone(screen.get_key()) + + # Check that unicode input also works +- self._inject_key(screen, ord(u"├")) ++ self._inject_key(screen, ord("├")) + ch = screen.get_event() +- self.assertEqual(ch.key_code, ord(u"├")) ++ self.assertEqual(ch.key_code, ord("├")) + self.assertIsNone(screen.get_event()) + + # Check that unicode input colliding with curses KEY_MAP also works (code: 263) +- self._inject_key(screen, ord(u"ć")) ++ self._inject_key(screen, ord("ć")) + ch = screen.get_event() +- self.assertEqual(ch.key_code, ord(u"ć")) ++ self.assertEqual(ch.key_code, ord("ć")) + self.assertIsNone(screen.get_event()) + + Screen.wrapper(internal_checks, height=15, unicode_aware=True) +@@ -901,7 +892,7 @@ class TestScreen(unittest.TestCase): + canvas.reset() + canvas.print_at("你確", -1, 0) + canvas.print_at("你確", canvas.width - 1, 0) +- self.assert_line_equals(canvas, u" 確確 ") ++ self.assert_line_equals(canvas, " 確確 ") + + def test_cjk_glyphs_overwrite(self): + """ +@@ -919,7 +910,7 @@ class TestScreen(unittest.TestCase): + + # Half-glyph appears as an "x" to show error and then double-width glyphs are returned + # twice, reflecting their extra width. +- self.assert_line_equals(screen, u"x你你確確 ", y=1, length=6) ++ self.assert_line_equals(screen, "x你你確確 ", y=1, length=6) + + def test_save_signal_state(self): + """Tests that the signal state class works properly. +Index: asciimatics-1.14.0/tests/test_strings.py +=================================================================== +--- asciimatics-1.14.0.orig/tests/test_strings.py ++++ asciimatics-1.14.0/tests/test_strings.py +@@ -1,8 +1,3 @@ +-# -*- coding: utf-8 -*- +-from __future__ import division +-from __future__ import absolute_import +-from __future__ import print_function +-from __future__ import unicode_literals + from datetime import datetime + import time + import unittest +Index: asciimatics-1.14.0/tests/test_utilities.py +=================================================================== +--- asciimatics-1.14.0.orig/tests/test_utilities.py ++++ asciimatics-1.14.0/tests/test_utilities.py +@@ -1,8 +1,3 @@ +-# -*- coding: utf-8 -*- +-from __future__ import division +-from __future__ import absolute_import +-from __future__ import print_function +-from __future__ import unicode_literals + from datetime import datetime + import time + import unittest +Index: asciimatics-1.14.0/tests/test_widgets.py +=================================================================== +--- asciimatics-1.14.0.orig/tests/test_widgets.py ++++ asciimatics-1.14.0/tests/test_widgets.py +@@ -1,17 +1,8 @@ +-# -*- coding: utf-8 -*- +-from __future__ import division +-from __future__ import absolute_import +-from __future__ import print_function +-from __future__ import unicode_literals + from datetime import date, time + from time import sleep +-from mock import patch +-from builtins import ord +-from builtins import chr +-from builtins import str + import unittest + import sys +-from mock.mock import MagicMock ++from unittest.mock import MagicMock, patch + from asciimatics.event import KeyboardEvent, MouseEvent + from asciimatics.exceptions import NextScene, StopApplication, InvalidFields + from asciimatics.scene import Scene +@@ -24,9 +15,9 @@ from asciimatics.parsers import Asciimat + from asciimatics.strings import ColouredText + + +-class TestFrame(Frame): ++class _TestFrame(Frame): + def __init__(self, screen, has_border=True, can_scroll=True, reduce_cpu=False, label_height=1): +- super(TestFrame, self).__init__(screen, ++ super().__init__(screen, + screen.height, + screen.width, + name="Test Form", +@@ -118,9 +109,9 @@ class TestFrame(Frame): + raise StopApplication("User requested exit") + + +-class TestFrame2(Frame): ++class _TestFrame2(Frame): + def __init__(self, screen, init_values): +- super(TestFrame2, self).__init__(screen, ++ super().__init__(screen, + screen.height, + screen.width, + data={"selected": "None"}, +@@ -177,17 +168,17 @@ class TestFrame2(Frame): + raise StopApplication("User pressed quit") + + +-class TestFrame3(Frame): ++class _TestFrame3(Frame): + def __init__(self, screen): +- super(TestFrame3, self).__init__(screen, 10, 20, ++ super().__init__(screen, 10, 20, + name="Blank", + has_shadow=True) + self.fix() + + +-class TestFrame4(Frame): ++class _TestFrame4(Frame): + def __init__(self, screen, file_filter=None): +- super(TestFrame4, self).__init__( ++ super().__init__( + screen, screen.height, screen.width, has_border=False, can_scroll=False, name="My Form") + + # State tracking for callbacks +@@ -213,9 +204,9 @@ class TestFrame4(Frame): + self.highlighted = self.file_list.value + + +-class TestFrame5(Frame): ++class _TestFrame5(Frame): + def __init__(self, screen): +- super(TestFrame5, self).__init__( ++ super().__init__( + screen, screen.height, screen.width, has_border=True, name="My Form") + + # Simple full-page Widget +@@ -238,9 +229,9 @@ class TestFrame5(Frame): + self.changed = True + + +-class TestFrame6(Frame): ++class _TestFrame6(Frame): + def __init__(self, screen): +- super(TestFrame6, self).__init__( ++ super().__init__( + screen, screen.height, screen.width, has_border=True, name="My Form") + + # Simple full-page Widget +@@ -296,7 +287,7 @@ class TestWidgets(unittest.TestCase): + """ + screen = MagicMock(spec=Screen, colours=8, unicode_aware=False) + canvas = Canvas(screen, 10, 40, 0, 0) +- form = TestFrame(canvas) ++ form = _TestFrame(canvas) + + # Should be empty on construction + self.assertEqual(form.data, {}) +@@ -323,7 +314,7 @@ class TestWidgets(unittest.TestCase): + """ + screen = MagicMock(spec=Screen, colours=8, unicode_aware=False) + canvas = Canvas(screen, 10, 40, 0, 0) +- form = TestFrame(canvas) ++ form = _TestFrame(canvas) + form.reset() + + # Check initial rendering +@@ -379,7 +370,7 @@ class TestWidgets(unittest.TestCase): + """ + screen = MagicMock(spec=Screen, colours=8, unicode_aware=True) + canvas = Canvas(screen, 10, 40, 0, 0) +- form = TestFrame(canvas) ++ form = _TestFrame(canvas) + form.reset() + + # Check initial rendering +@@ -435,7 +426,7 @@ class TestWidgets(unittest.TestCase): + """ + screen = MagicMock(spec=Screen, colours=8, unicode_aware=False) + canvas = Canvas(screen, 10, 40, 0, 0) +- form = TestFrame(canvas, has_border=False, can_scroll=False) ++ form = _TestFrame(canvas, has_border=False, can_scroll=False) + form.reset() + + # Check initial rendering +@@ -475,7 +466,7 @@ class TestWidgets(unittest.TestCase): + """ + screen = MagicMock(spec=Screen, colours=8, unicode_aware=False) + canvas = Canvas(screen, 10, 40, 0, 0) +- form = TestFrame(canvas, has_border=False, can_scroll=True) ++ form = _TestFrame(canvas, has_border=False, can_scroll=True) + form.reset() + + # Check initial rendering +@@ -499,7 +490,7 @@ class TestWidgets(unittest.TestCase): + """ + screen = MagicMock(spec=Screen, colours=8, unicode_aware=False) + canvas = Canvas(screen, 10, 40, 0, 0) +- form = TestFrame(canvas) ++ form = _TestFrame(canvas) + form.reset() + self.process_keys(form, + ["ABC\nDEF", "GHI", "jkl", "MN", " ", " ", "", " "], +@@ -531,7 +522,7 @@ class TestWidgets(unittest.TestCase): + """ + screen = MagicMock(spec=Screen, colours=8, unicode_aware=False) + canvas = Canvas(screen, 10, 40, 0, 0) +- form = TestFrame(canvas) ++ form = _TestFrame(canvas) + form.reset() + + # Check basic movement keys +@@ -603,7 +594,7 @@ class TestWidgets(unittest.TestCase): + """ + screen = MagicMock(spec=Screen, colours=8, unicode_aware=False) + canvas = Canvas(screen, 10, 40, 0, 0) +- form = TestFrame(canvas) ++ form = _TestFrame(canvas) + form.reset() + + # Check basic movement keys +@@ -646,7 +637,7 @@ class TestWidgets(unittest.TestCase): + """ + screen = MagicMock(spec=Screen, colours=8, unicode_aware=False) + canvas = Canvas(screen, 10, 40, 0, 0) +- form = TestFrame(canvas) ++ form = _TestFrame(canvas) + form.reset() + + # Check that save still works with no validation. +@@ -676,7 +667,7 @@ class TestWidgets(unittest.TestCase): + """ + screen = MagicMock(spec=Screen, colours=8, unicode_aware=False) + canvas = Canvas(screen, 10, 40, 0, 0) +- form = TestFrame(canvas) ++ form = _TestFrame(canvas) + form.reset() + + # Check basic selection keys +@@ -703,7 +694,7 @@ class TestWidgets(unittest.TestCase): + """ + screen = MagicMock(spec=Screen, colours=8, unicode_aware=False) + canvas = Canvas(screen, 10, 40, 0, 0) +- form = TestFrame(canvas) ++ form = _TestFrame(canvas) + form.reset() + + # Check basic selection keys - including limit checking +@@ -744,7 +735,7 @@ class TestWidgets(unittest.TestCase): + screen = MagicMock(spec=Screen, colours=8, unicode_aware=False) + scene = MagicMock(spec=Scene) + canvas = Canvas(screen, 10, 40, 0, 0) +- form = TestFrame(canvas) ++ form = _TestFrame(canvas) + form.register_scene(scene) + form.reset() + +@@ -790,7 +781,7 @@ class TestWidgets(unittest.TestCase): + """ + screen = MagicMock(spec=Screen, colours=8, unicode_aware=False) + canvas = Canvas(screen, 10, 40, 0, 0) +- form = TestFrame(canvas) ++ form = _TestFrame(canvas) + form.reset() + + # If the Frame loses the focus it must not return a focussed widget. +@@ -808,7 +799,7 @@ class TestWidgets(unittest.TestCase): + """ + screen = MagicMock(spec=Screen, colours=8, unicode_aware=False) + canvas = Canvas(screen, 10, 40, 0, 0) +- form = TestFrame(canvas) ++ form = _TestFrame(canvas) + form.reset() + + # A Frame with a valid focus should return the widget in focus. +@@ -824,7 +815,7 @@ class TestWidgets(unittest.TestCase): + """ + screen = MagicMock(spec=Screen, colours=8, unicode_aware=False) + canvas = Canvas(screen, 10, 40, 0, 0) +- form = TestFrame(canvas) ++ form = _TestFrame(canvas) + form.reset() + + # Check default focus at start is first visible widget +@@ -901,7 +892,7 @@ class TestWidgets(unittest.TestCase): + screen = MagicMock(spec=Screen, colours=8, unicode_aware=False) + scene = MagicMock(spec=Scene) + canvas = Canvas(screen, 10, 40, 0, 0) +- form = TestFrame2( ++ form = _TestFrame2( + canvas, [("One", 1), ("Two is now quite a bit longer than before", 2)]) + form.register_scene(scene) + form.reset() +@@ -990,7 +981,7 @@ class TestWidgets(unittest.TestCase): + screen = MagicMock(spec=Screen, colours=8, unicode_aware=False) + scene = MagicMock(spec=Scene) + canvas = Canvas(screen, 10, 40, 0, 0) +- form = TestFrame2(canvas, [("One", 1), ("Two", 2)]) ++ form = _TestFrame2(canvas, [("One", 1), ("Two", 2)]) + form.register_scene(scene) + form.reset() + +@@ -1650,9 +1641,9 @@ class TestWidgets(unittest.TestCase): + [3, 5, 0], + [ + (["1", "2", "3"], 1), +- ([u"你", u"確", u"定"], 2), ++ (["你", "確", "定"], 2), + ], +- titles=[u"你確定嗎?", u"你確定嗎?", u"你確定嗎?"]) ++ titles=["你確定嗎?", "你確定嗎?", "你確定嗎?"]) + text = Text() + text_box = TextBox(3) + form.add_layout(layout) +@@ -1664,23 +1655,23 @@ class TestWidgets(unittest.TestCase): + form.reset() + + # Set some interesting values... +- text.value = u"你確定嗎? 你確定嗎? 你確定嗎?" +- text_box.value = [u"你確定嗎", u"?"] ++ text.value = "你確定嗎? 你確定嗎? 你確定嗎?" ++ text_box.value = ["你確定嗎", "?"] + + # Check that the CJK characters render correctly - no really this is correctly aligned! + form.update(0) + self.assert_canvas_equals( + canvas, +- u"你你 你你確確 你你確確定定嗎嗎?? \n" + +- u"1 2 3 \n" + +- u"你你 確確 定定 \n" + +- u" \n" + +- u"你你確確定定嗎嗎?? 你你確確定定嗎嗎?? 你你確確定定嗎嗎?? \n" + +- u"你你確確定定嗎嗎 \n" + +- u"?? \n" + +- u" \n" + +- u" \n" + +- u" \n") ++ "你你 你你確確 你你確確定定嗎嗎?? \n" + ++ "1 2 3 \n" + ++ "你你 確確 定定 \n" + ++ " \n" + ++ "你你確確定定嗎嗎?? 你你確確定定嗎嗎?? 你你確確定定嗎嗎?? \n" + ++ "你你確確定定嗎嗎 \n" + ++ "?? \n" + ++ " \n" + ++ " \n" + ++ " \n") + + # Check that mouse input takes into account the glyph width + self.process_mouse(form, [(5, 4, MouseEvent.LEFT_CLICK)]) +@@ -1688,14 +1679,14 @@ class TestWidgets(unittest.TestCase): + self.process_mouse(form, [(2, 4, MouseEvent.LEFT_CLICK)]) + self.process_keys(form, ["p"]) + form.save() +- self.assertEqual(text.value, u"你p確b定嗎? 你確定嗎? 你確定嗎?") ++ self.assertEqual(text.value, "你p確b定嗎? 你確定嗎? 你確定嗎?") + + self.process_mouse(form, [(2, 5, MouseEvent.LEFT_CLICK)]) + self.process_keys(form, ["p"]) + self.process_mouse(form, [(1, 6, MouseEvent.LEFT_CLICK)]) + self.process_keys(form, ["b"]) + form.save() +- self.assertEqual(text_box.value, [u"你p確定嗎", u"b?"]) ++ self.assertEqual(text_box.value, ["你p確定嗎", "b?"]) + + def test_shadow(self): + """ +@@ -1751,8 +1742,8 @@ class TestWidgets(unittest.TestCase): + self.assertEqual(scene2.effects[0]._buttons, ["Yes", "No"]) + + # Check that normal Frame data gets copied to the new Scene. +- frame = TestFrame(canvas) +- frame2 = TestFrame(canvas) ++ frame = _TestFrame(canvas) ++ frame2 = _TestFrame(canvas) + scene2 = Scene([frame2], 10) + frame.register_scene(scene) + frame2.register_scene(scene) +@@ -1770,7 +1761,7 @@ class TestWidgets(unittest.TestCase): + """ + screen = MagicMock(spec=Screen, colours=8, unicode_aware=False) + canvas = Canvas(screen, 10, 40, 0, 0) +- form = TestFrame(canvas) ++ form = _TestFrame(canvas) + form.reset() + + # With no special CPU consideration, and a cursor to animate, there +@@ -1792,7 +1783,7 @@ class TestWidgets(unittest.TestCase): + """ + screen = MagicMock(spec=Screen, colours=8, unicode_aware=False) + canvas = Canvas(screen, 10, 40, 0, 0) +- form = TestFrame(canvas, reduce_cpu=True) ++ form = _TestFrame(canvas, reduce_cpu=True) + form.reset() + + # In this mode, it shouldn't matter where we are on the Frame - all +@@ -1810,7 +1801,7 @@ class TestWidgets(unittest.TestCase): + """ + screen = MagicMock(spec=Screen, colours=8, unicode_aware=False) + canvas = Canvas(screen, 10, 40, 0, 0) +- form = TestFrame(canvas, reduce_cpu=True) ++ form = _TestFrame(canvas, reduce_cpu=True) + self.assertEqual(form.stop_frame, -1) + + def test_empty_frame(self): +@@ -1820,7 +1811,7 @@ class TestWidgets(unittest.TestCase): + screen = MagicMock(spec=Screen, colours=8, unicode_aware=False) + canvas = Canvas(screen, 10, 40, 0, 0) + scene = MagicMock(spec=Scene) +- form = TestFrame3(canvas) ++ form = _TestFrame3(canvas) + form.register_scene(scene) + form.reset() + +@@ -1844,7 +1835,7 @@ class TestWidgets(unittest.TestCase): + """ + screen = MagicMock(spec=Screen, colours=8, unicode_aware=False) + canvas = Canvas(screen, 10, 40, 0, 0) +- form = TestFrame(canvas) ++ form = _TestFrame(canvas) + form.reset() + + # Check initial rendering +@@ -1888,7 +1879,7 @@ class TestWidgets(unittest.TestCase): + """ + screen = MagicMock(spec=Screen, colours=8, unicode_aware=False) + canvas = Canvas(screen, 10, 40, 0, 0) +- form = TestFrame(canvas, label_height=2) ++ form = _TestFrame(canvas, label_height=2) + form.reset() + + # Check Label obeys required height +@@ -2004,7 +1995,7 @@ class TestWidgets(unittest.TestCase): + screen = MagicMock(spec=Screen, colours=8, unicode_aware=False) + scene = MagicMock(spec=Scene) + canvas = Canvas(screen, 10, 40, 0, 0) +- form = TestFrame4(canvas) ++ form = _TestFrame4(canvas) + form.register_scene(scene) + form.reset() + +@@ -2038,7 +2029,7 @@ class TestWidgets(unittest.TestCase): + screen = MagicMock(spec=Screen, colours=8, unicode_aware=False) + scene = MagicMock(spec=Scene) + canvas = Canvas(screen, 10, 40, 0, 0) +- form = TestFrame4(canvas) ++ form = _TestFrame4(canvas) + form.register_scene(scene) + form.reset() + +@@ -2088,7 +2079,7 @@ class TestWidgets(unittest.TestCase): + screen = MagicMock(spec=Screen, colours=8, unicode_aware=False) + scene = MagicMock(spec=Scene) + canvas = Canvas(screen, 10, 40, 0, 0) +- form = TestFrame4(canvas) ++ form = _TestFrame4(canvas) + form.register_scene(scene) + form.reset() + +@@ -2181,7 +2172,7 @@ class TestWidgets(unittest.TestCase): + screen = MagicMock(spec=Screen, colours=8, unicode_aware=False) + scene = MagicMock(spec=Scene) + canvas = Canvas(screen, 10, 40, 0, 0) +- form = TestFrame4(canvas, file_filter=r".*\.bmp$") ++ form = _TestFrame4(canvas, file_filter=r".*\.bmp$") + form.register_scene(scene) + form.reset() + +@@ -2219,7 +2210,7 @@ class TestWidgets(unittest.TestCase): + screen = MagicMock(spec=Screen, colours=8, unicode_aware=False) + scene = Scene([], duration=-1) + canvas = Canvas(screen, 10, 40, 0, 0) +- form = TestFrame5(canvas) ++ form = _TestFrame5(canvas) + scene.add_effect(form) + scene.reset() + +@@ -2336,7 +2327,7 @@ class TestWidgets(unittest.TestCase): + screen = MagicMock(spec=Screen, colours=8, unicode_aware=False) + scene = Scene([], duration=-1) + canvas = Canvas(screen, 10, 40, 0, 0) +- form = TestFrame5(canvas) ++ form = _TestFrame5(canvas) + scene.add_effect(form) + scene.reset() + +@@ -2566,7 +2557,7 @@ class TestWidgets(unittest.TestCase): + layout = Layout([100], fill_frame=True) + form.add_layout(layout) + layout.add_widget(Divider(draw_line=False, height=7)) +- dd_list = DropdownList([("Item {}".format(i), i) for i in range(10)]) ++ dd_list = DropdownList([(f"Item {i}", i) for i in range(10)]) + layout.add_widget(dd_list) + form.fix() + form.register_scene(scene) +@@ -2620,7 +2611,7 @@ class TestWidgets(unittest.TestCase): + layout = Layout([100], fill_frame=True) + form.add_layout(layout) + layout.add_widget(Divider(draw_line=False, height=7)) +- dd_list = DropdownList([("Item {}".format(i), i) for i in range(10)], fit=True) ++ dd_list = DropdownList([(f"Item {i}", i) for i in range(10)], fit=True) + layout.add_widget(dd_list) + form.fix() + form.register_scene(scene) +@@ -2692,7 +2683,7 @@ class TestWidgets(unittest.TestCase): + screen = MagicMock(spec=Screen, colours=8, unicode_aware=False) + scene = Scene([], duration=-1) + canvas = Canvas(screen, 10, 40, 0, 0) +- form = TestFrame5(canvas) ++ form = _TestFrame5(canvas) + scene.add_effect(form) + scene.reset() + +@@ -3405,7 +3396,7 @@ class TestWidgets(unittest.TestCase): + screen = MagicMock(spec=Screen, colours=8, unicode_aware=False) + scene = Scene([], duration=-1) + canvas = Canvas(screen, 10, 40, 0, 0) +- form = TestFrame6(canvas) ++ form = _TestFrame6(canvas) + scene.add_effect(form) + scene.reset() + +Index: asciimatics-1.14.0/tests/test_particles.py +=================================================================== +--- asciimatics-1.14.0.orig/tests/test_particles.py ++++ asciimatics-1.14.0/tests/test_particles.py +@@ -1,5 +1,5 @@ + import unittest +-from mock.mock import MagicMock ++from unittest.mock import MagicMock + from asciimatics.particles import ShootScreen, DropScreen, Explosion, Rain, \ + StarFirework, PalmFirework, RingFirework, SerpentFirework + from asciimatics.screen import Screen, Canvas +Index: asciimatics-1.14.0/setup.py +=================================================================== +--- asciimatics-1.14.0.orig/setup.py ++++ asciimatics-1.14.0/setup.py +@@ -66,16 +66,9 @@ setup( + 'pyfiglet >= 0.7.2', + 'Pillow >= 2.7.0', + 'wcwidth', +- 'future', +- 'backports.functools_lru_cache;python_version<"3.0"', ++ 'curses' + ], + extras_require={ + ':sys_platform == "win32"': ['pywin32'], + }, +- setup_requires=['setuptools_scm'], +- tests_require=[ +- 'mock', +- 'nose', +- ], +- test_suite='nose.collector', + ) diff --git a/python-asciimatics-no-mock.patch b/python-asciimatics-no-mock.patch deleted file mode 100644 index 70fd3c8..0000000 --- a/python-asciimatics-no-mock.patch +++ /dev/null @@ -1,56 +0,0 @@ -Index: asciimatics-1.13.0/tests/test_effects.py -=================================================================== ---- asciimatics-1.13.0.orig/tests/test_effects.py 2020-09-18 16:37:11.000000000 +0200 -+++ asciimatics-1.13.0/tests/test_effects.py 2022-03-07 13:53:31.271205331 +0100 -@@ -1,7 +1,7 @@ - from builtins import chr - import unittest - from datetime import datetime --from mock.mock import MagicMock, patch -+from unittest.mock import MagicMock, patch - from random import randint - import os - import sys -Index: asciimatics-1.13.0/tests/test_particles.py -=================================================================== ---- asciimatics-1.13.0.orig/tests/test_particles.py 2020-09-18 16:37:11.000000000 +0200 -+++ asciimatics-1.13.0/tests/test_particles.py 2022-03-07 13:54:14.599457606 +0100 -@@ -1,5 +1,5 @@ - import unittest --from mock.mock import MagicMock -+from unittest.mock import MagicMock - from asciimatics.particles import ShootScreen, DropScreen, Explosion, Rain, \ - StarFirework, PalmFirework, RingFirework, SerpentFirework - from asciimatics.screen import Screen, Canvas -Index: asciimatics-1.13.0/tests/test_screen.py -=================================================================== ---- asciimatics-1.13.0.orig/tests/test_screen.py 2021-03-06 18:11:13.000000000 +0100 -+++ asciimatics-1.13.0/tests/test_screen.py 2022-03-07 13:54:48.895656238 +0100 -@@ -5,7 +5,7 @@ from __future__ import print_function - from __future__ import unicode_literals - - import os --from mock import MagicMock -+from unittest.mock import MagicMock - from random import randint - import unittest - import sys -Index: asciimatics-1.13.0/tests/test_widgets.py -=================================================================== ---- asciimatics-1.13.0.orig/tests/test_widgets.py 2021-04-05 16:20:35.000000000 +0200 -+++ asciimatics-1.13.0/tests/test_widgets.py 2022-03-07 13:58:16.396856253 +0100 -@@ -5,13 +5,12 @@ from __future__ import print_function - from __future__ import unicode_literals - from datetime import date, time - from time import sleep --from mock import patch -+from unittest.mock import MagicMock,patch - from builtins import ord - from builtins import chr - from builtins import str - import unittest - import sys --from mock.mock import MagicMock - from asciimatics.event import KeyboardEvent, MouseEvent - from asciimatics.exceptions import NextScene, StopApplication, InvalidFields - from asciimatics.scene import Scene diff --git a/python-asciimatics.changes b/python-asciimatics.changes index 1a2ae2f..5ca71a6 100644 --- a/python-asciimatics.changes +++ b/python-asciimatics.changes @@ -1,3 +1,10 @@ +------------------------------------------------------------------- +Mon Sep 11 04:59:40 UTC 2023 - Steve Kowalik + +- Drop patch python-asciimatics-no-mock.patch, has been subsummed. +- Add patch move-to-python3.patch +- Switch to autosetup and pyproject macros. + ------------------------------------------------------------------- Mon Aug 29 16:38:23 UTC 2022 - Yogalakshmi Arunachalam diff --git a/python-asciimatics.spec b/python-asciimatics.spec index 7c19cf3..dcc22cc 100644 --- a/python-asciimatics.spec +++ b/python-asciimatics.spec @@ -1,7 +1,7 @@ # # spec file for package python-asciimatics # -# Copyright (c) 2022 SUSE LLC +# Copyright (c) 2023 SUSE LLC # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -16,30 +16,28 @@ # -%{?!python_module:%define python_module() python-%{**} python3-%{**}} Name: python-asciimatics Version: 1.14.0 Release: 0 Summary: Package to replace curses and create ASCII animations License: Apache-2.0 -Group: Development/Languages/Python URL: https://github.com/peterbrittain/asciimatics Source: https://files.pythonhosted.org/packages/source/a/asciimatics/asciimatics-%{version}.tar.gz -# https://github.com/peterbrittain/asciimatics/issues/347 -Patch0: python-asciimatics-no-mock.patch -BuildRequires: %{python_module setuptools} +# PATCH-FIX-UPSTREAM Based on gh#peterbrittain/asciimatics#376 +Patch0: move-to-python3.patch +BuildRequires: %{python_module pip} +BuildRequires: %{python_module setuptools_scm} +BuildRequires: %{python_module wheel} BuildRequires: fdupes BuildRequires: python-rpm-macros Requires: python-Pillow >= 2.7.0 Requires: python-curses -Requires: python-future Requires: python-pyfiglet >= 0.7.2 Requires: python-wcwidth BuildArch: noarch # SECTION test requirements BuildRequires: %{python_module Pillow >= 2.7.0} BuildRequires: %{python_module curses} -BuildRequires: %{python_module future} BuildRequires: %{python_module pyfiglet >= 0.7.2} BuildRequires: %{python_module pytest} BuildRequires: %{python_module wcwidth} @@ -51,15 +49,13 @@ Asciimatics is a package to help people create full-screen text UIs (from interactive forms to ASCII animations) on any platform. %prep -%setup -q -n asciimatics-%{version} -%autopatch -p1 -sed -i '/setup_requires/d' setup.py +%autosetup -p1 -n asciimatics-%{version} %build -%python_build +%pyproject_wheel %install -%python_install +%pyproject_install %python_expand %fdupes %{buildroot}%{$python_sitelib} %check @@ -69,6 +65,7 @@ sed -i '/setup_requires/d' setup.py %files %{python_files} %doc CHANGES.rst README.rst doc/source/*.rst doc/source/*.png %license LICENSE -%{python_sitelib}/* +%{python_sitelib}/asciimatics +%{python_sitelib}/asciimatics-%{version}.dist-info %changelog