added completly new version for haslach 2025
This commit is contained in:
40
.venv/lib/python3.7/site-packages/pygame/tests/__init__.py
Normal file
40
.venv/lib/python3.7/site-packages/pygame/tests/__init__.py
Normal file
@@ -0,0 +1,40 @@
|
||||
"""Pygame unit test suite package
|
||||
|
||||
Exports function run()
|
||||
|
||||
A quick way to run the test suite package from the command line
|
||||
is by importing the go submodule:
|
||||
|
||||
python -m "import pygame.tests" [<test options>]
|
||||
|
||||
Command line option --help displays a usage message. Available options
|
||||
correspond to the pygame.tests.run arguments.
|
||||
|
||||
The xxxx_test submodules of the tests package are unit test suites for
|
||||
individual parts of Pygame. Each can also be run as a main program. This is
|
||||
useful if the test, such as cdrom_test, is interactive.
|
||||
|
||||
For Pygame development the test suite can be run from a Pygame distribution
|
||||
root directory using run_tests.py. Alternately, test/__main__.py can be run
|
||||
directly.
|
||||
|
||||
"""
|
||||
|
||||
if __name__ == "pygame.tests":
|
||||
from pygame.tests.test_utils.run_tests import run
|
||||
elif __name__ == "__main__":
|
||||
import os
|
||||
import sys
|
||||
|
||||
pkg_dir = os.path.split(os.path.abspath(__file__))[0]
|
||||
parent_dir, pkg_name = os.path.split(pkg_dir)
|
||||
is_pygame_pkg = pkg_name == "tests" and os.path.split(parent_dir)[1] == "pygame"
|
||||
if not is_pygame_pkg:
|
||||
sys.path.insert(0, parent_dir)
|
||||
|
||||
if is_pygame_pkg:
|
||||
import pygame.tests.__main__
|
||||
else:
|
||||
import test.__main__
|
||||
else:
|
||||
from test.test_utils.run_tests import run
|
143
.venv/lib/python3.7/site-packages/pygame/tests/__main__.py
Normal file
143
.venv/lib/python3.7/site-packages/pygame/tests/__main__.py
Normal file
@@ -0,0 +1,143 @@
|
||||
"""Load and run the Pygame test suite
|
||||
|
||||
python -c "import pygame.tests.go" [<test options>]
|
||||
|
||||
or
|
||||
|
||||
python test/go.py [<test options>]
|
||||
|
||||
Command line option --help displays a command line usage message.
|
||||
|
||||
run_tests.py in the main distribution directory is an alternative to test.go
|
||||
|
||||
"""
|
||||
|
||||
import sys
|
||||
|
||||
if __name__ == "__main__":
|
||||
import os
|
||||
|
||||
pkg_dir = os.path.split(os.path.abspath(__file__))[0]
|
||||
parent_dir, pkg_name = os.path.split(pkg_dir)
|
||||
is_pygame_pkg = pkg_name == "tests" and os.path.split(parent_dir)[1] == "pygame"
|
||||
if not is_pygame_pkg:
|
||||
sys.path.insert(0, parent_dir)
|
||||
else:
|
||||
is_pygame_pkg = __name__.startswith("pygame.tests.")
|
||||
|
||||
if is_pygame_pkg:
|
||||
from pygame.tests.test_utils.run_tests import run_and_exit
|
||||
from pygame.tests.test_utils.test_runner import opt_parser
|
||||
else:
|
||||
from test.test_utils.run_tests import run_and_exit
|
||||
from test.test_utils.test_runner import opt_parser
|
||||
|
||||
if is_pygame_pkg:
|
||||
test_pkg_name = "pygame.tests"
|
||||
else:
|
||||
test_pkg_name = "test"
|
||||
program_name = sys.argv[0]
|
||||
if program_name == "-c":
|
||||
program_name = f'python -c "import {test_pkg_name}.go"'
|
||||
|
||||
###########################################################################
|
||||
# Set additional command line options
|
||||
#
|
||||
# Defined in test_runner.py as it shares options, added to here
|
||||
|
||||
opt_parser.set_usage(
|
||||
f"""
|
||||
|
||||
Runs all or some of the {test_pkg_name}.xxxx_test tests.
|
||||
|
||||
$ {program_name} sprite threads -sd
|
||||
|
||||
Runs the sprite and threads module tests isolated in subprocesses, dumping
|
||||
all failing tests info in the form of a dict.
|
||||
|
||||
"""
|
||||
)
|
||||
|
||||
opt_parser.add_option(
|
||||
"-d", "--dump", action="store_true", help="dump results as dict ready to eval"
|
||||
)
|
||||
|
||||
opt_parser.add_option("-F", "--file", help="dump results to a file")
|
||||
|
||||
opt_parser.add_option(
|
||||
"-m",
|
||||
"--multi_thread",
|
||||
metavar="THREADS",
|
||||
type="int",
|
||||
help="run subprocessed tests in x THREADS",
|
||||
)
|
||||
|
||||
opt_parser.add_option(
|
||||
"-t",
|
||||
"--time_out",
|
||||
metavar="SECONDS",
|
||||
type="int",
|
||||
help="kill stalled subprocessed tests after SECONDS",
|
||||
)
|
||||
|
||||
opt_parser.add_option(
|
||||
"-f", "--fake", metavar="DIR", help="run fake tests in run_tests__tests/$DIR"
|
||||
)
|
||||
|
||||
opt_parser.add_option(
|
||||
"-p",
|
||||
"--python",
|
||||
metavar="PYTHON",
|
||||
help="path to python executable to run subproccesed tests\n"
|
||||
"default (sys.executable): %s" % sys.executable,
|
||||
)
|
||||
|
||||
opt_parser.add_option(
|
||||
"-I",
|
||||
"--interactive",
|
||||
action="store_true",
|
||||
help="include tests requiring user input",
|
||||
)
|
||||
|
||||
opt_parser.add_option("-S", "--seed", type="int", help="Randomisation seed")
|
||||
|
||||
###########################################################################
|
||||
# Set run() keyword arguments according to command line arguments.
|
||||
# args will be the test module list, passed as positional argumemts.
|
||||
|
||||
options, args = opt_parser.parse_args()
|
||||
kwds = {}
|
||||
if options.incomplete:
|
||||
kwds["incomplete"] = True
|
||||
if options.usesubprocess:
|
||||
kwds["usesubprocess"] = True
|
||||
else:
|
||||
kwds["usesubprocess"] = False
|
||||
if options.dump:
|
||||
kwds["dump"] = True
|
||||
if options.file:
|
||||
kwds["file"] = options.file
|
||||
if options.exclude:
|
||||
kwds["exclude"] = options.exclude
|
||||
if options.unbuffered:
|
||||
kwds["unbuffered"] = True
|
||||
if options.randomize:
|
||||
kwds["randomize"] = True
|
||||
if options.seed is not None:
|
||||
kwds["seed"] = options.seed
|
||||
if options.multi_thread is not None:
|
||||
kwds["multi_thread"] = options.multi_thread
|
||||
if options.time_out is not None:
|
||||
kwds["time_out"] = options.time_out
|
||||
if options.fake:
|
||||
kwds["fake"] = options.fake
|
||||
if options.python:
|
||||
kwds["python"] = options.python
|
||||
if options.interactive:
|
||||
kwds["interactive"] = True
|
||||
kwds["verbosity"] = options.verbosity if options.verbosity is not None else 1
|
||||
|
||||
|
||||
###########################################################################
|
||||
# Run the test suite.
|
||||
run_and_exit(*args, **kwds)
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
623
.venv/lib/python3.7/site-packages/pygame/tests/base_test.py
Normal file
623
.venv/lib/python3.7/site-packages/pygame/tests/base_test.py
Normal file
@@ -0,0 +1,623 @@
|
||||
import sys
|
||||
import unittest
|
||||
|
||||
import platform
|
||||
|
||||
IS_PYPY = "PyPy" == platform.python_implementation()
|
||||
|
||||
try:
|
||||
from pygame.tests.test_utils import arrinter
|
||||
except NameError:
|
||||
pass
|
||||
import pygame
|
||||
|
||||
|
||||
quit_count = 0
|
||||
|
||||
|
||||
def quit_hook():
|
||||
global quit_count
|
||||
quit_count += 1
|
||||
|
||||
|
||||
class BaseModuleTest(unittest.TestCase):
|
||||
def tearDown(self):
|
||||
# Clean up after each test method.
|
||||
pygame.quit()
|
||||
|
||||
def test_get_sdl_byteorder(self):
|
||||
"""Ensure the SDL byte order is valid"""
|
||||
byte_order = pygame.get_sdl_byteorder()
|
||||
expected_options = (pygame.LIL_ENDIAN, pygame.BIG_ENDIAN)
|
||||
|
||||
self.assertIn(byte_order, expected_options)
|
||||
|
||||
def test_get_sdl_version(self):
|
||||
"""Ensure the SDL version is valid"""
|
||||
self.assertEqual(len(pygame.get_sdl_version()), 3)
|
||||
|
||||
class ExporterBase:
|
||||
def __init__(self, shape, typechar, itemsize):
|
||||
import ctypes
|
||||
|
||||
ndim = len(shape)
|
||||
self.ndim = ndim
|
||||
self.shape = tuple(shape)
|
||||
array_len = 1
|
||||
for d in shape:
|
||||
array_len *= d
|
||||
self.size = itemsize * array_len
|
||||
self.parent = ctypes.create_string_buffer(self.size)
|
||||
self.itemsize = itemsize
|
||||
strides = [itemsize] * ndim
|
||||
for i in range(ndim - 1, 0, -1):
|
||||
strides[i - 1] = strides[i] * shape[i]
|
||||
self.strides = tuple(strides)
|
||||
self.data = ctypes.addressof(self.parent), False
|
||||
if self.itemsize == 1:
|
||||
byteorder = "|"
|
||||
elif sys.byteorder == "big":
|
||||
byteorder = ">"
|
||||
else:
|
||||
byteorder = "<"
|
||||
self.typestr = byteorder + typechar + str(self.itemsize)
|
||||
|
||||
def assertSame(self, proxy, obj):
|
||||
self.assertEqual(proxy.length, obj.size)
|
||||
iface = proxy.__array_interface__
|
||||
self.assertEqual(iface["typestr"], obj.typestr)
|
||||
self.assertEqual(iface["shape"], obj.shape)
|
||||
self.assertEqual(iface["strides"], obj.strides)
|
||||
self.assertEqual(iface["data"], obj.data)
|
||||
|
||||
def test_PgObject_GetBuffer_array_interface(self):
|
||||
from pygame.bufferproxy import BufferProxy
|
||||
|
||||
class Exporter(self.ExporterBase):
|
||||
def get__array_interface__(self):
|
||||
return {
|
||||
"version": 3,
|
||||
"typestr": self.typestr,
|
||||
"shape": self.shape,
|
||||
"strides": self.strides,
|
||||
"data": self.data,
|
||||
}
|
||||
|
||||
__array_interface__ = property(get__array_interface__)
|
||||
# Should be ignored by PgObject_GetBuffer
|
||||
__array_struct__ = property(lambda self: None)
|
||||
|
||||
_shape = [2, 3, 5, 7, 11] # Some prime numbers
|
||||
for ndim in range(1, len(_shape)):
|
||||
o = Exporter(_shape[0:ndim], "i", 2)
|
||||
v = BufferProxy(o)
|
||||
self.assertSame(v, o)
|
||||
ndim = 2
|
||||
shape = _shape[0:ndim]
|
||||
for typechar in ("i", "u"):
|
||||
for itemsize in (1, 2, 4, 8):
|
||||
o = Exporter(shape, typechar, itemsize)
|
||||
v = BufferProxy(o)
|
||||
self.assertSame(v, o)
|
||||
for itemsize in (4, 8):
|
||||
o = Exporter(shape, "f", itemsize)
|
||||
v = BufferProxy(o)
|
||||
self.assertSame(v, o)
|
||||
|
||||
# Is the dict received from an exporting object properly released?
|
||||
# The dict should be freed before PgObject_GetBuffer returns.
|
||||
# When the BufferProxy v's length property is referenced, v calls
|
||||
# PgObject_GetBuffer, which in turn references Exporter2 o's
|
||||
# __array_interface__ property. The Exporter2 instance o returns a
|
||||
# dict subclass for which it keeps both a regular reference and a
|
||||
# weak reference. The regular reference should be the only
|
||||
# remaining reference when PgObject_GetBuffer returns. This is
|
||||
# verified by first checking the weak reference both before and
|
||||
# after the regular reference held by o is removed.
|
||||
|
||||
import weakref, gc
|
||||
|
||||
class NoDictError(RuntimeError):
|
||||
pass
|
||||
|
||||
class WRDict(dict):
|
||||
"""Weak referenceable dict"""
|
||||
|
||||
pass
|
||||
|
||||
class Exporter2(Exporter):
|
||||
def get__array_interface__2(self):
|
||||
self.d = WRDict(Exporter.get__array_interface__(self))
|
||||
self.dict_ref = weakref.ref(self.d)
|
||||
return self.d
|
||||
|
||||
__array_interface__ = property(get__array_interface__2)
|
||||
|
||||
def free_dict(self):
|
||||
self.d = None
|
||||
|
||||
def is_dict_alive(self):
|
||||
try:
|
||||
return self.dict_ref() is not None
|
||||
except AttributeError:
|
||||
raise NoDictError("__array_interface__ is unread")
|
||||
|
||||
o = Exporter2((2, 4), "u", 4)
|
||||
v = BufferProxy(o)
|
||||
self.assertRaises(NoDictError, o.is_dict_alive)
|
||||
length = v.length
|
||||
self.assertTrue(o.is_dict_alive())
|
||||
o.free_dict()
|
||||
gc.collect()
|
||||
self.assertFalse(o.is_dict_alive())
|
||||
|
||||
def test_GetView_array_struct(self):
|
||||
from pygame.bufferproxy import BufferProxy
|
||||
|
||||
class Exporter(self.ExporterBase):
|
||||
def __init__(self, shape, typechar, itemsize):
|
||||
super().__init__(shape, typechar, itemsize)
|
||||
self.view = BufferProxy(self.__dict__)
|
||||
|
||||
def get__array_struct__(self):
|
||||
return self.view.__array_struct__
|
||||
|
||||
__array_struct__ = property(get__array_struct__)
|
||||
# Should not cause PgObject_GetBuffer to fail
|
||||
__array_interface__ = property(lambda self: None)
|
||||
|
||||
_shape = [2, 3, 5, 7, 11] # Some prime numbers
|
||||
for ndim in range(1, len(_shape)):
|
||||
o = Exporter(_shape[0:ndim], "i", 2)
|
||||
v = BufferProxy(o)
|
||||
self.assertSame(v, o)
|
||||
ndim = 2
|
||||
shape = _shape[0:ndim]
|
||||
for typechar in ("i", "u"):
|
||||
for itemsize in (1, 2, 4, 8):
|
||||
o = Exporter(shape, typechar, itemsize)
|
||||
v = BufferProxy(o)
|
||||
self.assertSame(v, o)
|
||||
for itemsize in (4, 8):
|
||||
o = Exporter(shape, "f", itemsize)
|
||||
v = BufferProxy(o)
|
||||
self.assertSame(v, o)
|
||||
|
||||
# Check returned cobject/capsule reference count
|
||||
try:
|
||||
from sys import getrefcount
|
||||
except ImportError:
|
||||
# PyPy: no reference counting
|
||||
pass
|
||||
else:
|
||||
o = Exporter(shape, typechar, itemsize)
|
||||
self.assertEqual(getrefcount(o.__array_struct__), 1)
|
||||
|
||||
if pygame.HAVE_NEWBUF:
|
||||
from pygame.tests.test_utils import buftools
|
||||
|
||||
def NEWBUF_assertSame(self, proxy, exp):
|
||||
buftools = self.buftools
|
||||
Importer = buftools.Importer
|
||||
self.assertEqual(proxy.length, exp.len)
|
||||
imp = Importer(proxy, buftools.PyBUF_RECORDS_RO)
|
||||
self.assertEqual(imp.readonly, exp.readonly)
|
||||
self.assertEqual(imp.format, exp.format)
|
||||
self.assertEqual(imp.itemsize, exp.itemsize)
|
||||
self.assertEqual(imp.ndim, exp.ndim)
|
||||
self.assertEqual(imp.shape, exp.shape)
|
||||
self.assertEqual(imp.strides, exp.strides)
|
||||
self.assertTrue(imp.suboffsets is None)
|
||||
|
||||
@unittest.skipIf(not pygame.HAVE_NEWBUF, "newbuf not implemented")
|
||||
@unittest.skipIf(IS_PYPY, "pypy no likey")
|
||||
def test_newbuf(self):
|
||||
from pygame.bufferproxy import BufferProxy
|
||||
|
||||
Exporter = self.buftools.Exporter
|
||||
_shape = [2, 3, 5, 7, 11] # Some prime numbers
|
||||
for ndim in range(1, len(_shape)):
|
||||
o = Exporter(_shape[0:ndim], "=h")
|
||||
v = BufferProxy(o)
|
||||
self.NEWBUF_assertSame(v, o)
|
||||
ndim = 2
|
||||
shape = _shape[0:ndim]
|
||||
for format in [
|
||||
"b",
|
||||
"B",
|
||||
"=h",
|
||||
"=H",
|
||||
"=i",
|
||||
"=I",
|
||||
"=q",
|
||||
"=Q",
|
||||
"f",
|
||||
"d",
|
||||
"1h",
|
||||
"=1h",
|
||||
"x",
|
||||
"1x",
|
||||
"2x",
|
||||
"3x",
|
||||
"4x",
|
||||
"5x",
|
||||
"6x",
|
||||
"7x",
|
||||
"8x",
|
||||
"9x",
|
||||
]:
|
||||
o = Exporter(shape, format)
|
||||
v = BufferProxy(o)
|
||||
self.NEWBUF_assertSame(v, o)
|
||||
|
||||
@unittest.skipIf(not pygame.HAVE_NEWBUF, "newbuf not implemented")
|
||||
def test_bad_format(self):
|
||||
from pygame.bufferproxy import BufferProxy
|
||||
from pygame.newbuffer import BufferMixin
|
||||
from ctypes import create_string_buffer, addressof
|
||||
|
||||
buftools = self.buftools
|
||||
Exporter = buftools.Exporter
|
||||
Importer = buftools.Importer
|
||||
PyBUF_FORMAT = buftools.PyBUF_FORMAT
|
||||
|
||||
for format in [
|
||||
"",
|
||||
"=",
|
||||
"1",
|
||||
" ",
|
||||
"2h",
|
||||
"=2h",
|
||||
"0x",
|
||||
"11x",
|
||||
"=!",
|
||||
"h ",
|
||||
" h",
|
||||
"hh",
|
||||
"?",
|
||||
]:
|
||||
exp = Exporter((1,), format, itemsize=2)
|
||||
b = BufferProxy(exp)
|
||||
self.assertRaises(ValueError, Importer, b, PyBUF_FORMAT)
|
||||
|
||||
@unittest.skipIf(not pygame.HAVE_NEWBUF, "newbuf not implemented")
|
||||
@unittest.skipIf(IS_PYPY, "fails on pypy")
|
||||
def test_PgDict_AsBuffer_PyBUF_flags(self):
|
||||
from pygame.bufferproxy import BufferProxy
|
||||
|
||||
is_lil_endian = pygame.get_sdl_byteorder() == pygame.LIL_ENDIAN
|
||||
fsys, frev = ("<", ">") if is_lil_endian else (">", "<")
|
||||
buftools = self.buftools
|
||||
Importer = buftools.Importer
|
||||
a = BufferProxy(
|
||||
{"typestr": "|u4", "shape": (10, 2), "data": (9, False)}
|
||||
) # 9? No data accesses.
|
||||
b = Importer(a, buftools.PyBUF_SIMPLE)
|
||||
self.assertEqual(b.ndim, 0)
|
||||
self.assertTrue(b.format is None)
|
||||
self.assertEqual(b.len, a.length)
|
||||
self.assertEqual(b.itemsize, 4)
|
||||
self.assertTrue(b.shape is None)
|
||||
self.assertTrue(b.strides is None)
|
||||
self.assertTrue(b.suboffsets is None)
|
||||
self.assertFalse(b.readonly)
|
||||
self.assertEqual(b.buf, 9)
|
||||
b = Importer(a, buftools.PyBUF_WRITABLE)
|
||||
self.assertEqual(b.ndim, 0)
|
||||
self.assertTrue(b.format is None)
|
||||
self.assertEqual(b.len, a.length)
|
||||
self.assertEqual(b.itemsize, 4)
|
||||
self.assertTrue(b.shape is None)
|
||||
self.assertTrue(b.strides is None)
|
||||
self.assertTrue(b.suboffsets is None)
|
||||
self.assertFalse(b.readonly)
|
||||
self.assertEqual(b.buf, 9)
|
||||
b = Importer(a, buftools.PyBUF_ND)
|
||||
self.assertEqual(b.ndim, 2)
|
||||
self.assertTrue(b.format is None)
|
||||
self.assertEqual(b.len, a.length)
|
||||
self.assertEqual(b.itemsize, 4)
|
||||
self.assertEqual(b.shape, (10, 2))
|
||||
self.assertTrue(b.strides is None)
|
||||
self.assertTrue(b.suboffsets is None)
|
||||
self.assertFalse(b.readonly)
|
||||
self.assertEqual(b.buf, 9)
|
||||
a = BufferProxy(
|
||||
{
|
||||
"typestr": fsys + "i2",
|
||||
"shape": (5, 10),
|
||||
"strides": (24, 2),
|
||||
"data": (42, False),
|
||||
}
|
||||
) # 42? No data accesses.
|
||||
b = Importer(a, buftools.PyBUF_STRIDES)
|
||||
self.assertEqual(b.ndim, 2)
|
||||
self.assertTrue(b.format is None)
|
||||
self.assertEqual(b.len, 100)
|
||||
self.assertEqual(b.itemsize, 2)
|
||||
self.assertEqual(b.shape, (5, 10))
|
||||
self.assertEqual(b.strides, (24, 2))
|
||||
self.assertTrue(b.suboffsets is None)
|
||||
self.assertFalse(b.readonly)
|
||||
self.assertEqual(b.buf, 42)
|
||||
b = Importer(a, buftools.PyBUF_FULL_RO)
|
||||
self.assertEqual(b.ndim, 2)
|
||||
self.assertEqual(b.format, "=h")
|
||||
self.assertEqual(b.len, 100)
|
||||
self.assertEqual(b.itemsize, 2)
|
||||
self.assertEqual(b.shape, (5, 10))
|
||||
self.assertEqual(b.strides, (24, 2))
|
||||
self.assertTrue(b.suboffsets is None)
|
||||
self.assertFalse(b.readonly)
|
||||
self.assertEqual(b.buf, 42)
|
||||
self.assertRaises(BufferError, Importer, a, buftools.PyBUF_SIMPLE)
|
||||
self.assertRaises(BufferError, Importer, a, buftools.PyBUF_ND)
|
||||
self.assertRaises(BufferError, Importer, a, buftools.PyBUF_C_CONTIGUOUS)
|
||||
self.assertRaises(BufferError, Importer, a, buftools.PyBUF_F_CONTIGUOUS)
|
||||
self.assertRaises(BufferError, Importer, a, buftools.PyBUF_ANY_CONTIGUOUS)
|
||||
self.assertRaises(BufferError, Importer, a, buftools.PyBUF_CONTIG)
|
||||
self.assertRaises(BufferError, Importer, a, buftools.PyBUF_SIMPLE)
|
||||
self.assertRaises(BufferError, Importer, a, buftools.PyBUF_ND)
|
||||
self.assertRaises(BufferError, Importer, a, buftools.PyBUF_C_CONTIGUOUS)
|
||||
self.assertRaises(BufferError, Importer, a, buftools.PyBUF_F_CONTIGUOUS)
|
||||
self.assertRaises(BufferError, Importer, a, buftools.PyBUF_ANY_CONTIGUOUS)
|
||||
self.assertRaises(BufferError, Importer, a, buftools.PyBUF_CONTIG)
|
||||
a = BufferProxy(
|
||||
{
|
||||
"typestr": frev + "i2",
|
||||
"shape": (3, 5, 10),
|
||||
"strides": (120, 24, 2),
|
||||
"data": (1000000, True),
|
||||
}
|
||||
) # 1000000? No data accesses.
|
||||
b = Importer(a, buftools.PyBUF_FULL_RO)
|
||||
self.assertEqual(b.ndim, 3)
|
||||
self.assertEqual(b.format, frev + "h")
|
||||
self.assertEqual(b.len, 300)
|
||||
self.assertEqual(b.itemsize, 2)
|
||||
self.assertEqual(b.shape, (3, 5, 10))
|
||||
self.assertEqual(b.strides, (120, 24, 2))
|
||||
self.assertTrue(b.suboffsets is None)
|
||||
self.assertTrue(b.readonly)
|
||||
self.assertEqual(b.buf, 1000000)
|
||||
self.assertRaises(BufferError, Importer, a, buftools.PyBUF_FULL)
|
||||
|
||||
@unittest.skipIf(IS_PYPY or (not pygame.HAVE_NEWBUF), "newbuf with ctypes")
|
||||
def test_PgObject_AsBuffer_PyBUF_flags(self):
|
||||
from pygame.bufferproxy import BufferProxy
|
||||
import ctypes
|
||||
|
||||
is_lil_endian = pygame.get_sdl_byteorder() == pygame.LIL_ENDIAN
|
||||
fsys, frev = ("<", ">") if is_lil_endian else (">", "<")
|
||||
buftools = self.buftools
|
||||
Importer = buftools.Importer
|
||||
e = arrinter.Exporter(
|
||||
(10, 2), typekind="f", itemsize=ctypes.sizeof(ctypes.c_double)
|
||||
)
|
||||
a = BufferProxy(e)
|
||||
b = Importer(a, buftools.PyBUF_SIMPLE)
|
||||
self.assertEqual(b.ndim, 0)
|
||||
self.assertTrue(b.format is None)
|
||||
self.assertEqual(b.len, e.len)
|
||||
self.assertEqual(b.itemsize, e.itemsize)
|
||||
self.assertTrue(b.shape is None)
|
||||
self.assertTrue(b.strides is None)
|
||||
self.assertTrue(b.suboffsets is None)
|
||||
self.assertFalse(b.readonly)
|
||||
self.assertEqual(b.buf, e.data)
|
||||
b = Importer(a, buftools.PyBUF_WRITABLE)
|
||||
self.assertEqual(b.ndim, 0)
|
||||
self.assertTrue(b.format is None)
|
||||
self.assertEqual(b.len, e.len)
|
||||
self.assertEqual(b.itemsize, e.itemsize)
|
||||
self.assertTrue(b.shape is None)
|
||||
self.assertTrue(b.strides is None)
|
||||
self.assertTrue(b.suboffsets is None)
|
||||
self.assertFalse(b.readonly)
|
||||
self.assertEqual(b.buf, e.data)
|
||||
b = Importer(a, buftools.PyBUF_ND)
|
||||
self.assertEqual(b.ndim, e.nd)
|
||||
self.assertTrue(b.format is None)
|
||||
self.assertEqual(b.len, a.length)
|
||||
self.assertEqual(b.itemsize, e.itemsize)
|
||||
self.assertEqual(b.shape, e.shape)
|
||||
self.assertTrue(b.strides is None)
|
||||
self.assertTrue(b.suboffsets is None)
|
||||
self.assertFalse(b.readonly)
|
||||
self.assertEqual(b.buf, e.data)
|
||||
e = arrinter.Exporter((5, 10), typekind="i", itemsize=2, strides=(24, 2))
|
||||
a = BufferProxy(e)
|
||||
b = Importer(a, buftools.PyBUF_STRIDES)
|
||||
self.assertEqual(b.ndim, e.nd)
|
||||
self.assertTrue(b.format is None)
|
||||
self.assertEqual(b.len, e.len)
|
||||
self.assertEqual(b.itemsize, e.itemsize)
|
||||
self.assertEqual(b.shape, e.shape)
|
||||
self.assertEqual(b.strides, e.strides)
|
||||
self.assertTrue(b.suboffsets is None)
|
||||
self.assertFalse(b.readonly)
|
||||
self.assertEqual(b.buf, e.data)
|
||||
b = Importer(a, buftools.PyBUF_FULL_RO)
|
||||
self.assertEqual(b.ndim, e.nd)
|
||||
self.assertEqual(b.format, "=h")
|
||||
self.assertEqual(b.len, e.len)
|
||||
self.assertEqual(b.itemsize, e.itemsize)
|
||||
self.assertEqual(b.shape, e.shape)
|
||||
self.assertEqual(b.strides, e.strides)
|
||||
self.assertTrue(b.suboffsets is None)
|
||||
self.assertFalse(b.readonly)
|
||||
self.assertEqual(b.buf, e.data)
|
||||
self.assertRaises(BufferError, Importer, a, buftools.PyBUF_SIMPLE)
|
||||
self.assertRaises(BufferError, Importer, a, buftools.PyBUF_WRITABLE)
|
||||
self.assertRaises(BufferError, Importer, a, buftools.PyBUF_WRITABLE)
|
||||
self.assertRaises(BufferError, Importer, a, buftools.PyBUF_ND)
|
||||
self.assertRaises(BufferError, Importer, a, buftools.PyBUF_C_CONTIGUOUS)
|
||||
self.assertRaises(BufferError, Importer, a, buftools.PyBUF_F_CONTIGUOUS)
|
||||
self.assertRaises(BufferError, Importer, a, buftools.PyBUF_ANY_CONTIGUOUS)
|
||||
self.assertRaises(BufferError, Importer, a, buftools.PyBUF_CONTIG)
|
||||
self.assertRaises(BufferError, Importer, a, buftools.PyBUF_SIMPLE)
|
||||
self.assertRaises(BufferError, Importer, a, buftools.PyBUF_ND)
|
||||
self.assertRaises(BufferError, Importer, a, buftools.PyBUF_C_CONTIGUOUS)
|
||||
self.assertRaises(BufferError, Importer, a, buftools.PyBUF_F_CONTIGUOUS)
|
||||
self.assertRaises(BufferError, Importer, a, buftools.PyBUF_ANY_CONTIGUOUS)
|
||||
self.assertRaises(BufferError, Importer, a, buftools.PyBUF_CONTIG)
|
||||
e = arrinter.Exporter(
|
||||
(3, 5, 10),
|
||||
typekind="i",
|
||||
itemsize=2,
|
||||
strides=(120, 24, 2),
|
||||
flags=arrinter.PAI_ALIGNED,
|
||||
)
|
||||
a = BufferProxy(e)
|
||||
b = Importer(a, buftools.PyBUF_FULL_RO)
|
||||
self.assertEqual(b.ndim, e.nd)
|
||||
self.assertEqual(b.format, frev + "h")
|
||||
self.assertEqual(b.len, e.len)
|
||||
self.assertEqual(b.itemsize, e.itemsize)
|
||||
self.assertEqual(b.shape, e.shape)
|
||||
self.assertEqual(b.strides, e.strides)
|
||||
self.assertTrue(b.suboffsets is None)
|
||||
self.assertTrue(b.readonly)
|
||||
self.assertEqual(b.buf, e.data)
|
||||
self.assertRaises(BufferError, Importer, a, buftools.PyBUF_FULL)
|
||||
|
||||
def test_PgObject_GetBuffer_exception(self):
|
||||
# For consistency with surfarray
|
||||
from pygame.bufferproxy import BufferProxy
|
||||
|
||||
bp = BufferProxy(1)
|
||||
self.assertRaises(ValueError, getattr, bp, "length")
|
||||
|
||||
def not_init_assertions(self):
|
||||
self.assertFalse(pygame.get_init(), "pygame shouldn't be initialized")
|
||||
self.assertFalse(pygame.display.get_init(), "display shouldn't be initialized")
|
||||
|
||||
if "pygame.mixer" in sys.modules:
|
||||
self.assertFalse(pygame.mixer.get_init(), "mixer shouldn't be initialized")
|
||||
|
||||
if "pygame.font" in sys.modules:
|
||||
self.assertFalse(pygame.font.get_init(), "init shouldn't be initialized")
|
||||
|
||||
## !!! TODO : Remove when scrap works for OS X
|
||||
import platform
|
||||
|
||||
if platform.system().startswith("Darwin"):
|
||||
return
|
||||
|
||||
try:
|
||||
self.assertRaises(pygame.error, pygame.scrap.get)
|
||||
except NotImplementedError:
|
||||
# Scrap is optional.
|
||||
pass
|
||||
|
||||
# pygame.cdrom
|
||||
# pygame.joystick
|
||||
|
||||
def init_assertions(self):
|
||||
self.assertTrue(pygame.get_init())
|
||||
self.assertTrue(pygame.display.get_init())
|
||||
|
||||
if "pygame.mixer" in sys.modules:
|
||||
self.assertTrue(pygame.mixer.get_init())
|
||||
|
||||
if "pygame.font" in sys.modules:
|
||||
self.assertTrue(pygame.font.get_init())
|
||||
|
||||
def test_quit__and_init(self):
|
||||
# __doc__ (as of 2008-06-25) for pygame.base.quit:
|
||||
|
||||
# pygame.quit(): return None
|
||||
# uninitialize all pygame modules
|
||||
|
||||
# Make sure everything is not init
|
||||
self.not_init_assertions()
|
||||
|
||||
# Initiate it
|
||||
pygame.init()
|
||||
|
||||
# Check
|
||||
self.init_assertions()
|
||||
|
||||
# Quit
|
||||
pygame.quit()
|
||||
|
||||
# All modules have quit
|
||||
self.not_init_assertions()
|
||||
|
||||
def test_register_quit(self):
|
||||
"""Ensure that a registered function is called on quit()"""
|
||||
self.assertEqual(quit_count, 0)
|
||||
|
||||
pygame.init()
|
||||
pygame.register_quit(quit_hook)
|
||||
pygame.quit()
|
||||
|
||||
self.assertEqual(quit_count, 1)
|
||||
|
||||
def test_get_error(self):
|
||||
# __doc__ (as of 2008-08-02) for pygame.base.get_error:
|
||||
|
||||
# pygame.get_error(): return errorstr
|
||||
# get the current error message
|
||||
#
|
||||
# SDL maintains an internal error message. This message will usually
|
||||
# be given to you when pygame.error is raised. You will rarely need to
|
||||
# call this function.
|
||||
#
|
||||
|
||||
# The first error could be all sorts of nonsense or empty.
|
||||
e = pygame.get_error()
|
||||
pygame.set_error("hi")
|
||||
self.assertEqual(pygame.get_error(), "hi")
|
||||
pygame.set_error("")
|
||||
self.assertEqual(pygame.get_error(), "")
|
||||
|
||||
def test_set_error(self):
|
||||
# The first error could be all sorts of nonsense or empty.
|
||||
e = pygame.get_error()
|
||||
pygame.set_error("hi")
|
||||
self.assertEqual(pygame.get_error(), "hi")
|
||||
pygame.set_error("")
|
||||
self.assertEqual(pygame.get_error(), "")
|
||||
|
||||
def test_unicode_error(self):
|
||||
pygame.set_error("你好")
|
||||
self.assertEqual("你好", pygame.get_error())
|
||||
|
||||
def test_init(self):
|
||||
"""Ensures init() works properly."""
|
||||
# Make sure nothing initialized.
|
||||
self.not_init_assertions()
|
||||
|
||||
# display and joystick must init, at minimum
|
||||
expected_min_passes = 2
|
||||
|
||||
# All modules should pass.
|
||||
expected_fails = 0
|
||||
|
||||
passes, fails = pygame.init()
|
||||
|
||||
self.init_assertions()
|
||||
self.assertGreaterEqual(passes, expected_min_passes)
|
||||
self.assertEqual(fails, expected_fails)
|
||||
|
||||
def test_get_init(self):
|
||||
# Test if get_init() gets the init state.
|
||||
self.assertFalse(pygame.get_init())
|
||||
|
||||
def test_get_init__after_init(self):
|
||||
# Test if get_init() gets the init state after pygame.init() called.
|
||||
pygame.init()
|
||||
|
||||
self.assertTrue(pygame.get_init())
|
||||
|
||||
def test_get_init__after_quit(self):
|
||||
# Test if get_init() gets the init state after pygame.quit() called.
|
||||
pygame.init()
|
||||
pygame.quit()
|
||||
|
||||
self.assertFalse(pygame.get_init())
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
153
.venv/lib/python3.7/site-packages/pygame/tests/blit_test.py
Normal file
153
.venv/lib/python3.7/site-packages/pygame/tests/blit_test.py
Normal file
@@ -0,0 +1,153 @@
|
||||
import unittest
|
||||
|
||||
import pygame
|
||||
from pygame.locals import *
|
||||
|
||||
|
||||
class BlitTest(unittest.TestCase):
|
||||
def test_SRCALPHA(self):
|
||||
"""SRCALPHA tests."""
|
||||
# blend(s, 0, d) = d
|
||||
s = pygame.Surface((1, 1), SRCALPHA, 32)
|
||||
s.fill((255, 255, 255, 0))
|
||||
|
||||
d = pygame.Surface((1, 1), SRCALPHA, 32)
|
||||
d.fill((0, 0, 255, 255))
|
||||
|
||||
s.blit(d, (0, 0))
|
||||
self.assertEqual(s.get_at((0, 0)), d.get_at((0, 0)))
|
||||
|
||||
# blend(s, 255, d) = s
|
||||
s = pygame.Surface((1, 1), SRCALPHA, 32)
|
||||
s.fill((123, 0, 0, 255))
|
||||
s1 = pygame.Surface((1, 1), SRCALPHA, 32)
|
||||
s1.fill((123, 0, 0, 255))
|
||||
d = pygame.Surface((1, 1), SRCALPHA, 32)
|
||||
d.fill((10, 0, 0, 0))
|
||||
s.blit(d, (0, 0))
|
||||
self.assertEqual(s.get_at((0, 0)), s1.get_at((0, 0)))
|
||||
|
||||
# TODO: these should be true too.
|
||||
# blend(0, sA, 0) = 0
|
||||
# blend(255, sA, 255) = 255
|
||||
# blend(s, sA, d) <= 255
|
||||
|
||||
def test_BLEND(self):
|
||||
"""BLEND_ tests."""
|
||||
|
||||
# test that it doesn't overflow, and that it is saturated.
|
||||
s = pygame.Surface((1, 1), SRCALPHA, 32)
|
||||
s.fill((255, 255, 255, 0))
|
||||
|
||||
d = pygame.Surface((1, 1), SRCALPHA, 32)
|
||||
d.fill((0, 0, 255, 255))
|
||||
|
||||
s.blit(d, (0, 0), None, BLEND_ADD)
|
||||
|
||||
# print("d %s" % (d.get_at((0,0)),))
|
||||
# print(s.get_at((0,0)))
|
||||
# self.assertEqual(s.get_at((0,0))[2], 255 )
|
||||
# self.assertEqual(s.get_at((0,0))[3], 0 )
|
||||
|
||||
s.blit(d, (0, 0), None, BLEND_RGBA_ADD)
|
||||
# print(s.get_at((0,0)))
|
||||
self.assertEqual(s.get_at((0, 0))[3], 255)
|
||||
|
||||
# test adding works.
|
||||
s.fill((20, 255, 255, 0))
|
||||
d.fill((10, 0, 255, 255))
|
||||
s.blit(d, (0, 0), None, BLEND_ADD)
|
||||
self.assertEqual(s.get_at((0, 0))[2], 255)
|
||||
|
||||
# test subbing works.
|
||||
s.fill((20, 255, 255, 0))
|
||||
d.fill((10, 0, 255, 255))
|
||||
s.blit(d, (0, 0), None, BLEND_SUB)
|
||||
self.assertEqual(s.get_at((0, 0))[0], 10)
|
||||
|
||||
# no overflow in sub blend.
|
||||
s.fill((20, 255, 255, 0))
|
||||
d.fill((30, 0, 255, 255))
|
||||
s.blit(d, (0, 0), None, BLEND_SUB)
|
||||
self.assertEqual(s.get_at((0, 0))[0], 0)
|
||||
|
||||
def make_blit_list(self, num_surfs):
|
||||
blit_list = []
|
||||
for i in range(num_surfs):
|
||||
dest = (i * 10, 0)
|
||||
surf = pygame.Surface((10, 10), SRCALPHA, 32)
|
||||
color = (i * 1, i * 1, i * 1)
|
||||
surf.fill(color)
|
||||
blit_list.append((surf, dest))
|
||||
return blit_list
|
||||
|
||||
def test_blits(self):
|
||||
NUM_SURFS = 255
|
||||
PRINT_TIMING = 0
|
||||
dst = pygame.Surface((NUM_SURFS * 10, 10), SRCALPHA, 32)
|
||||
dst.fill((230, 230, 230))
|
||||
blit_list = self.make_blit_list(NUM_SURFS)
|
||||
|
||||
def blits(blit_list):
|
||||
for surface, dest in blit_list:
|
||||
dst.blit(surface, dest)
|
||||
|
||||
from time import time
|
||||
|
||||
t0 = time()
|
||||
results = blits(blit_list)
|
||||
t1 = time()
|
||||
if PRINT_TIMING:
|
||||
print(f"python blits: {t1 - t0}")
|
||||
|
||||
dst.fill((230, 230, 230))
|
||||
t0 = time()
|
||||
results = dst.blits(blit_list)
|
||||
t1 = time()
|
||||
if PRINT_TIMING:
|
||||
print(f"Surface.blits :{t1 - t0}")
|
||||
|
||||
# check if we blit all the different colors in the correct spots.
|
||||
for i in range(NUM_SURFS):
|
||||
color = (i * 1, i * 1, i * 1)
|
||||
self.assertEqual(dst.get_at((i * 10, 0)), color)
|
||||
self.assertEqual(dst.get_at(((i * 10) + 5, 5)), color)
|
||||
|
||||
self.assertEqual(len(results), NUM_SURFS)
|
||||
|
||||
t0 = time()
|
||||
results = dst.blits(blit_list, doreturn=0)
|
||||
t1 = time()
|
||||
if PRINT_TIMING:
|
||||
print(f"Surface.blits doreturn=0: {t1 - t0}")
|
||||
self.assertEqual(results, None)
|
||||
|
||||
t0 = time()
|
||||
results = dst.blits(((surf, dest) for surf, dest in blit_list))
|
||||
t1 = time()
|
||||
if PRINT_TIMING:
|
||||
print(f"Surface.blits generator: {t1 - t0}")
|
||||
|
||||
def test_blits_not_sequence(self):
|
||||
dst = pygame.Surface((100, 10), SRCALPHA, 32)
|
||||
self.assertRaises(ValueError, dst.blits, None)
|
||||
|
||||
def test_blits_wrong_length(self):
|
||||
dst = pygame.Surface((100, 10), SRCALPHA, 32)
|
||||
self.assertRaises(
|
||||
ValueError, dst.blits, [pygame.Surface((10, 10), SRCALPHA, 32)]
|
||||
)
|
||||
|
||||
def test_blits_bad_surf_args(self):
|
||||
dst = pygame.Surface((100, 10), SRCALPHA, 32)
|
||||
self.assertRaises(TypeError, dst.blits, [(None, None)])
|
||||
|
||||
def test_blits_bad_dest(self):
|
||||
dst = pygame.Surface((100, 10), SRCALPHA, 32)
|
||||
self.assertRaises(
|
||||
TypeError, dst.blits, [(pygame.Surface((10, 10), SRCALPHA, 32), None)]
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
@@ -0,0 +1,504 @@
|
||||
import re
|
||||
import weakref
|
||||
import gc
|
||||
import ctypes
|
||||
import unittest
|
||||
|
||||
import pygame
|
||||
from pygame.bufferproxy import BufferProxy
|
||||
|
||||
|
||||
try:
|
||||
BufferError
|
||||
except NameError:
|
||||
from pygame import BufferError
|
||||
|
||||
|
||||
class BufferProxyTest(unittest.TestCase):
|
||||
view_keywords = {
|
||||
"shape": (5, 4, 3),
|
||||
"typestr": "|u1",
|
||||
"data": (0, True),
|
||||
"strides": (4, 20, 1),
|
||||
}
|
||||
|
||||
def test_module_name(self):
|
||||
self.assertEqual(pygame.bufferproxy.__name__, "pygame.bufferproxy")
|
||||
|
||||
def test_class_name(self):
|
||||
self.assertEqual(BufferProxy.__name__, "BufferProxy")
|
||||
|
||||
def test___array_struct___property(self):
|
||||
kwds = self.view_keywords
|
||||
v = BufferProxy(kwds)
|
||||
d = pygame.get_array_interface(v)
|
||||
self.assertEqual(len(d), 5)
|
||||
self.assertEqual(d["version"], 3)
|
||||
self.assertEqual(d["shape"], kwds["shape"])
|
||||
self.assertEqual(d["typestr"], kwds["typestr"])
|
||||
self.assertEqual(d["data"], kwds["data"])
|
||||
self.assertEqual(d["strides"], kwds["strides"])
|
||||
|
||||
def test___array_interface___property(self):
|
||||
kwds = self.view_keywords
|
||||
v = BufferProxy(kwds)
|
||||
d = v.__array_interface__
|
||||
self.assertEqual(len(d), 5)
|
||||
self.assertEqual(d["version"], 3)
|
||||
self.assertEqual(d["shape"], kwds["shape"])
|
||||
self.assertEqual(d["typestr"], kwds["typestr"])
|
||||
self.assertEqual(d["data"], kwds["data"])
|
||||
self.assertEqual(d["strides"], kwds["strides"])
|
||||
|
||||
def test_parent_property(self):
|
||||
kwds = dict(self.view_keywords)
|
||||
p = []
|
||||
kwds["parent"] = p
|
||||
v = BufferProxy(kwds)
|
||||
|
||||
self.assertIs(v.parent, p)
|
||||
|
||||
def test_before(self):
|
||||
def callback(parent):
|
||||
success.append(parent is p)
|
||||
|
||||
class MyException(Exception):
|
||||
pass
|
||||
|
||||
def raise_exception(parent):
|
||||
raise MyException("Just a test.")
|
||||
|
||||
kwds = dict(self.view_keywords)
|
||||
p = []
|
||||
kwds["parent"] = p
|
||||
|
||||
# For array interface
|
||||
success = []
|
||||
kwds["before"] = callback
|
||||
v = BufferProxy(kwds)
|
||||
self.assertEqual(len(success), 0)
|
||||
d = v.__array_interface__
|
||||
self.assertEqual(len(success), 1)
|
||||
self.assertTrue(success[0])
|
||||
d = v.__array_interface__
|
||||
self.assertEqual(len(success), 1)
|
||||
d = v = None
|
||||
gc.collect()
|
||||
self.assertEqual(len(success), 1)
|
||||
|
||||
# For array struct
|
||||
success = []
|
||||
kwds["before"] = callback
|
||||
v = BufferProxy(kwds)
|
||||
self.assertEqual(len(success), 0)
|
||||
c = v.__array_struct__
|
||||
self.assertEqual(len(success), 1)
|
||||
self.assertTrue(success[0])
|
||||
c = v.__array_struct__
|
||||
self.assertEqual(len(success), 1)
|
||||
c = v = None
|
||||
gc.collect()
|
||||
self.assertEqual(len(success), 1)
|
||||
|
||||
# Callback raises an exception
|
||||
kwds["before"] = raise_exception
|
||||
v = BufferProxy(kwds)
|
||||
self.assertRaises(MyException, lambda: v.__array_struct__)
|
||||
|
||||
def test_after(self):
|
||||
def callback(parent):
|
||||
success.append(parent is p)
|
||||
|
||||
kwds = dict(self.view_keywords)
|
||||
p = []
|
||||
kwds["parent"] = p
|
||||
|
||||
# For array interface
|
||||
success = []
|
||||
kwds["after"] = callback
|
||||
v = BufferProxy(kwds)
|
||||
self.assertEqual(len(success), 0)
|
||||
d = v.__array_interface__
|
||||
self.assertEqual(len(success), 0)
|
||||
d = v.__array_interface__
|
||||
self.assertEqual(len(success), 0)
|
||||
d = v = None
|
||||
gc.collect()
|
||||
self.assertEqual(len(success), 1)
|
||||
self.assertTrue(success[0])
|
||||
|
||||
# For array struct
|
||||
success = []
|
||||
kwds["after"] = callback
|
||||
v = BufferProxy(kwds)
|
||||
self.assertEqual(len(success), 0)
|
||||
c = v.__array_struct__
|
||||
self.assertEqual(len(success), 0)
|
||||
c = v.__array_struct__
|
||||
self.assertEqual(len(success), 0)
|
||||
c = v = None
|
||||
gc.collect()
|
||||
self.assertEqual(len(success), 1)
|
||||
self.assertTrue(success[0])
|
||||
|
||||
def test_attribute(self):
|
||||
v = BufferProxy(self.view_keywords)
|
||||
self.assertRaises(AttributeError, getattr, v, "undefined")
|
||||
v.undefined = 12
|
||||
self.assertEqual(v.undefined, 12)
|
||||
del v.undefined
|
||||
self.assertRaises(AttributeError, getattr, v, "undefined")
|
||||
|
||||
def test_weakref(self):
|
||||
v = BufferProxy(self.view_keywords)
|
||||
weak_v = weakref.ref(v)
|
||||
|
||||
self.assertIs(weak_v(), v)
|
||||
|
||||
v = None
|
||||
gc.collect()
|
||||
|
||||
self.assertIsNone(weak_v())
|
||||
|
||||
def test_gc(self):
|
||||
"""refcount agnostic check that contained objects are freed"""
|
||||
|
||||
def before_callback(parent):
|
||||
return r[0]
|
||||
|
||||
def after_callback(parent):
|
||||
return r[1]
|
||||
|
||||
class Obj:
|
||||
pass
|
||||
|
||||
p = Obj()
|
||||
a = Obj()
|
||||
r = [Obj(), Obj()]
|
||||
weak_p = weakref.ref(p)
|
||||
weak_a = weakref.ref(a)
|
||||
weak_r0 = weakref.ref(r[0])
|
||||
weak_r1 = weakref.ref(r[1])
|
||||
weak_before = weakref.ref(before_callback)
|
||||
weak_after = weakref.ref(after_callback)
|
||||
kwds = dict(self.view_keywords)
|
||||
kwds["parent"] = p
|
||||
kwds["before"] = before_callback
|
||||
kwds["after"] = after_callback
|
||||
v = BufferProxy(kwds)
|
||||
v.some_attribute = a
|
||||
weak_v = weakref.ref(v)
|
||||
kwds = p = a = before_callback = after_callback = None
|
||||
gc.collect()
|
||||
self.assertTrue(weak_p() is not None)
|
||||
self.assertTrue(weak_a() is not None)
|
||||
self.assertTrue(weak_before() is not None)
|
||||
self.assertTrue(weak_after() is not None)
|
||||
v = None
|
||||
[gc.collect() for x in range(4)]
|
||||
self.assertTrue(weak_v() is None)
|
||||
self.assertTrue(weak_p() is None)
|
||||
self.assertTrue(weak_a() is None)
|
||||
self.assertTrue(weak_before() is None)
|
||||
self.assertTrue(weak_after() is None)
|
||||
self.assertTrue(weak_r0() is not None)
|
||||
self.assertTrue(weak_r1() is not None)
|
||||
r = None
|
||||
gc.collect()
|
||||
self.assertTrue(weak_r0() is None)
|
||||
self.assertTrue(weak_r1() is None)
|
||||
|
||||
# Cycle removal
|
||||
kwds = dict(self.view_keywords)
|
||||
kwds["parent"] = []
|
||||
v = BufferProxy(kwds)
|
||||
v.some_attribute = v
|
||||
tracked = True
|
||||
for o in gc.get_objects():
|
||||
if o is v:
|
||||
break
|
||||
else:
|
||||
tracked = False
|
||||
self.assertTrue(tracked)
|
||||
kwds["parent"].append(v)
|
||||
kwds = None
|
||||
gc.collect()
|
||||
n1 = len(gc.garbage)
|
||||
v = None
|
||||
gc.collect()
|
||||
n2 = len(gc.garbage)
|
||||
self.assertEqual(n2, n1)
|
||||
|
||||
def test_c_api(self):
|
||||
api = pygame.bufferproxy._PYGAME_C_API
|
||||
api_type = type(pygame.base._PYGAME_C_API)
|
||||
|
||||
self.assertIsInstance(api, api_type)
|
||||
|
||||
def test_repr(self):
|
||||
v = BufferProxy(self.view_keywords)
|
||||
cname = BufferProxy.__name__
|
||||
oname, ovalue = re.findall(r"<([^)]+)\(([^)]+)\)>", repr(v))[0]
|
||||
self.assertEqual(oname, cname)
|
||||
self.assertEqual(v.length, int(ovalue))
|
||||
|
||||
def test_subclassing(self):
|
||||
class MyBufferProxy(BufferProxy):
|
||||
def __repr__(self):
|
||||
return f"*{BufferProxy.__repr__(self)}*"
|
||||
|
||||
kwds = dict(self.view_keywords)
|
||||
kwds["parent"] = 0
|
||||
v = MyBufferProxy(kwds)
|
||||
self.assertEqual(v.parent, 0)
|
||||
r = repr(v)
|
||||
self.assertEqual(r[:2], "*<")
|
||||
self.assertEqual(r[-2:], ">*")
|
||||
|
||||
@unittest.skipIf(not pygame.HAVE_NEWBUF, "newbuf not implemented")
|
||||
def NEWBUF_test_newbuf(self):
|
||||
from ctypes import string_at
|
||||
|
||||
from pygame.tests.test_utils import buftools
|
||||
|
||||
Exporter = buftools.Exporter
|
||||
Importer = buftools.Importer
|
||||
exp = Exporter((10,), "B", readonly=True)
|
||||
b = BufferProxy(exp)
|
||||
self.assertEqual(b.length, exp.len)
|
||||
self.assertEqual(b.raw, string_at(exp.buf, exp.len))
|
||||
d = b.__array_interface__
|
||||
try:
|
||||
self.assertEqual(d["typestr"], "|u1")
|
||||
self.assertEqual(d["shape"], exp.shape)
|
||||
self.assertEqual(d["strides"], exp.strides)
|
||||
self.assertEqual(d["data"], (exp.buf, True))
|
||||
finally:
|
||||
d = None
|
||||
exp = Exporter((3,), "=h")
|
||||
b = BufferProxy(exp)
|
||||
self.assertEqual(b.length, exp.len)
|
||||
self.assertEqual(b.raw, string_at(exp.buf, exp.len))
|
||||
d = b.__array_interface__
|
||||
try:
|
||||
lil_endian = pygame.get_sdl_byteorder() == pygame.LIL_ENDIAN
|
||||
f = f"{'<' if lil_endian else '>'}i{exp.itemsize}"
|
||||
self.assertEqual(d["typestr"], f)
|
||||
self.assertEqual(d["shape"], exp.shape)
|
||||
self.assertEqual(d["strides"], exp.strides)
|
||||
self.assertEqual(d["data"], (exp.buf, False))
|
||||
finally:
|
||||
d = None
|
||||
|
||||
exp = Exporter((10, 2), "=i")
|
||||
b = BufferProxy(exp)
|
||||
imp = Importer(b, buftools.PyBUF_RECORDS)
|
||||
self.assertTrue(imp.obj is b)
|
||||
self.assertEqual(imp.buf, exp.buf)
|
||||
self.assertEqual(imp.ndim, exp.ndim)
|
||||
self.assertEqual(imp.format, exp.format)
|
||||
self.assertEqual(imp.readonly, exp.readonly)
|
||||
self.assertEqual(imp.itemsize, exp.itemsize)
|
||||
self.assertEqual(imp.len, exp.len)
|
||||
self.assertEqual(imp.shape, exp.shape)
|
||||
self.assertEqual(imp.strides, exp.strides)
|
||||
self.assertTrue(imp.suboffsets is None)
|
||||
|
||||
d = {
|
||||
"typestr": "|u1",
|
||||
"shape": (10,),
|
||||
"strides": (1,),
|
||||
"data": (9, True),
|
||||
} # 9? Will not reading the data anyway.
|
||||
b = BufferProxy(d)
|
||||
imp = Importer(b, buftools.PyBUF_SIMPLE)
|
||||
self.assertTrue(imp.obj is b)
|
||||
self.assertEqual(imp.buf, 9)
|
||||
self.assertEqual(imp.len, 10)
|
||||
self.assertEqual(imp.format, None)
|
||||
self.assertEqual(imp.itemsize, 1)
|
||||
self.assertEqual(imp.ndim, 0)
|
||||
self.assertTrue(imp.readonly)
|
||||
self.assertTrue(imp.shape is None)
|
||||
self.assertTrue(imp.strides is None)
|
||||
self.assertTrue(imp.suboffsets is None)
|
||||
|
||||
try:
|
||||
pygame.bufferproxy.get_segcount
|
||||
except AttributeError:
|
||||
pass
|
||||
else:
|
||||
|
||||
def test_oldbuf_arg(self):
|
||||
self.OLDBUF_test_oldbuf_arg()
|
||||
|
||||
def OLDBUF_test_oldbuf_arg(self):
|
||||
from pygame.bufferproxy import get_segcount, get_read_buffer, get_write_buffer
|
||||
|
||||
content = b"\x01\x00\x00\x02" * 12
|
||||
memory = ctypes.create_string_buffer(content)
|
||||
memaddr = ctypes.addressof(memory)
|
||||
|
||||
def raise_exception(o):
|
||||
raise ValueError("An exception")
|
||||
|
||||
bf = BufferProxy(
|
||||
{
|
||||
"shape": (len(content),),
|
||||
"typestr": "|u1",
|
||||
"data": (memaddr, False),
|
||||
"strides": (1,),
|
||||
}
|
||||
)
|
||||
seglen, segaddr = get_read_buffer(bf, 0)
|
||||
self.assertEqual(segaddr, 0)
|
||||
self.assertEqual(seglen, 0)
|
||||
seglen, segaddr = get_write_buffer(bf, 0)
|
||||
self.assertEqual(segaddr, 0)
|
||||
self.assertEqual(seglen, 0)
|
||||
segcount, buflen = get_segcount(bf)
|
||||
self.assertEqual(segcount, 1)
|
||||
self.assertEqual(buflen, len(content))
|
||||
seglen, segaddr = get_read_buffer(bf, 0)
|
||||
self.assertEqual(segaddr, memaddr)
|
||||
self.assertEqual(seglen, len(content))
|
||||
seglen, segaddr = get_write_buffer(bf, 0)
|
||||
self.assertEqual(segaddr, memaddr)
|
||||
self.assertEqual(seglen, len(content))
|
||||
|
||||
bf = BufferProxy(
|
||||
{
|
||||
"shape": (len(content),),
|
||||
"typestr": "|u1",
|
||||
"data": (memaddr, True),
|
||||
"strides": (1,),
|
||||
}
|
||||
)
|
||||
segcount, buflen = get_segcount(bf)
|
||||
self.assertEqual(segcount, 1)
|
||||
self.assertEqual(buflen, len(content))
|
||||
seglen, segaddr = get_read_buffer(bf, 0)
|
||||
self.assertEqual(segaddr, memaddr)
|
||||
self.assertEqual(seglen, len(content))
|
||||
self.assertRaises(ValueError, get_write_buffer, bf, 0)
|
||||
|
||||
bf = BufferProxy(
|
||||
{
|
||||
"shape": (len(content),),
|
||||
"typestr": "|u1",
|
||||
"data": (memaddr, True),
|
||||
"strides": (1,),
|
||||
"before": raise_exception,
|
||||
}
|
||||
)
|
||||
segcount, buflen = get_segcount(bf)
|
||||
self.assertEqual(segcount, 0)
|
||||
self.assertEqual(buflen, 0)
|
||||
|
||||
bf = BufferProxy(
|
||||
{
|
||||
"shape": (3, 4),
|
||||
"typestr": "|u4",
|
||||
"data": (memaddr, True),
|
||||
"strides": (12, 4),
|
||||
}
|
||||
)
|
||||
segcount, buflen = get_segcount(bf)
|
||||
self.assertEqual(segcount, 3 * 4)
|
||||
self.assertEqual(buflen, 3 * 4 * 4)
|
||||
for i in range(0, 4):
|
||||
seglen, segaddr = get_read_buffer(bf, i)
|
||||
self.assertEqual(segaddr, memaddr + i * 4)
|
||||
self.assertEqual(seglen, 4)
|
||||
|
||||
|
||||
class BufferProxyLegacyTest(unittest.TestCase):
|
||||
content = b"\x01\x00\x00\x02" * 12
|
||||
buffer = ctypes.create_string_buffer(content)
|
||||
data = (ctypes.addressof(buffer), True)
|
||||
|
||||
def test_length(self):
|
||||
# __doc__ (as of 2008-08-02) for pygame.bufferproxy.BufferProxy.length:
|
||||
|
||||
# The size of the buffer data in bytes.
|
||||
bf = BufferProxy(
|
||||
{"shape": (3, 4), "typestr": "|u4", "data": self.data, "strides": (12, 4)}
|
||||
)
|
||||
self.assertEqual(bf.length, len(self.content))
|
||||
bf = BufferProxy(
|
||||
{"shape": (3, 3), "typestr": "|u4", "data": self.data, "strides": (12, 4)}
|
||||
)
|
||||
self.assertEqual(bf.length, 3 * 3 * 4)
|
||||
|
||||
def test_raw(self):
|
||||
# __doc__ (as of 2008-08-02) for pygame.bufferproxy.BufferProxy.raw:
|
||||
|
||||
# The raw buffer data as string. The string may contain NUL bytes.
|
||||
|
||||
bf = BufferProxy(
|
||||
{"shape": (len(self.content),), "typestr": "|u1", "data": self.data}
|
||||
)
|
||||
self.assertEqual(bf.raw, self.content)
|
||||
bf = BufferProxy(
|
||||
{"shape": (3, 4), "typestr": "|u4", "data": self.data, "strides": (4, 12)}
|
||||
)
|
||||
self.assertEqual(bf.raw, self.content)
|
||||
bf = BufferProxy(
|
||||
{"shape": (3, 4), "typestr": "|u1", "data": self.data, "strides": (16, 4)}
|
||||
)
|
||||
self.assertRaises(ValueError, getattr, bf, "raw")
|
||||
|
||||
def test_write(self):
|
||||
# __doc__ (as of 2008-08-02) for pygame.bufferproxy.BufferProxy.write:
|
||||
|
||||
# B.write (bufferproxy, buffer, offset) -> None
|
||||
#
|
||||
# Writes raw data to the bufferproxy.
|
||||
#
|
||||
# Writes the raw data from buffer to the BufferProxy object, starting
|
||||
# at the specified offset within the BufferProxy.
|
||||
# If the length of the passed buffer exceeds the length of the
|
||||
# BufferProxy (reduced by the offset), an IndexError will be raised.
|
||||
from ctypes import c_byte, sizeof, addressof, string_at, memset
|
||||
|
||||
nullbyte = b"\x00"
|
||||
Buf = c_byte * 10
|
||||
data_buf = Buf(*range(1, 3 * sizeof(Buf) + 1, 3))
|
||||
data = string_at(data_buf, sizeof(data_buf))
|
||||
buf = Buf()
|
||||
bp = BufferProxy(
|
||||
{"typestr": "|u1", "shape": (sizeof(buf),), "data": (addressof(buf), False)}
|
||||
)
|
||||
try:
|
||||
self.assertEqual(bp.raw, nullbyte * sizeof(Buf))
|
||||
bp.write(data)
|
||||
self.assertEqual(bp.raw, data)
|
||||
memset(buf, 0, sizeof(buf))
|
||||
bp.write(data[:3], 2)
|
||||
raw = bp.raw
|
||||
self.assertEqual(raw[:2], nullbyte * 2)
|
||||
self.assertEqual(raw[2:5], data[:3])
|
||||
self.assertEqual(raw[5:], nullbyte * (sizeof(Buf) - 5))
|
||||
bp.write(data[:3], bp.length - 3)
|
||||
raw = bp.raw
|
||||
self.assertEqual(raw[-3:], data[:3])
|
||||
self.assertRaises(IndexError, bp.write, data, 1)
|
||||
self.assertRaises(IndexError, bp.write, data[:5], -1)
|
||||
self.assertRaises(IndexError, bp.write, data[:5], bp.length)
|
||||
self.assertRaises(TypeError, bp.write, 12)
|
||||
bp = BufferProxy(
|
||||
{
|
||||
"typestr": "|u1",
|
||||
"shape": (sizeof(buf),),
|
||||
"data": (addressof(buf), True),
|
||||
}
|
||||
)
|
||||
self.assertRaises(pygame.BufferError, bp.write, b"123")
|
||||
finally:
|
||||
# Make sure bp is garbage collected before buf
|
||||
bp = None
|
||||
gc.collect()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
@@ -0,0 +1,5 @@
|
||||
import unittest
|
||||
|
||||
|
||||
class CameraModuleTest(unittest.TestCase):
|
||||
pass
|
1360
.venv/lib/python3.7/site-packages/pygame/tests/color_test.py
Normal file
1360
.venv/lib/python3.7/site-packages/pygame/tests/color_test.py
Normal file
File diff suppressed because it is too large
Load Diff
426
.venv/lib/python3.7/site-packages/pygame/tests/constants_test.py
Normal file
426
.venv/lib/python3.7/site-packages/pygame/tests/constants_test.py
Normal file
@@ -0,0 +1,426 @@
|
||||
import unittest
|
||||
import pygame.constants
|
||||
|
||||
|
||||
# K_* and KSCAN_* common names.
|
||||
K_AND_KSCAN_COMMON_NAMES = (
|
||||
"UNKNOWN",
|
||||
"BACKSPACE",
|
||||
"TAB",
|
||||
"CLEAR",
|
||||
"RETURN",
|
||||
"PAUSE",
|
||||
"ESCAPE",
|
||||
"SPACE",
|
||||
"COMMA",
|
||||
"MINUS",
|
||||
"PERIOD",
|
||||
"SLASH",
|
||||
"0",
|
||||
"1",
|
||||
"2",
|
||||
"3",
|
||||
"4",
|
||||
"5",
|
||||
"6",
|
||||
"7",
|
||||
"8",
|
||||
"9",
|
||||
"SEMICOLON",
|
||||
"EQUALS",
|
||||
"LEFTBRACKET",
|
||||
"BACKSLASH",
|
||||
"RIGHTBRACKET",
|
||||
"DELETE",
|
||||
"KP0",
|
||||
"KP1",
|
||||
"KP2",
|
||||
"KP3",
|
||||
"KP4",
|
||||
"KP5",
|
||||
"KP6",
|
||||
"KP7",
|
||||
"KP8",
|
||||
"KP9",
|
||||
"KP_PERIOD",
|
||||
"KP_DIVIDE",
|
||||
"KP_MULTIPLY",
|
||||
"KP_MINUS",
|
||||
"KP_PLUS",
|
||||
"KP_ENTER",
|
||||
"KP_EQUALS",
|
||||
"UP",
|
||||
"DOWN",
|
||||
"RIGHT",
|
||||
"LEFT",
|
||||
"INSERT",
|
||||
"HOME",
|
||||
"END",
|
||||
"PAGEUP",
|
||||
"PAGEDOWN",
|
||||
"F1",
|
||||
"F2",
|
||||
"F3",
|
||||
"F4",
|
||||
"F5",
|
||||
"F6",
|
||||
"F7",
|
||||
"F8",
|
||||
"F9",
|
||||
"F10",
|
||||
"F11",
|
||||
"F12",
|
||||
"F13",
|
||||
"F14",
|
||||
"F15",
|
||||
"NUMLOCK",
|
||||
"CAPSLOCK",
|
||||
"SCROLLOCK",
|
||||
"RSHIFT",
|
||||
"LSHIFT",
|
||||
"RCTRL",
|
||||
"LCTRL",
|
||||
"RALT",
|
||||
"LALT",
|
||||
"RMETA",
|
||||
"LMETA",
|
||||
"LSUPER",
|
||||
"RSUPER",
|
||||
"MODE",
|
||||
"HELP",
|
||||
"PRINT",
|
||||
"SYSREQ",
|
||||
"BREAK",
|
||||
"MENU",
|
||||
"POWER",
|
||||
"EURO",
|
||||
"KP_0",
|
||||
"KP_1",
|
||||
"KP_2",
|
||||
"KP_3",
|
||||
"KP_4",
|
||||
"KP_5",
|
||||
"KP_6",
|
||||
"KP_7",
|
||||
"KP_8",
|
||||
"KP_9",
|
||||
"NUMLOCKCLEAR",
|
||||
"SCROLLLOCK",
|
||||
"RGUI",
|
||||
"LGUI",
|
||||
"PRINTSCREEN",
|
||||
"CURRENCYUNIT",
|
||||
"CURRENCYSUBUNIT",
|
||||
)
|
||||
|
||||
# Constants that have the same value.
|
||||
K_AND_KSCAN_COMMON_OVERLAPS = (
|
||||
("KP0", "KP_0"),
|
||||
("KP1", "KP_1"),
|
||||
("KP2", "KP_2"),
|
||||
("KP3", "KP_3"),
|
||||
("KP4", "KP_4"),
|
||||
("KP5", "KP_5"),
|
||||
("KP6", "KP_6"),
|
||||
("KP7", "KP_7"),
|
||||
("KP8", "KP_8"),
|
||||
("KP9", "KP_9"),
|
||||
("NUMLOCK", "NUMLOCKCLEAR"),
|
||||
("SCROLLOCK", "SCROLLLOCK"),
|
||||
("LSUPER", "LMETA", "LGUI"),
|
||||
("RSUPER", "RMETA", "RGUI"),
|
||||
("PRINT", "PRINTSCREEN"),
|
||||
("BREAK", "PAUSE"),
|
||||
("EURO", "CURRENCYUNIT"),
|
||||
)
|
||||
|
||||
|
||||
def create_overlap_set(constant_names):
|
||||
"""Helper function to find overlapping constant values/names.
|
||||
|
||||
Returns a set of fronzensets:
|
||||
set(frozenset(names of overlapping constants), ...)
|
||||
"""
|
||||
# Create an overlap dict.
|
||||
overlap_dict = {}
|
||||
|
||||
for name in constant_names:
|
||||
value = getattr(pygame.constants, name)
|
||||
overlap_dict.setdefault(value, set()).add(name)
|
||||
|
||||
# Get all entries with more than 1 value.
|
||||
overlaps = set()
|
||||
|
||||
for overlap_names in overlap_dict.values():
|
||||
if len(overlap_names) > 1:
|
||||
overlaps.add(frozenset(overlap_names))
|
||||
|
||||
return overlaps
|
||||
|
||||
|
||||
class KConstantsTests(unittest.TestCase):
|
||||
"""Test K_* (key) constants."""
|
||||
|
||||
# K_* specific names.
|
||||
K_SPECIFIC_NAMES = (
|
||||
"a",
|
||||
"b",
|
||||
"c",
|
||||
"d",
|
||||
"e",
|
||||
"f",
|
||||
"g",
|
||||
"h",
|
||||
"i",
|
||||
"j",
|
||||
"k",
|
||||
"l",
|
||||
"m",
|
||||
"n",
|
||||
"o",
|
||||
"p",
|
||||
"q",
|
||||
"r",
|
||||
"s",
|
||||
"t",
|
||||
"u",
|
||||
"v",
|
||||
"w",
|
||||
"x",
|
||||
"y",
|
||||
"z",
|
||||
"QUOTE",
|
||||
"BACKQUOTE",
|
||||
"EXCLAIM",
|
||||
"QUOTEDBL",
|
||||
"HASH",
|
||||
"DOLLAR",
|
||||
"AMPERSAND",
|
||||
"LEFTPAREN",
|
||||
"RIGHTPAREN",
|
||||
"ASTERISK",
|
||||
"PLUS",
|
||||
"COLON",
|
||||
"LESS",
|
||||
"GREATER",
|
||||
"QUESTION",
|
||||
"AT",
|
||||
"CARET",
|
||||
"UNDERSCORE",
|
||||
"PERCENT",
|
||||
)
|
||||
|
||||
# Create a sequence of all the K_* constant names.
|
||||
K_NAMES = tuple("K_" + n for n in K_AND_KSCAN_COMMON_NAMES + K_SPECIFIC_NAMES)
|
||||
|
||||
def test_k__existence(self):
|
||||
"""Ensures K constants exist."""
|
||||
for name in self.K_NAMES:
|
||||
self.assertTrue(hasattr(pygame.constants, name), f"missing constant {name}")
|
||||
|
||||
def test_k__type(self):
|
||||
"""Ensures K constants are the correct type."""
|
||||
for name in self.K_NAMES:
|
||||
value = getattr(pygame.constants, name)
|
||||
|
||||
self.assertIs(type(value), int)
|
||||
|
||||
def test_k__value_overlap(self):
|
||||
"""Ensures no unexpected K constant values overlap."""
|
||||
EXPECTED_OVERLAPS = {
|
||||
frozenset("K_" + n for n in item) for item in K_AND_KSCAN_COMMON_OVERLAPS
|
||||
}
|
||||
|
||||
overlaps = create_overlap_set(self.K_NAMES)
|
||||
|
||||
self.assertSetEqual(overlaps, EXPECTED_OVERLAPS)
|
||||
|
||||
|
||||
class KscanConstantsTests(unittest.TestCase):
|
||||
"""Test KSCAN_* (scancode) constants."""
|
||||
|
||||
# KSCAN_* specific names.
|
||||
KSCAN_SPECIFIC_NAMES = (
|
||||
"A",
|
||||
"B",
|
||||
"C",
|
||||
"D",
|
||||
"E",
|
||||
"F",
|
||||
"G",
|
||||
"H",
|
||||
"I",
|
||||
"J",
|
||||
"K",
|
||||
"L",
|
||||
"M",
|
||||
"N",
|
||||
"O",
|
||||
"P",
|
||||
"Q",
|
||||
"R",
|
||||
"S",
|
||||
"T",
|
||||
"U",
|
||||
"V",
|
||||
"W",
|
||||
"X",
|
||||
"Y",
|
||||
"Z",
|
||||
"APOSTROPHE",
|
||||
"GRAVE",
|
||||
"INTERNATIONAL1",
|
||||
"INTERNATIONAL2",
|
||||
"INTERNATIONAL3",
|
||||
"INTERNATIONAL4",
|
||||
"INTERNATIONAL5",
|
||||
"INTERNATIONAL6",
|
||||
"INTERNATIONAL7",
|
||||
"INTERNATIONAL8",
|
||||
"INTERNATIONAL9",
|
||||
"LANG1",
|
||||
"LANG2",
|
||||
"LANG3",
|
||||
"LANG4",
|
||||
"LANG5",
|
||||
"LANG6",
|
||||
"LANG7",
|
||||
"LANG8",
|
||||
"LANG9",
|
||||
"NONUSBACKSLASH",
|
||||
"NONUSHASH",
|
||||
)
|
||||
|
||||
# Create a sequence of all the KSCAN_* constant names.
|
||||
KSCAN_NAMES = tuple(
|
||||
"KSCAN_" + n for n in K_AND_KSCAN_COMMON_NAMES + KSCAN_SPECIFIC_NAMES
|
||||
)
|
||||
|
||||
def test_kscan__existence(self):
|
||||
"""Ensures KSCAN constants exist."""
|
||||
for name in self.KSCAN_NAMES:
|
||||
self.assertTrue(hasattr(pygame.constants, name), f"missing constant {name}")
|
||||
|
||||
def test_kscan__type(self):
|
||||
"""Ensures KSCAN constants are the correct type."""
|
||||
for name in self.KSCAN_NAMES:
|
||||
value = getattr(pygame.constants, name)
|
||||
|
||||
self.assertIs(type(value), int)
|
||||
|
||||
def test_kscan__value_overlap(self):
|
||||
"""Ensures no unexpected KSCAN constant values overlap."""
|
||||
EXPECTED_OVERLAPS = {
|
||||
frozenset("KSCAN_" + n for n in item)
|
||||
for item in K_AND_KSCAN_COMMON_OVERLAPS
|
||||
}
|
||||
|
||||
overlaps = create_overlap_set(self.KSCAN_NAMES)
|
||||
|
||||
self.assertSetEqual(overlaps, EXPECTED_OVERLAPS)
|
||||
|
||||
|
||||
class KmodConstantsTests(unittest.TestCase):
|
||||
"""Test KMOD_* (key modifier) constants."""
|
||||
|
||||
# KMOD_* constant names.
|
||||
KMOD_CONSTANTS = (
|
||||
"KMOD_NONE",
|
||||
"KMOD_LSHIFT",
|
||||
"KMOD_RSHIFT",
|
||||
"KMOD_SHIFT",
|
||||
"KMOD_LCTRL",
|
||||
"KMOD_RCTRL",
|
||||
"KMOD_CTRL",
|
||||
"KMOD_LALT",
|
||||
"KMOD_RALT",
|
||||
"KMOD_ALT",
|
||||
"KMOD_LMETA",
|
||||
"KMOD_RMETA",
|
||||
"KMOD_META",
|
||||
"KMOD_NUM",
|
||||
"KMOD_CAPS",
|
||||
"KMOD_MODE",
|
||||
"KMOD_LGUI",
|
||||
"KMOD_RGUI",
|
||||
"KMOD_GUI",
|
||||
)
|
||||
|
||||
def test_kmod__existence(self):
|
||||
"""Ensures KMOD constants exist."""
|
||||
for name in self.KMOD_CONSTANTS:
|
||||
self.assertTrue(hasattr(pygame.constants, name), f"missing constant {name}")
|
||||
|
||||
def test_kmod__type(self):
|
||||
"""Ensures KMOD constants are the correct type."""
|
||||
for name in self.KMOD_CONSTANTS:
|
||||
value = getattr(pygame.constants, name)
|
||||
|
||||
self.assertIs(type(value), int)
|
||||
|
||||
def test_kmod__value_overlap(self):
|
||||
"""Ensures no unexpected KMOD constant values overlap."""
|
||||
# KMODs that have the same values.
|
||||
EXPECTED_OVERLAPS = {
|
||||
frozenset(["KMOD_LGUI", "KMOD_LMETA"]),
|
||||
frozenset(["KMOD_RGUI", "KMOD_RMETA"]),
|
||||
frozenset(["KMOD_GUI", "KMOD_META"]),
|
||||
}
|
||||
|
||||
overlaps = create_overlap_set(self.KMOD_CONSTANTS)
|
||||
|
||||
self.assertSetEqual(overlaps, EXPECTED_OVERLAPS)
|
||||
|
||||
def test_kmod__no_bitwise_overlap(self):
|
||||
"""Ensures certain KMOD constants have no overlapping bits."""
|
||||
NO_BITWISE_OVERLAP = (
|
||||
"KMOD_NONE",
|
||||
"KMOD_LSHIFT",
|
||||
"KMOD_RSHIFT",
|
||||
"KMOD_LCTRL",
|
||||
"KMOD_RCTRL",
|
||||
"KMOD_LALT",
|
||||
"KMOD_RALT",
|
||||
"KMOD_LMETA",
|
||||
"KMOD_RMETA",
|
||||
"KMOD_NUM",
|
||||
"KMOD_CAPS",
|
||||
"KMOD_MODE",
|
||||
)
|
||||
|
||||
kmods = 0
|
||||
|
||||
for name in NO_BITWISE_OVERLAP:
|
||||
value = getattr(pygame.constants, name)
|
||||
|
||||
self.assertFalse(kmods & value)
|
||||
|
||||
kmods |= value
|
||||
|
||||
def test_kmod__bitwise_overlap(self):
|
||||
"""Ensures certain KMOD constants have overlapping bits."""
|
||||
# KMODS that are comprised of other KMODs.
|
||||
KMOD_COMPRISED_DICT = {
|
||||
"KMOD_SHIFT": ("KMOD_LSHIFT", "KMOD_RSHIFT"),
|
||||
"KMOD_CTRL": ("KMOD_LCTRL", "KMOD_RCTRL"),
|
||||
"KMOD_ALT": ("KMOD_LALT", "KMOD_RALT"),
|
||||
"KMOD_META": ("KMOD_LMETA", "KMOD_RMETA"),
|
||||
"KMOD_GUI": ("KMOD_LGUI", "KMOD_RGUI"),
|
||||
}
|
||||
|
||||
for base_name, seq_names in KMOD_COMPRISED_DICT.items():
|
||||
expected_value = 0 # Reset.
|
||||
|
||||
for name in seq_names:
|
||||
expected_value |= getattr(pygame.constants, name)
|
||||
|
||||
value = getattr(pygame.constants, base_name)
|
||||
|
||||
self.assertEqual(value, expected_value)
|
||||
|
||||
|
||||
################################################################################
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
@@ -0,0 +1,357 @@
|
||||
import unittest
|
||||
import pygame
|
||||
import pygame._sdl2.controller as controller
|
||||
from pygame.tests.test_utils import prompt, question
|
||||
|
||||
|
||||
class ControllerModuleTest(unittest.TestCase):
|
||||
def setUp(self):
|
||||
controller.init()
|
||||
|
||||
def tearDown(self):
|
||||
controller.quit()
|
||||
|
||||
def test_init(self):
|
||||
controller.quit()
|
||||
controller.init()
|
||||
self.assertTrue(controller.get_init())
|
||||
|
||||
def test_init__multiple(self):
|
||||
controller.init()
|
||||
controller.init()
|
||||
self.assertTrue(controller.get_init())
|
||||
|
||||
def test_quit(self):
|
||||
controller.quit()
|
||||
self.assertFalse(controller.get_init())
|
||||
|
||||
def test_quit__multiple(self):
|
||||
controller.quit()
|
||||
controller.quit()
|
||||
self.assertFalse(controller.get_init())
|
||||
|
||||
def test_get_init(self):
|
||||
self.assertTrue(controller.get_init())
|
||||
|
||||
def test_get_eventstate(self):
|
||||
controller.set_eventstate(True)
|
||||
self.assertTrue(controller.get_eventstate())
|
||||
|
||||
controller.set_eventstate(False)
|
||||
self.assertFalse(controller.get_eventstate())
|
||||
|
||||
controller.set_eventstate(True)
|
||||
|
||||
def test_get_count(self):
|
||||
self.assertGreaterEqual(controller.get_count(), 0)
|
||||
|
||||
def test_is_controller(self):
|
||||
for i in range(controller.get_count()):
|
||||
if controller.is_controller(i):
|
||||
c = controller.Controller(i)
|
||||
self.assertIsInstance(c, controller.Controller)
|
||||
c.quit()
|
||||
else:
|
||||
with self.assertRaises(pygame._sdl2.sdl2.error):
|
||||
c = controller.Controller(i)
|
||||
|
||||
with self.assertRaises(TypeError):
|
||||
controller.is_controller("Test")
|
||||
|
||||
def test_name_forindex(self):
|
||||
self.assertIsNone(controller.name_forindex(-1))
|
||||
|
||||
|
||||
class ControllerTypeTest(unittest.TestCase):
|
||||
def setUp(self):
|
||||
controller.init()
|
||||
|
||||
def tearDown(self):
|
||||
controller.quit()
|
||||
|
||||
def _get_first_controller(self):
|
||||
for i in range(controller.get_count()):
|
||||
if controller.is_controller(i):
|
||||
return controller.Controller(i)
|
||||
|
||||
def test_construction(self):
|
||||
c = self._get_first_controller()
|
||||
if c:
|
||||
self.assertIsInstance(c, controller.Controller)
|
||||
else:
|
||||
self.skipTest("No controller connected")
|
||||
|
||||
def test__auto_init(self):
|
||||
c = self._get_first_controller()
|
||||
if c:
|
||||
self.assertTrue(c.get_init())
|
||||
else:
|
||||
self.skipTest("No controller connected")
|
||||
|
||||
def test_get_init(self):
|
||||
c = self._get_first_controller()
|
||||
if c:
|
||||
self.assertTrue(c.get_init())
|
||||
c.quit()
|
||||
self.assertFalse(c.get_init())
|
||||
else:
|
||||
self.skipTest("No controller connected")
|
||||
|
||||
def test_from_joystick(self):
|
||||
for i in range(controller.get_count()):
|
||||
if controller.is_controller(i):
|
||||
joy = pygame.joystick.Joystick(i)
|
||||
break
|
||||
else:
|
||||
self.skipTest("No controller connected")
|
||||
|
||||
c = controller.Controller.from_joystick(joy)
|
||||
self.assertIsInstance(c, controller.Controller)
|
||||
|
||||
def test_as_joystick(self):
|
||||
c = self._get_first_controller()
|
||||
if c:
|
||||
joy = c.as_joystick()
|
||||
self.assertIsInstance(joy, type(pygame.joystick.Joystick(0)))
|
||||
else:
|
||||
self.skipTest("No controller connected")
|
||||
|
||||
def test_get_mapping(self):
|
||||
c = self._get_first_controller()
|
||||
if c:
|
||||
mapping = c.get_mapping()
|
||||
self.assertIsInstance(mapping, dict)
|
||||
self.assertIsNotNone(mapping["a"])
|
||||
else:
|
||||
self.skipTest("No controller connected")
|
||||
|
||||
def test_set_mapping(self):
|
||||
c = self._get_first_controller()
|
||||
if c:
|
||||
mapping = c.get_mapping()
|
||||
mapping["a"] = "b3"
|
||||
mapping["y"] = "b0"
|
||||
c.set_mapping(mapping)
|
||||
new_mapping = c.get_mapping()
|
||||
|
||||
self.assertEqual(len(mapping), len(new_mapping))
|
||||
for i in mapping:
|
||||
if mapping[i] not in ("a", "y"):
|
||||
self.assertEqual(mapping[i], new_mapping[i])
|
||||
else:
|
||||
if i == "a":
|
||||
self.assertEqual(new_mapping[i], mapping["y"])
|
||||
else:
|
||||
self.assertEqual(new_mapping[i], mapping["a"])
|
||||
else:
|
||||
self.skipTest("No controller connected")
|
||||
|
||||
|
||||
class ControllerInteractiveTest(unittest.TestCase):
|
||||
__tags__ = ["interactive"]
|
||||
|
||||
def _get_first_controller(self):
|
||||
for i in range(controller.get_count()):
|
||||
if controller.is_controller(i):
|
||||
return controller.Controller(i)
|
||||
|
||||
def setUp(self):
|
||||
controller.init()
|
||||
|
||||
def tearDown(self):
|
||||
controller.quit()
|
||||
|
||||
def test__get_count_interactive(self):
|
||||
prompt(
|
||||
"Please connect at least one controller "
|
||||
"before the test for controller.get_count() starts"
|
||||
)
|
||||
|
||||
# Reset the number of joysticks counted
|
||||
controller.quit()
|
||||
controller.init()
|
||||
|
||||
joystick_num = controller.get_count()
|
||||
ans = question(
|
||||
"get_count() thinks there are {} joysticks "
|
||||
"connected. Is that correct?".format(joystick_num)
|
||||
)
|
||||
|
||||
self.assertTrue(ans)
|
||||
|
||||
def test_set_eventstate_on_interactive(self):
|
||||
c = self._get_first_controller()
|
||||
if not c:
|
||||
self.skipTest("No controller connected")
|
||||
|
||||
pygame.display.init()
|
||||
pygame.font.init()
|
||||
|
||||
screen = pygame.display.set_mode((400, 400))
|
||||
font = pygame.font.Font(None, 20)
|
||||
running = True
|
||||
|
||||
screen.fill((255, 255, 255))
|
||||
screen.blit(
|
||||
font.render("Press button 'x' (on ps4) or 'a' (on xbox).", True, (0, 0, 0)),
|
||||
(0, 0),
|
||||
)
|
||||
pygame.display.update()
|
||||
|
||||
controller.set_eventstate(True)
|
||||
|
||||
while running:
|
||||
for event in pygame.event.get():
|
||||
if event.type == pygame.QUIT:
|
||||
running = False
|
||||
|
||||
if event.type == pygame.CONTROLLERBUTTONDOWN:
|
||||
running = False
|
||||
|
||||
pygame.display.quit()
|
||||
pygame.font.quit()
|
||||
|
||||
def test_set_eventstate_off_interactive(self):
|
||||
c = self._get_first_controller()
|
||||
if not c:
|
||||
self.skipTest("No controller connected")
|
||||
|
||||
pygame.display.init()
|
||||
pygame.font.init()
|
||||
|
||||
screen = pygame.display.set_mode((400, 400))
|
||||
font = pygame.font.Font(None, 20)
|
||||
running = True
|
||||
|
||||
screen.fill((255, 255, 255))
|
||||
screen.blit(
|
||||
font.render("Press button 'x' (on ps4) or 'a' (on xbox).", True, (0, 0, 0)),
|
||||
(0, 0),
|
||||
)
|
||||
pygame.display.update()
|
||||
|
||||
controller.set_eventstate(False)
|
||||
|
||||
while running:
|
||||
for event in pygame.event.get(pygame.QUIT):
|
||||
if event:
|
||||
running = False
|
||||
|
||||
if c.get_button(pygame.CONTROLLER_BUTTON_A):
|
||||
if pygame.event.peek(pygame.CONTROLLERBUTTONDOWN):
|
||||
pygame.display.quit()
|
||||
pygame.font.quit()
|
||||
self.fail()
|
||||
else:
|
||||
running = False
|
||||
|
||||
pygame.display.quit()
|
||||
pygame.font.quit()
|
||||
|
||||
def test_get_button_interactive(self):
|
||||
c = self._get_first_controller()
|
||||
if not c:
|
||||
self.skipTest("No controller connected")
|
||||
|
||||
pygame.display.init()
|
||||
pygame.font.init()
|
||||
|
||||
screen = pygame.display.set_mode((400, 400))
|
||||
font = pygame.font.Font(None, 20)
|
||||
running = True
|
||||
|
||||
label1 = font.render(
|
||||
"Press button 'x' (on ps4) or 'a' (on xbox).", True, (0, 0, 0)
|
||||
)
|
||||
|
||||
label2 = font.render(
|
||||
'The two values should match up. Press "y" or "n" to confirm.',
|
||||
True,
|
||||
(0, 0, 0),
|
||||
)
|
||||
|
||||
is_pressed = [False, False] # event, get_button()
|
||||
while running:
|
||||
for event in pygame.event.get():
|
||||
if event.type == pygame.QUIT:
|
||||
running = False
|
||||
if event.type == pygame.CONTROLLERBUTTONDOWN and event.button == 0:
|
||||
is_pressed[0] = True
|
||||
if event.type == pygame.CONTROLLERBUTTONUP and event.button == 0:
|
||||
is_pressed[0] = False
|
||||
|
||||
if event.type == pygame.KEYDOWN:
|
||||
if event.key == pygame.K_y:
|
||||
running = False
|
||||
if event.key == pygame.K_n:
|
||||
running = False
|
||||
pygame.display.quit()
|
||||
pygame.font.quit()
|
||||
self.fail()
|
||||
|
||||
is_pressed[1] = c.get_button(pygame.CONTROLLER_BUTTON_A)
|
||||
|
||||
screen.fill((255, 255, 255))
|
||||
screen.blit(label1, (0, 0))
|
||||
screen.blit(label2, (0, 20))
|
||||
screen.blit(font.render(str(is_pressed), True, (0, 0, 0)), (0, 40))
|
||||
pygame.display.update()
|
||||
|
||||
pygame.display.quit()
|
||||
pygame.font.quit()
|
||||
|
||||
def test_get_axis_interactive(self):
|
||||
c = self._get_first_controller()
|
||||
if not c:
|
||||
self.skipTest("No controller connected")
|
||||
|
||||
pygame.display.init()
|
||||
pygame.font.init()
|
||||
|
||||
screen = pygame.display.set_mode((400, 400))
|
||||
font = pygame.font.Font(None, 20)
|
||||
running = True
|
||||
|
||||
label1 = font.render(
|
||||
"Press down the right trigger. The value on-screen should", True, (0, 0, 0)
|
||||
)
|
||||
|
||||
label2 = font.render(
|
||||
"indicate how far the trigger is pressed down. This value should",
|
||||
True,
|
||||
(0, 0, 0),
|
||||
)
|
||||
|
||||
label3 = font.render(
|
||||
'be in the range of 0-32767. Press "y" or "n" to confirm.', True, (0, 0, 0)
|
||||
)
|
||||
|
||||
while running:
|
||||
for event in pygame.event.get():
|
||||
if event.type == pygame.QUIT:
|
||||
running = False
|
||||
|
||||
if event.type == pygame.KEYDOWN:
|
||||
if event.key == pygame.K_y:
|
||||
running = False
|
||||
if event.key == pygame.K_n:
|
||||
running = False
|
||||
pygame.display.quit()
|
||||
pygame.font.quit()
|
||||
self.fail()
|
||||
|
||||
right_trigger = c.get_axis(pygame.CONTROLLER_AXIS_TRIGGERRIGHT)
|
||||
|
||||
screen.fill((255, 255, 255))
|
||||
screen.blit(label1, (0, 0))
|
||||
screen.blit(label2, (0, 20))
|
||||
screen.blit(label3, (0, 40))
|
||||
screen.blit(font.render(str(right_trigger), True, (0, 0, 0)), (0, 60))
|
||||
pygame.display.update()
|
||||
|
||||
pygame.display.quit()
|
||||
pygame.font.quit()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
290
.venv/lib/python3.7/site-packages/pygame/tests/cursors_test.py
Normal file
290
.venv/lib/python3.7/site-packages/pygame/tests/cursors_test.py
Normal file
@@ -0,0 +1,290 @@
|
||||
import unittest
|
||||
from pygame.tests.test_utils import fixture_path
|
||||
import pygame
|
||||
|
||||
|
||||
class CursorsModuleTest(unittest.TestCase):
|
||||
def test_compile(self):
|
||||
# __doc__ (as of 2008-06-25) for pygame.cursors.compile:
|
||||
|
||||
# pygame.cursors.compile(strings, black, white,xor) -> data, mask
|
||||
# compile cursor strings into cursor data
|
||||
#
|
||||
# This takes a set of strings with equal length and computes
|
||||
# the binary data for that cursor. The string widths must be
|
||||
# divisible by 8.
|
||||
#
|
||||
# The black and white arguments are single letter strings that
|
||||
# tells which characters will represent black pixels, and which
|
||||
# characters represent white pixels. All other characters are
|
||||
# considered clear.
|
||||
#
|
||||
# This returns a tuple containing the cursor data and cursor mask
|
||||
# data. Both these arguments are used when setting a cursor with
|
||||
# pygame.mouse.set_cursor().
|
||||
|
||||
# Various types of input strings
|
||||
test_cursor1 = ("X.X.XXXX", "XXXXXX..", " XXXX ")
|
||||
|
||||
test_cursor2 = (
|
||||
"X.X.XXXX",
|
||||
"XXXXXX..",
|
||||
"XXXXXX ",
|
||||
"XXXXXX..",
|
||||
"XXXXXX..",
|
||||
"XXXXXX",
|
||||
"XXXXXX..",
|
||||
"XXXXXX..",
|
||||
)
|
||||
test_cursor3 = (".XX.", " ", ".. ", "X.. X")
|
||||
|
||||
# Test such that total number of strings is not divisible by 8
|
||||
with self.assertRaises(ValueError):
|
||||
pygame.cursors.compile(test_cursor1)
|
||||
|
||||
# Test such that size of individual string is not divisible by 8
|
||||
with self.assertRaises(ValueError):
|
||||
pygame.cursors.compile(test_cursor2)
|
||||
|
||||
# Test such that neither size of individual string nor total number of strings is divisible by 8
|
||||
with self.assertRaises(ValueError):
|
||||
pygame.cursors.compile(test_cursor3)
|
||||
|
||||
# Test that checks whether the byte data from compile function is equal to actual byte data
|
||||
actual_byte_data = (
|
||||
192,
|
||||
0,
|
||||
0,
|
||||
224,
|
||||
0,
|
||||
0,
|
||||
240,
|
||||
0,
|
||||
0,
|
||||
216,
|
||||
0,
|
||||
0,
|
||||
204,
|
||||
0,
|
||||
0,
|
||||
198,
|
||||
0,
|
||||
0,
|
||||
195,
|
||||
0,
|
||||
0,
|
||||
193,
|
||||
128,
|
||||
0,
|
||||
192,
|
||||
192,
|
||||
0,
|
||||
192,
|
||||
96,
|
||||
0,
|
||||
192,
|
||||
48,
|
||||
0,
|
||||
192,
|
||||
56,
|
||||
0,
|
||||
192,
|
||||
248,
|
||||
0,
|
||||
220,
|
||||
192,
|
||||
0,
|
||||
246,
|
||||
96,
|
||||
0,
|
||||
198,
|
||||
96,
|
||||
0,
|
||||
6,
|
||||
96,
|
||||
0,
|
||||
3,
|
||||
48,
|
||||
0,
|
||||
3,
|
||||
48,
|
||||
0,
|
||||
1,
|
||||
224,
|
||||
0,
|
||||
1,
|
||||
128,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
), (
|
||||
192,
|
||||
0,
|
||||
0,
|
||||
224,
|
||||
0,
|
||||
0,
|
||||
240,
|
||||
0,
|
||||
0,
|
||||
248,
|
||||
0,
|
||||
0,
|
||||
252,
|
||||
0,
|
||||
0,
|
||||
254,
|
||||
0,
|
||||
0,
|
||||
255,
|
||||
0,
|
||||
0,
|
||||
255,
|
||||
128,
|
||||
0,
|
||||
255,
|
||||
192,
|
||||
0,
|
||||
255,
|
||||
224,
|
||||
0,
|
||||
255,
|
||||
240,
|
||||
0,
|
||||
255,
|
||||
248,
|
||||
0,
|
||||
255,
|
||||
248,
|
||||
0,
|
||||
255,
|
||||
192,
|
||||
0,
|
||||
247,
|
||||
224,
|
||||
0,
|
||||
199,
|
||||
224,
|
||||
0,
|
||||
7,
|
||||
224,
|
||||
0,
|
||||
3,
|
||||
240,
|
||||
0,
|
||||
3,
|
||||
240,
|
||||
0,
|
||||
1,
|
||||
224,
|
||||
0,
|
||||
1,
|
||||
128,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
)
|
||||
|
||||
cursor = pygame.cursors.compile(pygame.cursors.thickarrow_strings)
|
||||
self.assertEqual(cursor, actual_byte_data)
|
||||
|
||||
# Test such that cursor byte data obtained from compile function is valid in pygame.mouse.set_cursor()
|
||||
pygame.display.init()
|
||||
try:
|
||||
pygame.mouse.set_cursor((24, 24), (0, 0), *cursor)
|
||||
except pygame.error as e:
|
||||
if "not currently supported" in str(e):
|
||||
unittest.skip("skipping test as set_cursor() is not supported")
|
||||
finally:
|
||||
pygame.display.quit()
|
||||
|
||||
################################################################################
|
||||
|
||||
def test_load_xbm(self):
|
||||
# __doc__ (as of 2008-06-25) for pygame.cursors.load_xbm:
|
||||
|
||||
# pygame.cursors.load_xbm(cursorfile, maskfile) -> cursor_args
|
||||
# reads a pair of XBM files into set_cursor arguments
|
||||
#
|
||||
# Arguments can either be filenames or filelike objects
|
||||
# with the readlines method. Not largely tested, but
|
||||
# should work with typical XBM files.
|
||||
|
||||
# Test that load_xbm will take filenames as arguments
|
||||
cursorfile = fixture_path(r"xbm_cursors/white_sizing.xbm")
|
||||
maskfile = fixture_path(r"xbm_cursors/white_sizing_mask.xbm")
|
||||
cursor = pygame.cursors.load_xbm(cursorfile, maskfile)
|
||||
|
||||
# Test that load_xbm will take file objects as arguments
|
||||
with open(cursorfile) as cursor_f, open(maskfile) as mask_f:
|
||||
cursor = pygame.cursors.load_xbm(cursor_f, mask_f)
|
||||
|
||||
# Can it load using pathlib.Path?
|
||||
import pathlib
|
||||
|
||||
cursor = pygame.cursors.load_xbm(
|
||||
pathlib.Path(cursorfile), pathlib.Path(maskfile)
|
||||
)
|
||||
|
||||
# Is it in a format that mouse.set_cursor won't blow up on?
|
||||
pygame.display.init()
|
||||
try:
|
||||
pygame.mouse.set_cursor(*cursor)
|
||||
except pygame.error as e:
|
||||
if "not currently supported" in str(e):
|
||||
unittest.skip("skipping test as set_cursor() is not supported")
|
||||
finally:
|
||||
pygame.display.quit()
|
||||
|
||||
def test_Cursor(self):
|
||||
"""Ensure that the cursor object parses information properly"""
|
||||
|
||||
c1 = pygame.cursors.Cursor(pygame.SYSTEM_CURSOR_CROSSHAIR)
|
||||
|
||||
self.assertEqual(c1.data, (pygame.SYSTEM_CURSOR_CROSSHAIR,))
|
||||
self.assertEqual(c1.type, "system")
|
||||
|
||||
c2 = pygame.cursors.Cursor(c1)
|
||||
|
||||
self.assertEqual(c1, c2)
|
||||
|
||||
with self.assertRaises(TypeError):
|
||||
pygame.cursors.Cursor(-34002)
|
||||
with self.assertRaises(TypeError):
|
||||
pygame.cursors.Cursor("a", "b", "c", "d")
|
||||
with self.assertRaises(TypeError):
|
||||
pygame.cursors.Cursor((2,))
|
||||
|
||||
c3 = pygame.cursors.Cursor((0, 0), pygame.Surface((20, 20)))
|
||||
|
||||
self.assertEqual(c3.data[0], (0, 0))
|
||||
self.assertEqual(c3.data[1].get_size(), (20, 20))
|
||||
self.assertEqual(c3.type, "color")
|
||||
|
||||
xormask, andmask = pygame.cursors.compile(pygame.cursors.thickarrow_strings)
|
||||
c4 = pygame.cursors.Cursor((24, 24), (0, 0), xormask, andmask)
|
||||
|
||||
self.assertEqual(c4.data, ((24, 24), (0, 0), xormask, andmask))
|
||||
self.assertEqual(c4.type, "bitmap")
|
||||
|
||||
|
||||
################################################################################
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
||||
################################################################################
|
1199
.venv/lib/python3.7/site-packages/pygame/tests/display_test.py
Normal file
1199
.venv/lib/python3.7/site-packages/pygame/tests/display_test.py
Normal file
File diff suppressed because it is too large
Load Diff
35
.venv/lib/python3.7/site-packages/pygame/tests/docs_test.py
Normal file
35
.venv/lib/python3.7/site-packages/pygame/tests/docs_test.py
Normal file
@@ -0,0 +1,35 @@
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
import unittest
|
||||
|
||||
|
||||
class DocsIncludedTest(unittest.TestCase):
|
||||
def test_doc_import_works(self):
|
||||
from pygame.docs.__main__ import has_local_docs, open_docs
|
||||
|
||||
@unittest.skipIf("CI" not in os.environ, "Docs not required for local builds")
|
||||
def test_docs_included(self):
|
||||
from pygame.docs.__main__ import has_local_docs
|
||||
|
||||
self.assertTrue(has_local_docs())
|
||||
|
||||
@unittest.skipIf("CI" not in os.environ, "Docs not required for local builds")
|
||||
def test_docs_command(self):
|
||||
try:
|
||||
subprocess.run(
|
||||
[sys.executable, "-m", "pygame.docs"],
|
||||
timeout=5,
|
||||
# check ensures an exception is raised when the process fails
|
||||
check=True,
|
||||
# pipe stdout/stderr so that they don't clutter main stdout
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE,
|
||||
)
|
||||
except subprocess.TimeoutExpired:
|
||||
# timeout errors are not an issue
|
||||
pass
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
6508
.venv/lib/python3.7/site-packages/pygame/tests/draw_test.py
Normal file
6508
.venv/lib/python3.7/site-packages/pygame/tests/draw_test.py
Normal file
File diff suppressed because it is too large
Load Diff
949
.venv/lib/python3.7/site-packages/pygame/tests/event_test.py
Normal file
949
.venv/lib/python3.7/site-packages/pygame/tests/event_test.py
Normal file
@@ -0,0 +1,949 @@
|
||||
import collections
|
||||
import time
|
||||
import unittest
|
||||
import os
|
||||
|
||||
import pygame
|
||||
|
||||
EVENT_TYPES = (
|
||||
# pygame.NOEVENT,
|
||||
# pygame.ACTIVEEVENT,
|
||||
pygame.KEYDOWN,
|
||||
pygame.KEYUP,
|
||||
pygame.MOUSEMOTION,
|
||||
pygame.MOUSEBUTTONDOWN,
|
||||
pygame.MOUSEBUTTONUP,
|
||||
pygame.JOYAXISMOTION,
|
||||
pygame.JOYBALLMOTION,
|
||||
pygame.JOYHATMOTION,
|
||||
pygame.JOYBUTTONDOWN,
|
||||
pygame.JOYBUTTONUP,
|
||||
pygame.VIDEORESIZE,
|
||||
pygame.VIDEOEXPOSE,
|
||||
pygame.QUIT,
|
||||
pygame.SYSWMEVENT,
|
||||
pygame.USEREVENT,
|
||||
# pygame.NUMEVENTS,
|
||||
)
|
||||
|
||||
EVENT_TEST_PARAMS = collections.defaultdict(dict)
|
||||
EVENT_TEST_PARAMS.update(
|
||||
{
|
||||
pygame.KEYDOWN: {"key": pygame.K_SPACE},
|
||||
pygame.KEYUP: {"key": pygame.K_SPACE},
|
||||
pygame.MOUSEMOTION: dict(),
|
||||
pygame.MOUSEBUTTONDOWN: dict(button=1),
|
||||
pygame.MOUSEBUTTONUP: dict(button=1),
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
NAMES_AND_EVENTS = (
|
||||
("NoEvent", pygame.NOEVENT),
|
||||
("ActiveEvent", pygame.ACTIVEEVENT),
|
||||
("KeyDown", pygame.KEYDOWN),
|
||||
("KeyUp", pygame.KEYUP),
|
||||
("MouseMotion", pygame.MOUSEMOTION),
|
||||
("MouseButtonDown", pygame.MOUSEBUTTONDOWN),
|
||||
("MouseButtonUp", pygame.MOUSEBUTTONUP),
|
||||
("JoyAxisMotion", pygame.JOYAXISMOTION),
|
||||
("JoyBallMotion", pygame.JOYBALLMOTION),
|
||||
("JoyHatMotion", pygame.JOYHATMOTION),
|
||||
("JoyButtonDown", pygame.JOYBUTTONDOWN),
|
||||
("JoyButtonUp", pygame.JOYBUTTONUP),
|
||||
("VideoResize", pygame.VIDEORESIZE),
|
||||
("VideoExpose", pygame.VIDEOEXPOSE),
|
||||
("Quit", pygame.QUIT),
|
||||
("SysWMEvent", pygame.SYSWMEVENT),
|
||||
("MidiIn", pygame.MIDIIN),
|
||||
("MidiOut", pygame.MIDIOUT),
|
||||
("UserEvent", pygame.USEREVENT),
|
||||
("Unknown", 0xFFFF),
|
||||
("FingerMotion", pygame.FINGERMOTION),
|
||||
("FingerDown", pygame.FINGERDOWN),
|
||||
("FingerUp", pygame.FINGERUP),
|
||||
("MultiGesture", pygame.MULTIGESTURE),
|
||||
("MouseWheel", pygame.MOUSEWHEEL),
|
||||
("TextInput", pygame.TEXTINPUT),
|
||||
("TextEditing", pygame.TEXTEDITING),
|
||||
("ControllerAxisMotion", pygame.CONTROLLERAXISMOTION),
|
||||
("ControllerButtonDown", pygame.CONTROLLERBUTTONDOWN),
|
||||
("ControllerButtonUp", pygame.CONTROLLERBUTTONUP),
|
||||
("ControllerDeviceAdded", pygame.CONTROLLERDEVICEADDED),
|
||||
("ControllerDeviceRemoved", pygame.CONTROLLERDEVICEREMOVED),
|
||||
("ControllerDeviceMapped", pygame.CONTROLLERDEVICEREMAPPED),
|
||||
("DropFile", pygame.DROPFILE),
|
||||
("AudioDeviceAdded", pygame.AUDIODEVICEADDED),
|
||||
("AudioDeviceRemoved", pygame.AUDIODEVICEREMOVED),
|
||||
("DropText", pygame.DROPTEXT),
|
||||
("DropBegin", pygame.DROPBEGIN),
|
||||
("DropComplete", pygame.DROPCOMPLETE),
|
||||
)
|
||||
|
||||
|
||||
class EventTypeTest(unittest.TestCase):
|
||||
def test_Event(self):
|
||||
"""Ensure an Event object can be created."""
|
||||
e = pygame.event.Event(pygame.USEREVENT, some_attr=1, other_attr="1")
|
||||
|
||||
self.assertEqual(e.some_attr, 1)
|
||||
self.assertEqual(e.other_attr, "1")
|
||||
|
||||
# Event now uses tp_dictoffset and tp_members:
|
||||
# https://github.com/pygame/pygame/issues/62
|
||||
self.assertEqual(e.type, pygame.USEREVENT)
|
||||
self.assertIs(e.dict, e.__dict__)
|
||||
|
||||
e.some_attr = 12
|
||||
|
||||
self.assertEqual(e.some_attr, 12)
|
||||
|
||||
e.new_attr = 15
|
||||
|
||||
self.assertEqual(e.new_attr, 15)
|
||||
|
||||
self.assertRaises(AttributeError, setattr, e, "type", 0)
|
||||
self.assertRaises(AttributeError, setattr, e, "dict", None)
|
||||
|
||||
# Ensure attributes are visible to dir(), part of the original
|
||||
# posted request.
|
||||
d = dir(e)
|
||||
attrs = ("type", "dict", "__dict__", "some_attr", "other_attr", "new_attr")
|
||||
|
||||
for attr in attrs:
|
||||
self.assertIn(attr, d)
|
||||
|
||||
# redundant type field as kwarg
|
||||
self.assertRaises(ValueError, pygame.event.Event, 10, type=100)
|
||||
|
||||
def test_as_str(self):
|
||||
# Bug reported on Pygame mailing list July 24, 2011:
|
||||
# For Python 3.x str(event) to raises an UnicodeEncodeError when
|
||||
# an event attribute is a string with a non-ascii character.
|
||||
try:
|
||||
str(pygame.event.Event(EVENT_TYPES[0], a="\xed"))
|
||||
except UnicodeEncodeError:
|
||||
self.fail("Event object raised exception for non-ascii character")
|
||||
# Passed.
|
||||
|
||||
def test_event_bool(self):
|
||||
self.assertFalse(pygame.event.Event(pygame.NOEVENT))
|
||||
for event_type in [
|
||||
pygame.MOUSEBUTTONDOWN,
|
||||
pygame.ACTIVEEVENT,
|
||||
pygame.WINDOWLEAVE,
|
||||
pygame.USEREVENT_DROPFILE,
|
||||
]:
|
||||
self.assertTrue(pygame.event.Event(event_type))
|
||||
|
||||
def test_event_equality(self):
|
||||
"""Ensure that events can be compared correctly."""
|
||||
a = pygame.event.Event(EVENT_TYPES[0], a=1)
|
||||
b = pygame.event.Event(EVENT_TYPES[0], a=1)
|
||||
c = pygame.event.Event(EVENT_TYPES[1], a=1)
|
||||
d = pygame.event.Event(EVENT_TYPES[0], a=2)
|
||||
|
||||
self.assertTrue(a == a)
|
||||
self.assertFalse(a != a)
|
||||
self.assertTrue(a == b)
|
||||
self.assertFalse(a != b)
|
||||
self.assertTrue(a != c)
|
||||
self.assertFalse(a == c)
|
||||
self.assertTrue(a != d)
|
||||
self.assertFalse(a == d)
|
||||
|
||||
|
||||
race_condition_notification = """
|
||||
This test is dependent on timing. The event queue is cleared in preparation for
|
||||
tests. There is a small window where outside events from the OS may have effected
|
||||
results. Try running the test again.
|
||||
"""
|
||||
|
||||
|
||||
class EventModuleArgsTest(unittest.TestCase):
|
||||
def setUp(self):
|
||||
pygame.display.init()
|
||||
pygame.event.clear()
|
||||
|
||||
def tearDown(self):
|
||||
pygame.display.quit()
|
||||
|
||||
def test_get(self):
|
||||
pygame.event.get()
|
||||
pygame.event.get(None)
|
||||
pygame.event.get(None, True)
|
||||
|
||||
pygame.event.get(pump=False)
|
||||
pygame.event.get(pump=True)
|
||||
pygame.event.get(eventtype=None)
|
||||
pygame.event.get(eventtype=[pygame.KEYUP, pygame.KEYDOWN])
|
||||
pygame.event.get(eventtype=pygame.USEREVENT, pump=False)
|
||||
|
||||
# event type out of range
|
||||
self.assertRaises(ValueError, pygame.event.get, 0x00010000)
|
||||
self.assertRaises(TypeError, pygame.event.get, 1 + 2j)
|
||||
self.assertRaises(TypeError, pygame.event.get, "foo")
|
||||
|
||||
def test_clear(self):
|
||||
pygame.event.clear()
|
||||
pygame.event.clear(None)
|
||||
pygame.event.clear(None, True)
|
||||
|
||||
pygame.event.clear(pump=False)
|
||||
pygame.event.clear(pump=True)
|
||||
pygame.event.clear(eventtype=None)
|
||||
pygame.event.clear(eventtype=[pygame.KEYUP, pygame.KEYDOWN])
|
||||
pygame.event.clear(eventtype=pygame.USEREVENT, pump=False)
|
||||
|
||||
# event type out of range
|
||||
self.assertRaises(ValueError, pygame.event.clear, 0x0010FFFFF)
|
||||
self.assertRaises(TypeError, pygame.event.get, ["a", "b", "c"])
|
||||
|
||||
def test_peek(self):
|
||||
pygame.event.peek()
|
||||
pygame.event.peek(None)
|
||||
pygame.event.peek(None, True)
|
||||
|
||||
pygame.event.peek(pump=False)
|
||||
pygame.event.peek(pump=True)
|
||||
pygame.event.peek(eventtype=None)
|
||||
pygame.event.peek(eventtype=[pygame.KEYUP, pygame.KEYDOWN])
|
||||
pygame.event.peek(eventtype=pygame.USEREVENT, pump=False)
|
||||
|
||||
class Foo:
|
||||
pass
|
||||
|
||||
# event type out of range
|
||||
self.assertRaises(ValueError, pygame.event.peek, -1)
|
||||
self.assertRaises(ValueError, pygame.event.peek, [-10])
|
||||
self.assertRaises(TypeError, pygame.event.peek, Foo())
|
||||
|
||||
|
||||
class EventCustomTypeTest(unittest.TestCase):
|
||||
"""Those tests are special in that they need the _custom_event counter to
|
||||
be reset before and/or after being run."""
|
||||
|
||||
def setUp(self):
|
||||
pygame.quit()
|
||||
pygame.init()
|
||||
pygame.display.init()
|
||||
|
||||
def tearDown(self):
|
||||
pygame.quit()
|
||||
|
||||
def test_custom_type(self):
|
||||
self.assertEqual(pygame.event.custom_type(), pygame.USEREVENT + 1)
|
||||
atype = pygame.event.custom_type()
|
||||
atype2 = pygame.event.custom_type()
|
||||
|
||||
self.assertEqual(atype, atype2 - 1)
|
||||
|
||||
ev = pygame.event.Event(atype)
|
||||
pygame.event.post(ev)
|
||||
queue = pygame.event.get(atype)
|
||||
self.assertEqual(len(queue), 1)
|
||||
self.assertEqual(queue[0].type, atype)
|
||||
|
||||
def test_custom_type__end_boundary(self):
|
||||
"""Ensure custom_type() raises error when no more custom types.
|
||||
|
||||
The last allowed custom type number should be (pygame.NUMEVENTS - 1).
|
||||
"""
|
||||
last = -1
|
||||
start = pygame.event.custom_type() + 1
|
||||
for _ in range(start, pygame.NUMEVENTS):
|
||||
last = pygame.event.custom_type()
|
||||
|
||||
self.assertEqual(last, pygame.NUMEVENTS - 1)
|
||||
with self.assertRaises(pygame.error):
|
||||
pygame.event.custom_type()
|
||||
|
||||
def test_custom_type__reset(self):
|
||||
"""Ensure custom events get 'deregistered' by quit()."""
|
||||
before = pygame.event.custom_type()
|
||||
self.assertEqual(before, pygame.event.custom_type() - 1)
|
||||
pygame.quit()
|
||||
pygame.init()
|
||||
pygame.display.init()
|
||||
self.assertEqual(before, pygame.event.custom_type())
|
||||
|
||||
|
||||
class EventModuleTest(unittest.TestCase):
|
||||
def _assertCountEqual(self, *args, **kwargs):
|
||||
# Handle method name differences between Python versions.
|
||||
# Is this still needed?
|
||||
self.assertCountEqual(*args, **kwargs)
|
||||
|
||||
def _assertExpectedEvents(self, expected, got):
|
||||
"""Find events like expected events, raise on unexpected or missing,
|
||||
ignore additional event properties if expected properties are present."""
|
||||
|
||||
# This does greedy matching, don't encode an NP-hard problem
|
||||
# into your input data, *please*
|
||||
items_left = got[:]
|
||||
for expected_element in expected:
|
||||
for item in items_left:
|
||||
for key in expected_element.__dict__:
|
||||
if item.__dict__[key] != expected_element.__dict__[key]:
|
||||
break
|
||||
else:
|
||||
# found item!
|
||||
items_left.remove(item)
|
||||
break
|
||||
else:
|
||||
raise AssertionError(
|
||||
"Expected "
|
||||
+ str(expected_element)
|
||||
+ " among remaining events "
|
||||
+ str(items_left)
|
||||
+ " out of "
|
||||
+ str(got)
|
||||
)
|
||||
if len(items_left) > 0:
|
||||
raise AssertionError("Unexpected Events: " + str(items_left))
|
||||
|
||||
def setUp(self):
|
||||
pygame.display.init()
|
||||
pygame.event.clear() # flush events
|
||||
|
||||
def tearDown(self):
|
||||
pygame.event.clear() # flush events
|
||||
pygame.display.quit()
|
||||
|
||||
def test_event_numevents(self):
|
||||
"""Ensures NUMEVENTS does not exceed the maximum SDL number of events."""
|
||||
# Ref: https://www.libsdl.org/tmp/SDL/include/SDL_events.h
|
||||
MAX_SDL_EVENTS = 0xFFFF # SDL_LASTEVENT = 0xFFFF
|
||||
|
||||
self.assertLessEqual(pygame.NUMEVENTS, MAX_SDL_EVENTS)
|
||||
|
||||
def test_event_attribute(self):
|
||||
e1 = pygame.event.Event(pygame.USEREVENT, attr1="attr1")
|
||||
self.assertEqual(e1.attr1, "attr1")
|
||||
|
||||
def test_set_blocked(self):
|
||||
"""Ensure events can be blocked from the queue."""
|
||||
event = EVENT_TYPES[0]
|
||||
unblocked_event = EVENT_TYPES[1]
|
||||
pygame.event.set_blocked(event)
|
||||
|
||||
self.assertTrue(pygame.event.get_blocked(event))
|
||||
self.assertFalse(pygame.event.get_blocked(unblocked_event))
|
||||
|
||||
posted = pygame.event.post(
|
||||
pygame.event.Event(event, **EVENT_TEST_PARAMS[event])
|
||||
)
|
||||
self.assertFalse(posted)
|
||||
|
||||
# post an unblocked event
|
||||
posted = pygame.event.post(
|
||||
pygame.event.Event(unblocked_event, **EVENT_TEST_PARAMS[unblocked_event])
|
||||
)
|
||||
self.assertTrue(posted)
|
||||
|
||||
ret = pygame.event.get()
|
||||
should_be_blocked = [e for e in ret if e.type == event]
|
||||
should_be_allowed_types = [e.type for e in ret if e.type != event]
|
||||
|
||||
self.assertEqual(should_be_blocked, [])
|
||||
self.assertTrue(unblocked_event in should_be_allowed_types)
|
||||
|
||||
def test_set_blocked__event_sequence(self):
|
||||
"""Ensure a sequence of event types can be blocked."""
|
||||
event_types = [
|
||||
pygame.KEYDOWN,
|
||||
pygame.KEYUP,
|
||||
pygame.MOUSEMOTION,
|
||||
pygame.MOUSEBUTTONDOWN,
|
||||
pygame.MOUSEBUTTONUP,
|
||||
pygame.WINDOWFOCUSLOST,
|
||||
pygame.USEREVENT,
|
||||
]
|
||||
|
||||
pygame.event.set_blocked(event_types)
|
||||
|
||||
for etype in event_types:
|
||||
self.assertTrue(pygame.event.get_blocked(etype))
|
||||
|
||||
def test_set_blocked_all(self):
|
||||
"""Ensure all events can be unblocked at once."""
|
||||
pygame.event.set_blocked(None)
|
||||
|
||||
for e in EVENT_TYPES:
|
||||
self.assertTrue(pygame.event.get_blocked(e))
|
||||
|
||||
def test_post__and_poll(self):
|
||||
"""Ensure events can be posted to the queue."""
|
||||
e1 = pygame.event.Event(pygame.USEREVENT, attr1="attr1")
|
||||
pygame.event.post(e1)
|
||||
posted_event = pygame.event.poll()
|
||||
|
||||
self.assertEqual(e1.attr1, posted_event.attr1, race_condition_notification)
|
||||
|
||||
# fuzzing event types
|
||||
for i in range(1, 13):
|
||||
pygame.event.post(
|
||||
pygame.event.Event(EVENT_TYPES[i], **EVENT_TEST_PARAMS[EVENT_TYPES[i]])
|
||||
)
|
||||
|
||||
self.assertEqual(
|
||||
pygame.event.poll().type, EVENT_TYPES[i], race_condition_notification
|
||||
)
|
||||
|
||||
def test_post_and_get_keydown(self):
|
||||
"""Ensure keydown events can be posted to the queue."""
|
||||
activemodkeys = pygame.key.get_mods()
|
||||
|
||||
events = [
|
||||
pygame.event.Event(pygame.KEYDOWN, key=pygame.K_p),
|
||||
pygame.event.Event(pygame.KEYDOWN, key=pygame.K_y, mod=activemodkeys),
|
||||
pygame.event.Event(pygame.KEYDOWN, key=pygame.K_g, unicode="g"),
|
||||
pygame.event.Event(pygame.KEYDOWN, key=pygame.K_a, unicode=None),
|
||||
pygame.event.Event(pygame.KEYDOWN, key=pygame.K_m, mod=None, window=None),
|
||||
pygame.event.Event(
|
||||
pygame.KEYDOWN, key=pygame.K_e, mod=activemodkeys, unicode="e"
|
||||
),
|
||||
]
|
||||
|
||||
for e in events:
|
||||
pygame.event.post(e)
|
||||
posted_event = pygame.event.poll()
|
||||
self.assertEqual(e, posted_event, race_condition_notification)
|
||||
|
||||
def test_post_large_user_event(self):
|
||||
pygame.event.post(
|
||||
pygame.event.Event(
|
||||
pygame.USEREVENT, {"a": "a" * 1024}, test=list(range(100))
|
||||
)
|
||||
)
|
||||
e = pygame.event.poll()
|
||||
|
||||
self.assertEqual(e.type, pygame.USEREVENT)
|
||||
self.assertEqual(e.a, "a" * 1024)
|
||||
self.assertEqual(e.test, list(range(100)))
|
||||
|
||||
def test_post_blocked(self):
|
||||
"""
|
||||
Test blocked events are not posted. Also test whether post()
|
||||
returns a boolean correctly
|
||||
"""
|
||||
pygame.event.set_blocked(pygame.USEREVENT)
|
||||
self.assertFalse(pygame.event.post(pygame.event.Event(pygame.USEREVENT)))
|
||||
self.assertFalse(pygame.event.poll())
|
||||
pygame.event.set_allowed(pygame.USEREVENT)
|
||||
self.assertTrue(pygame.event.post(pygame.event.Event(pygame.USEREVENT)))
|
||||
self.assertEqual(pygame.event.poll(), pygame.event.Event(pygame.USEREVENT))
|
||||
|
||||
def test_get(self):
|
||||
"""Ensure get() retrieves all the events on the queue."""
|
||||
event_cnt = 10
|
||||
for _ in range(event_cnt):
|
||||
pygame.event.post(pygame.event.Event(pygame.USEREVENT))
|
||||
|
||||
queue = pygame.event.get()
|
||||
|
||||
self.assertEqual(len(queue), event_cnt)
|
||||
self.assertTrue(all(e.type == pygame.USEREVENT for e in queue))
|
||||
|
||||
def test_get_type(self):
|
||||
ev = pygame.event.Event(pygame.USEREVENT)
|
||||
pygame.event.post(ev)
|
||||
queue = pygame.event.get(pygame.USEREVENT)
|
||||
self.assertEqual(len(queue), 1)
|
||||
self.assertEqual(queue[0].type, pygame.USEREVENT)
|
||||
|
||||
TESTEVENTS = 10
|
||||
for _ in range(TESTEVENTS):
|
||||
pygame.event.post(ev)
|
||||
q = pygame.event.get([pygame.USEREVENT])
|
||||
self.assertEqual(len(q), TESTEVENTS)
|
||||
for event in q:
|
||||
self.assertEqual(event, ev)
|
||||
|
||||
def test_get_exclude_throw(self):
|
||||
self.assertRaises(
|
||||
pygame.error, pygame.event.get, pygame.KEYDOWN, False, pygame.KEYUP
|
||||
)
|
||||
|
||||
def test_get_exclude(self):
|
||||
pygame.event.post(pygame.event.Event(pygame.USEREVENT))
|
||||
pygame.event.post(pygame.event.Event(pygame.KEYDOWN))
|
||||
|
||||
queue = pygame.event.get(exclude=pygame.KEYDOWN)
|
||||
self.assertEqual(len(queue), 1)
|
||||
self.assertEqual(queue[0].type, pygame.USEREVENT)
|
||||
|
||||
pygame.event.post(pygame.event.Event(pygame.KEYUP))
|
||||
pygame.event.post(pygame.event.Event(pygame.USEREVENT))
|
||||
queue = pygame.event.get(exclude=(pygame.KEYDOWN, pygame.KEYUP))
|
||||
self.assertEqual(len(queue), 1)
|
||||
self.assertEqual(queue[0].type, pygame.USEREVENT)
|
||||
|
||||
queue = pygame.event.get()
|
||||
self.assertEqual(len(queue), 2)
|
||||
|
||||
def test_get__empty_queue(self):
|
||||
"""Ensure get() works correctly on an empty queue."""
|
||||
expected_events = []
|
||||
pygame.event.clear()
|
||||
|
||||
# Ensure all events can be checked.
|
||||
retrieved_events = pygame.event.get()
|
||||
|
||||
self.assertListEqual(retrieved_events, expected_events)
|
||||
|
||||
# Ensure events can be checked individually.
|
||||
for event_type in EVENT_TYPES:
|
||||
retrieved_events = pygame.event.get(event_type)
|
||||
|
||||
self.assertListEqual(retrieved_events, expected_events)
|
||||
|
||||
# Ensure events can be checked as a sequence.
|
||||
retrieved_events = pygame.event.get(EVENT_TYPES)
|
||||
|
||||
self.assertListEqual(retrieved_events, expected_events)
|
||||
|
||||
def test_get__event_sequence(self):
|
||||
"""Ensure get() can handle a sequence of event types."""
|
||||
event_types = [pygame.KEYDOWN, pygame.KEYUP, pygame.MOUSEMOTION]
|
||||
other_event_type = pygame.MOUSEBUTTONUP
|
||||
|
||||
# Test when no events in the queue.
|
||||
expected_events = []
|
||||
pygame.event.clear()
|
||||
retrieved_events = pygame.event.get(event_types)
|
||||
|
||||
# don't use self._assertCountEqual here. This checks for
|
||||
# expected properties in events, and ignores unexpected ones, for
|
||||
# forward compatibility with SDL2.
|
||||
self._assertExpectedEvents(expected=expected_events, got=retrieved_events)
|
||||
|
||||
# Test when an event type not in the list is in the queue.
|
||||
expected_events = []
|
||||
pygame.event.clear()
|
||||
pygame.event.post(
|
||||
pygame.event.Event(other_event_type, **EVENT_TEST_PARAMS[other_event_type])
|
||||
)
|
||||
|
||||
retrieved_events = pygame.event.get(event_types)
|
||||
|
||||
self._assertExpectedEvents(expected=expected_events, got=retrieved_events)
|
||||
|
||||
# Test when 1 event type in the list is in the queue.
|
||||
expected_events = [
|
||||
pygame.event.Event(event_types[0], **EVENT_TEST_PARAMS[event_types[0]])
|
||||
]
|
||||
pygame.event.clear()
|
||||
pygame.event.post(expected_events[0])
|
||||
|
||||
retrieved_events = pygame.event.get(event_types)
|
||||
|
||||
self._assertExpectedEvents(expected=expected_events, got=retrieved_events)
|
||||
|
||||
# Test all events in the list are in the queue.
|
||||
pygame.event.clear()
|
||||
expected_events = []
|
||||
|
||||
for etype in event_types:
|
||||
expected_events.append(
|
||||
pygame.event.Event(etype, **EVENT_TEST_PARAMS[etype])
|
||||
)
|
||||
pygame.event.post(expected_events[-1])
|
||||
|
||||
retrieved_events = pygame.event.get(event_types)
|
||||
|
||||
self._assertExpectedEvents(expected=expected_events, got=retrieved_events)
|
||||
|
||||
def test_get_clears_queue(self):
|
||||
"""Ensure get() clears the event queue after a call"""
|
||||
pygame.event.get() # should clear the queue completely by getting all events
|
||||
self.assertEqual(pygame.event.get(), [])
|
||||
|
||||
def test_clear(self):
|
||||
"""Ensure clear() removes all the events on the queue."""
|
||||
for e in EVENT_TYPES:
|
||||
pygame.event.post(pygame.event.Event(e, **EVENT_TEST_PARAMS[e]))
|
||||
poll_event = pygame.event.poll()
|
||||
|
||||
self.assertNotEqual(poll_event.type, pygame.NOEVENT)
|
||||
|
||||
pygame.event.clear()
|
||||
poll_event = pygame.event.poll()
|
||||
|
||||
self.assertEqual(poll_event.type, pygame.NOEVENT, race_condition_notification)
|
||||
|
||||
def test_clear__empty_queue(self):
|
||||
"""Ensure clear() works correctly on an empty queue."""
|
||||
expected_events = []
|
||||
pygame.event.clear()
|
||||
|
||||
# Test calling clear() on an already empty queue.
|
||||
pygame.event.clear()
|
||||
|
||||
retrieved_events = pygame.event.get()
|
||||
|
||||
self.assertListEqual(retrieved_events, expected_events)
|
||||
|
||||
def test_clear__event_sequence(self):
|
||||
"""Ensure a sequence of event types can be cleared from the queue."""
|
||||
cleared_event_types = EVENT_TYPES[:5]
|
||||
expected_event_types = EVENT_TYPES[5:10]
|
||||
expected_events = []
|
||||
|
||||
# Add the events to the queue.
|
||||
for etype in cleared_event_types:
|
||||
pygame.event.post(pygame.event.Event(etype, **EVENT_TEST_PARAMS[etype]))
|
||||
|
||||
for etype in expected_events:
|
||||
expected_events.append(
|
||||
pygame.event.Event(etype, **EVENT_TEST_PARAMS[etype])
|
||||
)
|
||||
pygame.event.post(expected_events[-1])
|
||||
|
||||
# Clear the cleared_events from the queue.
|
||||
pygame.event.clear(cleared_event_types)
|
||||
|
||||
# Check the rest of the events in the queue.
|
||||
remaining_events = pygame.event.get()
|
||||
|
||||
self._assertCountEqual(remaining_events, expected_events)
|
||||
|
||||
def test_event_name(self):
|
||||
"""Ensure event_name() returns the correct event name."""
|
||||
for expected_name, event in NAMES_AND_EVENTS:
|
||||
self.assertEqual(
|
||||
pygame.event.event_name(event), expected_name, f"0x{event:X}"
|
||||
)
|
||||
|
||||
def test_event_name__userevent_range(self):
|
||||
"""Ensures event_name() returns the correct name for user events.
|
||||
|
||||
Tests the full range of user events.
|
||||
"""
|
||||
expected_name = "UserEvent"
|
||||
|
||||
for event in range(pygame.USEREVENT, pygame.NUMEVENTS):
|
||||
self.assertEqual(
|
||||
pygame.event.event_name(event), expected_name, f"0x{event:X}"
|
||||
)
|
||||
|
||||
def test_event_name__userevent_boundary(self):
|
||||
"""Ensures event_name() does not return 'UserEvent' for events
|
||||
just outside the user event range.
|
||||
"""
|
||||
unexpected_name = "UserEvent"
|
||||
|
||||
for event in (pygame.USEREVENT - 1, pygame.NUMEVENTS):
|
||||
self.assertNotEqual(
|
||||
pygame.event.event_name(event), unexpected_name, f"0x{event:X}"
|
||||
)
|
||||
|
||||
def test_event_name__kwargs(self):
|
||||
"""Ensure event_name() returns the correct event name when kwargs used."""
|
||||
for expected_name, event in NAMES_AND_EVENTS:
|
||||
self.assertEqual(
|
||||
pygame.event.event_name(type=event), expected_name, f"0x{event:X}"
|
||||
)
|
||||
|
||||
def test_peek(self):
|
||||
"""Ensure queued events can be peeked at."""
|
||||
event_types = [pygame.KEYDOWN, pygame.KEYUP, pygame.MOUSEMOTION]
|
||||
|
||||
for event_type in event_types:
|
||||
pygame.event.post(
|
||||
pygame.event.Event(event_type, **EVENT_TEST_PARAMS[event_type])
|
||||
)
|
||||
|
||||
# Ensure events can be checked individually.
|
||||
for event_type in event_types:
|
||||
self.assertTrue(pygame.event.peek(event_type))
|
||||
|
||||
# Ensure events can be checked as a sequence.
|
||||
self.assertTrue(pygame.event.peek(event_types))
|
||||
|
||||
def test_peek__event_sequence(self):
|
||||
"""Ensure peek() can handle a sequence of event types."""
|
||||
event_types = [pygame.KEYDOWN, pygame.KEYUP, pygame.MOUSEMOTION]
|
||||
other_event_type = pygame.MOUSEBUTTONUP
|
||||
|
||||
# Test when no events in the queue.
|
||||
pygame.event.clear()
|
||||
peeked = pygame.event.peek(event_types)
|
||||
|
||||
self.assertFalse(peeked)
|
||||
|
||||
# Test when an event type not in the list is in the queue.
|
||||
pygame.event.clear()
|
||||
pygame.event.post(
|
||||
pygame.event.Event(other_event_type, **EVENT_TEST_PARAMS[other_event_type])
|
||||
)
|
||||
|
||||
peeked = pygame.event.peek(event_types)
|
||||
|
||||
self.assertFalse(peeked)
|
||||
|
||||
# Test when 1 event type in the list is in the queue.
|
||||
pygame.event.clear()
|
||||
pygame.event.post(
|
||||
pygame.event.Event(event_types[0], **EVENT_TEST_PARAMS[event_types[0]])
|
||||
)
|
||||
|
||||
peeked = pygame.event.peek(event_types)
|
||||
|
||||
self.assertTrue(peeked)
|
||||
|
||||
# Test all events in the list are in the queue.
|
||||
pygame.event.clear()
|
||||
for etype in event_types:
|
||||
pygame.event.post(pygame.event.Event(etype, **EVENT_TEST_PARAMS[etype]))
|
||||
|
||||
peeked = pygame.event.peek(event_types)
|
||||
|
||||
self.assertTrue(peeked)
|
||||
|
||||
def test_peek__empty_queue(self):
|
||||
"""Ensure peek() works correctly on an empty queue."""
|
||||
pygame.event.clear()
|
||||
|
||||
# Ensure all events can be checked.
|
||||
peeked = pygame.event.peek()
|
||||
|
||||
self.assertFalse(peeked)
|
||||
|
||||
# Ensure events can be checked individually.
|
||||
for event_type in EVENT_TYPES:
|
||||
peeked = pygame.event.peek(event_type)
|
||||
self.assertFalse(peeked)
|
||||
|
||||
# Ensure events can be checked as a sequence.
|
||||
peeked = pygame.event.peek(EVENT_TYPES)
|
||||
|
||||
self.assertFalse(peeked)
|
||||
|
||||
def test_set_allowed(self):
|
||||
"""Ensure a blocked event type can be unblocked/allowed."""
|
||||
event = EVENT_TYPES[0]
|
||||
pygame.event.set_blocked(event)
|
||||
|
||||
self.assertTrue(pygame.event.get_blocked(event))
|
||||
|
||||
pygame.event.set_allowed(event)
|
||||
|
||||
self.assertFalse(pygame.event.get_blocked(event))
|
||||
|
||||
def test_set_allowed__event_sequence(self):
|
||||
"""Ensure a sequence of blocked event types can be unblocked/allowed."""
|
||||
event_types = [
|
||||
pygame.KEYDOWN,
|
||||
pygame.KEYUP,
|
||||
pygame.MOUSEMOTION,
|
||||
pygame.MOUSEBUTTONDOWN,
|
||||
pygame.MOUSEBUTTONUP,
|
||||
]
|
||||
pygame.event.set_blocked(event_types)
|
||||
|
||||
pygame.event.set_allowed(event_types)
|
||||
|
||||
for etype in event_types:
|
||||
self.assertFalse(pygame.event.get_blocked(etype))
|
||||
|
||||
def test_set_allowed_all(self):
|
||||
"""Ensure all events can be unblocked/allowed at once."""
|
||||
pygame.event.set_blocked(None)
|
||||
|
||||
for e in EVENT_TYPES:
|
||||
self.assertTrue(pygame.event.get_blocked(e))
|
||||
|
||||
pygame.event.set_allowed(None)
|
||||
|
||||
for e in EVENT_TYPES:
|
||||
self.assertFalse(pygame.event.get_blocked(e))
|
||||
|
||||
def test_pump(self):
|
||||
"""Ensure pump() functions properly."""
|
||||
pygame.event.pump()
|
||||
|
||||
# @unittest.skipIf(
|
||||
# os.environ.get("SDL_VIDEODRIVER") == "dummy",
|
||||
# 'requires the SDL_VIDEODRIVER to be a non "dummy" value',
|
||||
# )
|
||||
# Fails on SDL 2.0.18
|
||||
@unittest.skip("flaky test, and broken on 2.0.18 windows")
|
||||
def test_set_grab__and_get_symmetric(self):
|
||||
"""Ensure event grabbing can be enabled and disabled.
|
||||
|
||||
WARNING: Moving the mouse off the display during this test can cause it
|
||||
to fail.
|
||||
"""
|
||||
surf = pygame.display.set_mode((10, 10))
|
||||
pygame.event.set_grab(True)
|
||||
|
||||
self.assertTrue(pygame.event.get_grab())
|
||||
|
||||
pygame.event.set_grab(False)
|
||||
|
||||
self.assertFalse(pygame.event.get_grab())
|
||||
|
||||
def test_get_blocked(self):
|
||||
"""Ensure an event's blocked state can be retrieved."""
|
||||
# Test each event is not blocked.
|
||||
pygame.event.set_allowed(None)
|
||||
|
||||
for etype in EVENT_TYPES:
|
||||
blocked = pygame.event.get_blocked(etype)
|
||||
|
||||
self.assertFalse(blocked)
|
||||
|
||||
# Test each event type is blocked.
|
||||
pygame.event.set_blocked(None)
|
||||
|
||||
for etype in EVENT_TYPES:
|
||||
blocked = pygame.event.get_blocked(etype)
|
||||
|
||||
self.assertTrue(blocked)
|
||||
|
||||
def test_get_blocked__event_sequence(self):
|
||||
"""Ensure get_blocked() can handle a sequence of event types."""
|
||||
event_types = [
|
||||
pygame.KEYDOWN,
|
||||
pygame.KEYUP,
|
||||
pygame.MOUSEMOTION,
|
||||
pygame.MOUSEBUTTONDOWN,
|
||||
pygame.MOUSEBUTTONUP,
|
||||
pygame.WINDOWMINIMIZED,
|
||||
pygame.USEREVENT,
|
||||
]
|
||||
|
||||
# Test no event types in the list are blocked.
|
||||
blocked = pygame.event.get_blocked(event_types)
|
||||
|
||||
self.assertFalse(blocked)
|
||||
|
||||
# Test when 1 event type in the list is blocked.
|
||||
pygame.event.set_blocked(event_types[2])
|
||||
|
||||
blocked = pygame.event.get_blocked(event_types)
|
||||
|
||||
self.assertTrue(blocked)
|
||||
|
||||
# Test all event types in the list are blocked.
|
||||
pygame.event.set_blocked(event_types)
|
||||
|
||||
blocked = pygame.event.get_blocked(event_types)
|
||||
|
||||
self.assertTrue(blocked)
|
||||
|
||||
# @unittest.skipIf(
|
||||
# os.environ.get("SDL_VIDEODRIVER") == "dummy",
|
||||
# 'requires the SDL_VIDEODRIVER to be a non "dummy" value',
|
||||
# )
|
||||
# Fails on SDL 2.0.18
|
||||
@unittest.skip("flaky test, and broken on 2.0.18 windows")
|
||||
def test_get_grab(self):
|
||||
"""Ensure get_grab() works as expected"""
|
||||
surf = pygame.display.set_mode((10, 10))
|
||||
# Test 5 times
|
||||
for i in range(5):
|
||||
pygame.event.set_grab(i % 2)
|
||||
self.assertEqual(pygame.event.get_grab(), i % 2)
|
||||
|
||||
@unittest.skipIf(
|
||||
os.environ.get("SDL_VIDEODRIVER") == "dummy",
|
||||
"requires the SDL_VIDEODRIVER to be a non dummy value",
|
||||
)
|
||||
@unittest.skipIf(pygame.get_sdl_version() < (2, 0, 16), "Needs at least SDL 2.0.16")
|
||||
def test_set_keyboard_grab_and_get_keyboard_grab(self):
|
||||
"""Ensure set_keyboard_grab() and get_keyboard_grab() work as expected"""
|
||||
|
||||
surf = pygame.display.set_mode((10, 10))
|
||||
|
||||
pygame.event.set_keyboard_grab(True)
|
||||
self.assertTrue(pygame.event.get_keyboard_grab())
|
||||
|
||||
pygame.event.set_keyboard_grab(False)
|
||||
self.assertFalse(pygame.event.get_keyboard_grab())
|
||||
|
||||
def test_poll(self):
|
||||
"""Ensure poll() works as expected"""
|
||||
pygame.event.clear()
|
||||
ev = pygame.event.poll()
|
||||
# poll() on empty queue should return NOEVENT
|
||||
self.assertEqual(ev.type, pygame.NOEVENT)
|
||||
|
||||
# test poll returns stuff in same order
|
||||
e1 = pygame.event.Event(pygame.USEREVENT)
|
||||
e2 = pygame.event.Event(pygame.KEYDOWN, key=pygame.K_a)
|
||||
e3 = pygame.event.Event(pygame.KEYUP, key=pygame.K_a)
|
||||
pygame.event.post(e1)
|
||||
pygame.event.post(e2)
|
||||
pygame.event.post(e3)
|
||||
|
||||
self.assertEqual(pygame.event.poll().type, e1.type)
|
||||
self.assertEqual(pygame.event.poll().type, e2.type)
|
||||
self.assertEqual(pygame.event.poll().type, e3.type)
|
||||
self.assertEqual(pygame.event.poll().type, pygame.NOEVENT)
|
||||
|
||||
|
||||
class EventModuleTestsWithTiming(unittest.TestCase):
|
||||
__tags__ = ["timing"]
|
||||
|
||||
def setUp(self):
|
||||
pygame.display.init()
|
||||
pygame.event.clear() # flush events
|
||||
|
||||
def tearDown(self):
|
||||
pygame.event.clear() # flush events
|
||||
pygame.display.quit()
|
||||
|
||||
def test_event_wait(self):
|
||||
"""Ensure wait() waits for an event on the queue."""
|
||||
# Test case without timeout.
|
||||
event = pygame.event.Event(EVENT_TYPES[0], **EVENT_TEST_PARAMS[EVENT_TYPES[0]])
|
||||
pygame.event.post(event)
|
||||
wait_event = pygame.event.wait()
|
||||
|
||||
self.assertEqual(wait_event.type, event.type)
|
||||
|
||||
# Test case with timeout and no event in the queue.
|
||||
wait_event = pygame.event.wait(100)
|
||||
self.assertEqual(wait_event.type, pygame.NOEVENT)
|
||||
|
||||
# Test case with timeout and an event in the queue.
|
||||
event = pygame.event.Event(EVENT_TYPES[0], **EVENT_TEST_PARAMS[EVENT_TYPES[0]])
|
||||
pygame.event.post(event)
|
||||
wait_event = pygame.event.wait(100)
|
||||
|
||||
self.assertEqual(wait_event.type, event.type)
|
||||
|
||||
# test wait with timeout waits for the correct duration
|
||||
pygame.time.set_timer(pygame.USEREVENT, 50, 3)
|
||||
|
||||
for wait_time, expected_type, expected_time in (
|
||||
(60, pygame.USEREVENT, 50),
|
||||
(65, pygame.USEREVENT, 50),
|
||||
(20, pygame.NOEVENT, 20),
|
||||
(45, pygame.USEREVENT, 30),
|
||||
(70, pygame.NOEVENT, 70),
|
||||
):
|
||||
start_time = time.perf_counter()
|
||||
self.assertEqual(pygame.event.wait(wait_time).type, expected_type)
|
||||
self.assertAlmostEqual(
|
||||
time.perf_counter() - start_time, expected_time / 1000, delta=0.01
|
||||
)
|
||||
|
||||
# test wait without timeout waits for the full duration
|
||||
pygame.time.set_timer(pygame.USEREVENT, 100, 1)
|
||||
|
||||
start_time = time.perf_counter()
|
||||
self.assertEqual(pygame.event.wait().type, pygame.USEREVENT)
|
||||
self.assertAlmostEqual(time.perf_counter() - start_time, 0.1, delta=0.01)
|
||||
|
||||
# test wait returns no event if event is arriving later
|
||||
pygame.time.set_timer(pygame.USEREVENT, 50, 1)
|
||||
self.assertEqual(pygame.event.wait(40).type, pygame.NOEVENT)
|
||||
|
||||
|
||||
################################################################################
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
BIN
.venv/lib/python3.7/site-packages/pygame/tests/fixtures/fonts/A_PyGameMono-8.png
vendored
Normal file
BIN
.venv/lib/python3.7/site-packages/pygame/tests/fixtures/fonts/A_PyGameMono-8.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 92 B |
BIN
.venv/lib/python3.7/site-packages/pygame/tests/fixtures/fonts/PlayfairDisplaySemibold.ttf
vendored
Normal file
BIN
.venv/lib/python3.7/site-packages/pygame/tests/fixtures/fonts/PlayfairDisplaySemibold.ttf
vendored
Normal file
Binary file not shown.
165
.venv/lib/python3.7/site-packages/pygame/tests/fixtures/fonts/PyGameMono-18-100dpi.bdf
vendored
Normal file
165
.venv/lib/python3.7/site-packages/pygame/tests/fixtures/fonts/PyGameMono-18-100dpi.bdf
vendored
Normal file
@@ -0,0 +1,165 @@
|
||||
STARTFONT 2.1
|
||||
FONT -FontForge-PyGameMono-Medium-R-Normal--25-180-100-100-M-250-ISO10646-1
|
||||
SIZE 18 100 100
|
||||
FONTBOUNDINGBOX 21 22 0 0
|
||||
COMMENT "Generated by fontforge, http://fontforge.sourceforge.net"
|
||||
COMMENT "Created by Lenard Lindstrom,,, with FontForge 2.0 (http://fontforge.sf.net)"
|
||||
STARTPROPERTIES 29
|
||||
FOUNDRY "FontForge"
|
||||
FAMILY_NAME "PyGameMono"
|
||||
WEIGHT_NAME "Medium"
|
||||
SLANT "R"
|
||||
SETWIDTH_NAME "Normal"
|
||||
ADD_STYLE_NAME ""
|
||||
PIXEL_SIZE 25
|
||||
POINT_SIZE 180
|
||||
RESOLUTION_X 100
|
||||
RESOLUTION_Y 100
|
||||
SPACING "M"
|
||||
AVERAGE_WIDTH 250
|
||||
CHARSET_REGISTRY "ISO10646"
|
||||
CHARSET_ENCODING "1"
|
||||
FONTNAME_REGISTRY ""
|
||||
CHARSET_COLLECTIONS "ISO10646-1"
|
||||
FONT_NAME "PyGameMono"
|
||||
FACE_NAME "PyGame Mono"
|
||||
FONT_VERSION "001.000"
|
||||
FONT_ASCENT 20
|
||||
FONT_DESCENT 5
|
||||
UNDERLINE_POSITION -2
|
||||
UNDERLINE_THICKNESS 2
|
||||
RAW_ASCENT 800
|
||||
RAW_DESCENT 200
|
||||
RELATIVE_WEIGHT 50
|
||||
RELATIVE_SETWIDTH 50
|
||||
FIGURE_WIDTH -1
|
||||
AVG_UPPERCASE_WIDTH 250
|
||||
ENDPROPERTIES
|
||||
CHARS 5
|
||||
STARTCHAR .notdef
|
||||
ENCODING 0
|
||||
SWIDTH 1000 0
|
||||
DWIDTH 25 0
|
||||
BBX 20 20 0 0
|
||||
BITMAP
|
||||
FFFFF0
|
||||
FFFFF0
|
||||
FE07F0
|
||||
F801F0
|
||||
F000F0
|
||||
E00070
|
||||
E00070
|
||||
C00030
|
||||
C00030
|
||||
C00030
|
||||
C00030
|
||||
C00030
|
||||
C00030
|
||||
E00070
|
||||
E00070
|
||||
F000F0
|
||||
F801F0
|
||||
FE07F0
|
||||
FFFFF0
|
||||
FFFFF0
|
||||
ENDCHAR
|
||||
STARTCHAR A
|
||||
ENCODING 65
|
||||
SWIDTH 1000 0
|
||||
DWIDTH 25 0
|
||||
BBX 20 21 0 1
|
||||
BITMAP
|
||||
03FC00
|
||||
1FFF80
|
||||
3FFFC0
|
||||
7C03E0
|
||||
F000F0
|
||||
E00070
|
||||
E00070
|
||||
F000F0
|
||||
FC03F0
|
||||
FFFFF0
|
||||
FFFFF0
|
||||
FFFFF0
|
||||
FF0FF0
|
||||
7C03F0
|
||||
7801E0
|
||||
7800E0
|
||||
7000E0
|
||||
700060
|
||||
600060
|
||||
200040
|
||||
200040
|
||||
ENDCHAR
|
||||
STARTCHAR B
|
||||
ENCODING 66
|
||||
SWIDTH 1000 0
|
||||
DWIDTH 25 0
|
||||
BBX 18 20 1 0
|
||||
BITMAP
|
||||
FFFE00
|
||||
FFFF80
|
||||
7E0780
|
||||
7801C0
|
||||
7000C0
|
||||
3000C0
|
||||
3000C0
|
||||
3801C0
|
||||
3E0780
|
||||
3FFF00
|
||||
3FFF00
|
||||
3E0780
|
||||
380180
|
||||
3000C0
|
||||
3000C0
|
||||
3000C0
|
||||
7801C0
|
||||
7E07C0
|
||||
FFFF80
|
||||
FFFE00
|
||||
ENDCHAR
|
||||
STARTCHAR C
|
||||
ENCODING 67
|
||||
SWIDTH 1000 0
|
||||
DWIDTH 25 0
|
||||
BBX 20 20 0 0
|
||||
BITMAP
|
||||
00FC00
|
||||
03FF00
|
||||
0FFF80
|
||||
1F03E0
|
||||
3E0070
|
||||
7C0010
|
||||
780000
|
||||
F80000
|
||||
F00000
|
||||
F00000
|
||||
F00000
|
||||
F00000
|
||||
F80000
|
||||
780000
|
||||
7C0010
|
||||
3E0070
|
||||
1F01E0
|
||||
0FFFC0
|
||||
03FF80
|
||||
00FE00
|
||||
ENDCHAR
|
||||
STARTCHAR u13079
|
||||
ENCODING 77945
|
||||
SWIDTH 1000 0
|
||||
DWIDTH 25 0
|
||||
BBX 21 10 0 5
|
||||
BITMAP
|
||||
03FC00
|
||||
0FFF80
|
||||
1E73C0
|
||||
78F8F0
|
||||
F0F878
|
||||
70F870
|
||||
3870E0
|
||||
1E03C0
|
||||
0FFF80
|
||||
03FC00
|
||||
ENDCHAR
|
||||
ENDFONT
|
143
.venv/lib/python3.7/site-packages/pygame/tests/fixtures/fonts/PyGameMono-18-75dpi.bdf
vendored
Normal file
143
.venv/lib/python3.7/site-packages/pygame/tests/fixtures/fonts/PyGameMono-18-75dpi.bdf
vendored
Normal file
@@ -0,0 +1,143 @@
|
||||
STARTFONT 2.1
|
||||
FONT -FontForge-PyGameMono-Medium-R-Normal--19-180-75-75-M-190-ISO10646-1
|
||||
SIZE 18 75 75
|
||||
FONTBOUNDINGBOX 15 17 0 0
|
||||
COMMENT "Generated by fontforge, http://fontforge.sourceforge.net"
|
||||
COMMENT "Created by Lenard Lindstrom,,, with FontForge 2.0 (http://fontforge.sf.net)"
|
||||
STARTPROPERTIES 29
|
||||
FOUNDRY "FontForge"
|
||||
FAMILY_NAME "PyGameMono"
|
||||
WEIGHT_NAME "Medium"
|
||||
SLANT "R"
|
||||
SETWIDTH_NAME "Normal"
|
||||
ADD_STYLE_NAME ""
|
||||
PIXEL_SIZE 19
|
||||
POINT_SIZE 180
|
||||
RESOLUTION_X 75
|
||||
RESOLUTION_Y 75
|
||||
SPACING "M"
|
||||
AVERAGE_WIDTH 190
|
||||
CHARSET_REGISTRY "ISO10646"
|
||||
CHARSET_ENCODING "1"
|
||||
FONTNAME_REGISTRY ""
|
||||
CHARSET_COLLECTIONS "ISO10646-1"
|
||||
FONT_NAME "PyGameMono"
|
||||
FACE_NAME "PyGame Mono"
|
||||
FONT_VERSION "001.000"
|
||||
FONT_ASCENT 15
|
||||
FONT_DESCENT 4
|
||||
UNDERLINE_POSITION -2
|
||||
UNDERLINE_THICKNESS 1
|
||||
RAW_ASCENT 800
|
||||
RAW_DESCENT 200
|
||||
RELATIVE_WEIGHT 50
|
||||
RELATIVE_SETWIDTH 50
|
||||
FIGURE_WIDTH -1
|
||||
AVG_UPPERCASE_WIDTH 190
|
||||
ENDPROPERTIES
|
||||
CHARS 5
|
||||
STARTCHAR .notdef
|
||||
ENCODING 0
|
||||
SWIDTH 1000 0
|
||||
DWIDTH 19 0
|
||||
BBX 15 15 0 0
|
||||
BITMAP
|
||||
FFFE
|
||||
FFFE
|
||||
FC7E
|
||||
F01E
|
||||
E00E
|
||||
C006
|
||||
C006
|
||||
C006
|
||||
C006
|
||||
C006
|
||||
E00E
|
||||
F01E
|
||||
FC7E
|
||||
FFFE
|
||||
FFFE
|
||||
ENDCHAR
|
||||
STARTCHAR A
|
||||
ENCODING 65
|
||||
SWIDTH 1000 0
|
||||
DWIDTH 19 0
|
||||
BBX 15 17 0 0
|
||||
BITMAP
|
||||
0FE0
|
||||
3FF8
|
||||
783C
|
||||
F01E
|
||||
E00E
|
||||
E00E
|
||||
F01E
|
||||
F83E
|
||||
FFFE
|
||||
FFFE
|
||||
FC7E
|
||||
701C
|
||||
701C
|
||||
600C
|
||||
600C
|
||||
4004
|
||||
4004
|
||||
ENDCHAR
|
||||
STARTCHAR B
|
||||
ENCODING 66
|
||||
SWIDTH 1000 0
|
||||
DWIDTH 19 0
|
||||
BBX 15 15 0 0
|
||||
BITMAP
|
||||
FFF8
|
||||
7FFC
|
||||
780E
|
||||
3006
|
||||
3006
|
||||
380E
|
||||
3FF8
|
||||
3FF8
|
||||
3FF8
|
||||
380E
|
||||
3006
|
||||
3006
|
||||
7C1E
|
||||
7FFC
|
||||
FFF8
|
||||
ENDCHAR
|
||||
STARTCHAR C
|
||||
ENCODING 67
|
||||
SWIDTH 1000 0
|
||||
DWIDTH 19 0
|
||||
BBX 15 15 0 0
|
||||
BITMAP
|
||||
03E0
|
||||
0FF8
|
||||
3C1C
|
||||
7806
|
||||
7000
|
||||
E000
|
||||
E000
|
||||
E000
|
||||
E000
|
||||
E000
|
||||
7000
|
||||
7806
|
||||
3C1C
|
||||
0FF8
|
||||
03E0
|
||||
ENDCHAR
|
||||
STARTCHAR u13079
|
||||
ENCODING 77945
|
||||
SWIDTH 1000 0
|
||||
DWIDTH 19 0
|
||||
BBX 15 7 0 4
|
||||
BITMAP
|
||||
0FE0
|
||||
3838
|
||||
638C
|
||||
E38E
|
||||
638C
|
||||
3838
|
||||
0FE0
|
||||
ENDCHAR
|
||||
ENDFONT
|
103
.venv/lib/python3.7/site-packages/pygame/tests/fixtures/fonts/PyGameMono-8.bdf
vendored
Normal file
103
.venv/lib/python3.7/site-packages/pygame/tests/fixtures/fonts/PyGameMono-8.bdf
vendored
Normal file
@@ -0,0 +1,103 @@
|
||||
STARTFONT 2.1
|
||||
FONT -FontForge-PyGameMono-Medium-R-Normal--8-80-75-75-C-80-ISO10646-1
|
||||
SIZE 8 75 75
|
||||
FONTBOUNDINGBOX 6 7 0 0
|
||||
COMMENT "Generated by fontforge, http://fontforge.sourceforge.net"
|
||||
COMMENT "Created by Lenard Lindstrom,,, with FontForge 2.0 (http://fontforge.sf.net)"
|
||||
STARTPROPERTIES 29
|
||||
FOUNDRY "FontForge"
|
||||
FAMILY_NAME "PyGameMono"
|
||||
WEIGHT_NAME "Medium"
|
||||
SLANT "R"
|
||||
SETWIDTH_NAME "Normal"
|
||||
ADD_STYLE_NAME ""
|
||||
PIXEL_SIZE 8
|
||||
POINT_SIZE 80
|
||||
RESOLUTION_X 75
|
||||
RESOLUTION_Y 75
|
||||
SPACING "C"
|
||||
AVERAGE_WIDTH 80
|
||||
CHARSET_REGISTRY "ISO10646"
|
||||
CHARSET_ENCODING "1"
|
||||
FONTNAME_REGISTRY ""
|
||||
CHARSET_COLLECTIONS "ISO10646-1"
|
||||
FONT_NAME "PyGameMono"
|
||||
FACE_NAME "PyGame Mono"
|
||||
FONT_VERSION "001.000"
|
||||
FONT_ASCENT 6
|
||||
FONT_DESCENT 2
|
||||
UNDERLINE_POSITION -1
|
||||
UNDERLINE_THICKNESS 1
|
||||
RAW_ASCENT 800
|
||||
RAW_DESCENT 200
|
||||
RELATIVE_WEIGHT 50
|
||||
RELATIVE_SETWIDTH 50
|
||||
FIGURE_WIDTH -1
|
||||
AVG_UPPERCASE_WIDTH 80
|
||||
ENDPROPERTIES
|
||||
CHARS 5
|
||||
STARTCHAR .notdef
|
||||
ENCODING 0
|
||||
SWIDTH 1000 0
|
||||
DWIDTH 8 0
|
||||
BBX 6 6 0 0
|
||||
BITMAP
|
||||
FC
|
||||
84
|
||||
84
|
||||
84
|
||||
84
|
||||
FC
|
||||
ENDCHAR
|
||||
STARTCHAR A
|
||||
ENCODING 65
|
||||
SWIDTH 1000 0
|
||||
DWIDTH 8 0
|
||||
BBX 6 7 0 0
|
||||
BITMAP
|
||||
78
|
||||
84
|
||||
84
|
||||
FC
|
||||
84
|
||||
84
|
||||
84
|
||||
ENDCHAR
|
||||
STARTCHAR B
|
||||
ENCODING 66
|
||||
SWIDTH 1000 0
|
||||
DWIDTH 8 0
|
||||
BBX 6 6 0 0
|
||||
BITMAP
|
||||
FC
|
||||
44
|
||||
78
|
||||
4C
|
||||
44
|
||||
FC
|
||||
ENDCHAR
|
||||
STARTCHAR C
|
||||
ENCODING 67
|
||||
SWIDTH 1000 0
|
||||
DWIDTH 8 0
|
||||
BBX 6 6 0 0
|
||||
BITMAP
|
||||
78
|
||||
C4
|
||||
C0
|
||||
C0
|
||||
C4
|
||||
78
|
||||
ENDCHAR
|
||||
STARTCHAR u13079
|
||||
ENCODING 77945
|
||||
SWIDTH 1000 0
|
||||
DWIDTH 8 0
|
||||
BBX 6 4 0 1
|
||||
BITMAP
|
||||
78
|
||||
B4
|
||||
B4
|
||||
78
|
||||
ENDCHAR
|
||||
ENDFONT
|
BIN
.venv/lib/python3.7/site-packages/pygame/tests/fixtures/fonts/PyGameMono.otf
vendored
Normal file
BIN
.venv/lib/python3.7/site-packages/pygame/tests/fixtures/fonts/PyGameMono.otf
vendored
Normal file
Binary file not shown.
BIN
.venv/lib/python3.7/site-packages/pygame/tests/fixtures/fonts/test_fixed.otf
vendored
Normal file
BIN
.venv/lib/python3.7/site-packages/pygame/tests/fixtures/fonts/test_fixed.otf
vendored
Normal file
Binary file not shown.
BIN
.venv/lib/python3.7/site-packages/pygame/tests/fixtures/fonts/test_sans.ttf
vendored
Normal file
BIN
.venv/lib/python3.7/site-packages/pygame/tests/fixtures/fonts/test_sans.ttf
vendored
Normal file
Binary file not shown.
BIN
.venv/lib/python3.7/site-packages/pygame/tests/fixtures/fonts/u13079_PyGameMono-8.png
vendored
Normal file
BIN
.venv/lib/python3.7/site-packages/pygame/tests/fixtures/fonts/u13079_PyGameMono-8.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 89 B |
8
.venv/lib/python3.7/site-packages/pygame/tests/fixtures/xbm_cursors/white_sizing.xbm
vendored
Normal file
8
.venv/lib/python3.7/site-packages/pygame/tests/fixtures/xbm_cursors/white_sizing.xbm
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
#define resize_white_width 16
|
||||
#define resize_white_height 16
|
||||
#define resize_white_x_hot 7
|
||||
#define resize_white_y_hot 7
|
||||
static unsigned char resize_white_bits[] = {
|
||||
0xff, 0x03, 0x01, 0x02, 0xfd, 0x03, 0x05, 0x00, 0xf5, 0x0f, 0x15, 0x08,
|
||||
0xd5, 0xeb, 0x55, 0xaa, 0x55, 0xaa, 0xd7, 0xab, 0x10, 0xa8, 0xf0, 0xb7,
|
||||
0x00, 0xa8, 0xc0, 0x9f, 0x40, 0x80, 0xc0, 0xff};
|
8
.venv/lib/python3.7/site-packages/pygame/tests/fixtures/xbm_cursors/white_sizing_mask.xbm
vendored
Normal file
8
.venv/lib/python3.7/site-packages/pygame/tests/fixtures/xbm_cursors/white_sizing_mask.xbm
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
#define resize_white_mask_width 16
|
||||
#define resize_white_mask_height 16
|
||||
#define resize_white_mask_x_hot 7
|
||||
#define resize_white_mask_y_hot 7
|
||||
static unsigned char resize_white_mask_bits[] = {
|
||||
0xff, 0x03, 0xff, 0x03, 0xff, 0x03, 0x07, 0x00, 0xf7, 0x0f, 0xf7, 0x0f,
|
||||
0xf7, 0xef, 0x77, 0xee, 0x77, 0xee, 0xf7, 0xef, 0xf0, 0xef, 0xf0, 0xff,
|
||||
0x00, 0xf8, 0xc0, 0xff, 0xc0, 0xff, 0xc0, 0xff};
|
749
.venv/lib/python3.7/site-packages/pygame/tests/font_test.py
Normal file
749
.venv/lib/python3.7/site-packages/pygame/tests/font_test.py
Normal file
@@ -0,0 +1,749 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from re import T
|
||||
import sys
|
||||
import os
|
||||
import unittest
|
||||
import pathlib
|
||||
import platform
|
||||
|
||||
import pygame
|
||||
from pygame import font as pygame_font # So font can be replaced with ftfont
|
||||
|
||||
|
||||
FONTDIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), "fixtures", "fonts")
|
||||
|
||||
|
||||
def equal_images(s1, s2):
|
||||
size = s1.get_size()
|
||||
if s2.get_size() != size:
|
||||
return False
|
||||
w, h = size
|
||||
for x in range(w):
|
||||
for y in range(h):
|
||||
if s1.get_at((x, y)) != s2.get_at((x, y)):
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
IS_PYPY = "PyPy" == platform.python_implementation()
|
||||
|
||||
|
||||
@unittest.skipIf(IS_PYPY, "pypy skip known failure") # TODO
|
||||
class FontModuleTest(unittest.TestCase):
|
||||
def setUp(self):
|
||||
pygame_font.init()
|
||||
|
||||
def tearDown(self):
|
||||
pygame_font.quit()
|
||||
|
||||
def test_get_sdl_ttf_version(self):
|
||||
def test_ver_tuple(ver):
|
||||
self.assertIsInstance(ver, tuple)
|
||||
self.assertEqual(len(ver), 3)
|
||||
for i in ver:
|
||||
self.assertIsInstance(i, int)
|
||||
|
||||
if pygame_font.__name__ != "pygame.ftfont":
|
||||
compiled = pygame_font.get_sdl_ttf_version()
|
||||
linked = pygame_font.get_sdl_ttf_version(linked=True)
|
||||
|
||||
test_ver_tuple(compiled)
|
||||
test_ver_tuple(linked)
|
||||
|
||||
self.assertTrue(linked >= compiled)
|
||||
|
||||
def test_SysFont(self):
|
||||
# Can only check that a font object is returned.
|
||||
fonts = pygame_font.get_fonts()
|
||||
if "arial" in fonts:
|
||||
# Try to use arial font if it is there, rather than a random font
|
||||
# which can be different depending on installed fonts on the system.
|
||||
font_name = "arial"
|
||||
else:
|
||||
font_name = sorted(fonts)[0]
|
||||
o = pygame_font.SysFont(font_name, 20)
|
||||
self.assertTrue(isinstance(o, pygame_font.FontType))
|
||||
o = pygame_font.SysFont(font_name, 20, italic=True)
|
||||
self.assertTrue(isinstance(o, pygame_font.FontType))
|
||||
o = pygame_font.SysFont(font_name, 20, bold=True)
|
||||
self.assertTrue(isinstance(o, pygame_font.FontType))
|
||||
o = pygame_font.SysFont("thisisnotafont", 20)
|
||||
self.assertTrue(isinstance(o, pygame_font.FontType))
|
||||
|
||||
def test_get_default_font(self):
|
||||
self.assertEqual(pygame_font.get_default_font(), "freesansbold.ttf")
|
||||
|
||||
def test_get_fonts_returns_something(self):
|
||||
fnts = pygame_font.get_fonts()
|
||||
self.assertTrue(fnts)
|
||||
|
||||
# to test if some files exist...
|
||||
# def XXtest_has_file_osx_10_5_sdk(self):
|
||||
# import os
|
||||
# f = "/Developer/SDKs/MacOSX10.5.sdk/usr/X11/include/ft2build.h"
|
||||
# self.assertEqual(os.path.exists(f), True)
|
||||
|
||||
# def XXtest_has_file_osx_10_4_sdk(self):
|
||||
# import os
|
||||
# f = "/Developer/SDKs/MacOSX10.4u.sdk/usr/X11R6/include/ft2build.h"
|
||||
# self.assertEqual(os.path.exists(f), True)
|
||||
|
||||
def test_get_fonts(self):
|
||||
fnts = pygame_font.get_fonts()
|
||||
|
||||
self.assertTrue(fnts, msg=repr(fnts))
|
||||
|
||||
for name in fnts:
|
||||
# note, on ubuntu 2.6 they are all unicode strings.
|
||||
|
||||
self.assertTrue(isinstance(name, str), name)
|
||||
# Font names can be comprised of only numeric characters, so
|
||||
# just checking name.islower() will not work as expected here.
|
||||
self.assertFalse(any(c.isupper() for c in name))
|
||||
self.assertTrue(name.isalnum(), name)
|
||||
|
||||
def test_get_init(self):
|
||||
self.assertTrue(pygame_font.get_init())
|
||||
pygame_font.quit()
|
||||
self.assertFalse(pygame_font.get_init())
|
||||
|
||||
def test_init(self):
|
||||
pygame_font.init()
|
||||
|
||||
def test_match_font_all_exist(self):
|
||||
fonts = pygame_font.get_fonts()
|
||||
|
||||
# Ensure all listed fonts are in fact available, and the returned file
|
||||
# name is a full path.
|
||||
for font in fonts:
|
||||
path = pygame_font.match_font(font)
|
||||
self.assertFalse(path is None)
|
||||
self.assertTrue(os.path.isabs(path) and os.path.isfile(path))
|
||||
|
||||
def test_match_font_name(self):
|
||||
"""That match_font accepts names of various types"""
|
||||
font = pygame_font.get_fonts()[0]
|
||||
font_path = pygame_font.match_font(font)
|
||||
self.assertIsNotNone(font_path)
|
||||
font_b = font.encode()
|
||||
not_a_font = "thisisnotafont"
|
||||
not_a_font_b = b"thisisnotafont"
|
||||
good_font_names = [
|
||||
# Check single name bytes.
|
||||
font_b,
|
||||
# Check string of comma-separated names.
|
||||
",".join([not_a_font, font, not_a_font]),
|
||||
# Check list of names.
|
||||
[not_a_font, font, not_a_font],
|
||||
# Check generator:
|
||||
(name for name in [not_a_font, font, not_a_font]),
|
||||
# Check comma-separated bytes.
|
||||
b",".join([not_a_font_b, font_b, not_a_font_b]),
|
||||
# Check list of bytes.
|
||||
[not_a_font_b, font_b, not_a_font_b],
|
||||
# Check mixed list of bytes and string.
|
||||
[font, not_a_font, font_b, not_a_font_b],
|
||||
]
|
||||
for font_name in good_font_names:
|
||||
self.assertEqual(pygame_font.match_font(font_name), font_path, font_name)
|
||||
|
||||
def test_not_match_font_name(self):
|
||||
"""match_font return None when names of various types do not exist"""
|
||||
not_a_font = "thisisnotafont"
|
||||
not_a_font_b = b"thisisnotafont"
|
||||
bad_font_names = [
|
||||
not_a_font,
|
||||
",".join([not_a_font, not_a_font, not_a_font]),
|
||||
[not_a_font, not_a_font, not_a_font],
|
||||
(name for name in [not_a_font, not_a_font, not_a_font]),
|
||||
not_a_font_b,
|
||||
b",".join([not_a_font_b, not_a_font_b, not_a_font_b]),
|
||||
[not_a_font_b, not_a_font_b, not_a_font_b],
|
||||
[not_a_font, not_a_font_b, not_a_font],
|
||||
]
|
||||
for font_name in bad_font_names:
|
||||
self.assertIsNone(pygame_font.match_font(font_name), font_name)
|
||||
|
||||
def test_match_font_bold(self):
|
||||
fonts = pygame_font.get_fonts()
|
||||
|
||||
# Look for a bold font.
|
||||
self.assertTrue(any(pygame_font.match_font(font, bold=True) for font in fonts))
|
||||
|
||||
def test_match_font_italic(self):
|
||||
fonts = pygame_font.get_fonts()
|
||||
|
||||
# Look for an italic font.
|
||||
self.assertTrue(
|
||||
any(pygame_font.match_font(font, italic=True) for font in fonts)
|
||||
)
|
||||
|
||||
def test_issue_742(self):
|
||||
"""that the font background does not crash."""
|
||||
surf = pygame.Surface((320, 240))
|
||||
font = pygame_font.Font(None, 24)
|
||||
image = font.render("Test", 0, (255, 255, 255), (0, 0, 0))
|
||||
self.assertIsNone(image.get_colorkey())
|
||||
image.set_alpha(255)
|
||||
surf.blit(image, (0, 0))
|
||||
|
||||
# not issue 742, but be sure to test that background color is
|
||||
# correctly issued on this mode
|
||||
self.assertEqual(surf.get_at((0, 0)), pygame.Color(0, 0, 0))
|
||||
|
||||
def test_issue_font_alphablit(self):
|
||||
"""Check that blitting anti-aliased text doesn't
|
||||
change the background blue"""
|
||||
pygame.display.set_mode((600, 400))
|
||||
|
||||
font = pygame_font.Font(None, 24)
|
||||
|
||||
(color, text, center, pos) = ((160, 200, 250), "Music", (190, 170), "midright")
|
||||
img1 = font.render(text, True, color)
|
||||
|
||||
img = pygame.Surface(img1.get_size(), depth=32)
|
||||
pre_blit_corner_pixel = img.get_at((0, 0))
|
||||
img.blit(img1, (0, 0))
|
||||
post_blit_corner_pixel = img.get_at((0, 0))
|
||||
|
||||
self.assertEqual(pre_blit_corner_pixel, post_blit_corner_pixel)
|
||||
|
||||
def test_segfault_after_reinit(self):
|
||||
"""Reinitialization of font module should not cause
|
||||
segmentation fault"""
|
||||
import gc
|
||||
|
||||
font = pygame_font.Font(None, 20)
|
||||
pygame_font.quit()
|
||||
pygame_font.init()
|
||||
del font
|
||||
gc.collect()
|
||||
|
||||
def test_quit(self):
|
||||
pygame_font.quit()
|
||||
|
||||
|
||||
@unittest.skipIf(IS_PYPY, "pypy skip known failure") # TODO
|
||||
class FontTest(unittest.TestCase):
|
||||
def setUp(self):
|
||||
pygame_font.init()
|
||||
|
||||
def tearDown(self):
|
||||
pygame_font.quit()
|
||||
|
||||
def test_render_args(self):
|
||||
screen = pygame.display.set_mode((600, 400))
|
||||
rect = screen.get_rect()
|
||||
f = pygame_font.Font(None, 20)
|
||||
screen.fill((10, 10, 10))
|
||||
font_surface = f.render(" bar", True, (0, 0, 0), (255, 255, 255))
|
||||
font_rect = font_surface.get_rect()
|
||||
font_rect.topleft = rect.topleft
|
||||
self.assertTrue(font_surface)
|
||||
screen.blit(font_surface, font_rect, font_rect)
|
||||
pygame.display.update()
|
||||
self.assertEqual(tuple(screen.get_at((0, 0)))[:3], (255, 255, 255))
|
||||
self.assertEqual(tuple(screen.get_at(font_rect.topleft))[:3], (255, 255, 255))
|
||||
|
||||
# If we don't have a real display, don't do this test.
|
||||
# Transparent background doesn't seem to work without a read video card.
|
||||
if os.environ.get("SDL_VIDEODRIVER") != "dummy":
|
||||
screen.fill((10, 10, 10))
|
||||
font_surface = f.render(" bar", True, (0, 0, 0), None)
|
||||
font_rect = font_surface.get_rect()
|
||||
font_rect.topleft = rect.topleft
|
||||
self.assertTrue(font_surface)
|
||||
screen.blit(font_surface, font_rect, font_rect)
|
||||
pygame.display.update()
|
||||
self.assertEqual(tuple(screen.get_at((0, 0)))[:3], (10, 10, 10))
|
||||
self.assertEqual(tuple(screen.get_at(font_rect.topleft))[:3], (10, 10, 10))
|
||||
|
||||
screen.fill((10, 10, 10))
|
||||
font_surface = f.render(" bar", True, (0, 0, 0))
|
||||
font_rect = font_surface.get_rect()
|
||||
font_rect.topleft = rect.topleft
|
||||
self.assertTrue(font_surface)
|
||||
screen.blit(font_surface, font_rect, font_rect)
|
||||
pygame.display.update(rect)
|
||||
self.assertEqual(tuple(screen.get_at((0, 0)))[:3], (10, 10, 10))
|
||||
self.assertEqual(tuple(screen.get_at(font_rect.topleft))[:3], (10, 10, 10))
|
||||
|
||||
|
||||
@unittest.skipIf(IS_PYPY, "pypy skip known failure") # TODO
|
||||
class FontTypeTest(unittest.TestCase):
|
||||
def setUp(self):
|
||||
pygame_font.init()
|
||||
|
||||
def tearDown(self):
|
||||
pygame_font.quit()
|
||||
|
||||
def test_default_parameters(self):
|
||||
f = pygame_font.Font()
|
||||
|
||||
def test_get_ascent(self):
|
||||
# Ckecking ascent would need a custom test font to do properly.
|
||||
f = pygame_font.Font(None, 20)
|
||||
ascent = f.get_ascent()
|
||||
self.assertTrue(isinstance(ascent, int))
|
||||
self.assertTrue(ascent > 0)
|
||||
s = f.render("X", False, (255, 255, 255))
|
||||
self.assertTrue(s.get_size()[1] > ascent)
|
||||
|
||||
def test_get_descent(self):
|
||||
# Ckecking descent would need a custom test font to do properly.
|
||||
f = pygame_font.Font(None, 20)
|
||||
descent = f.get_descent()
|
||||
self.assertTrue(isinstance(descent, int))
|
||||
self.assertTrue(descent < 0)
|
||||
|
||||
def test_get_height(self):
|
||||
# Ckecking height would need a custom test font to do properly.
|
||||
f = pygame_font.Font(None, 20)
|
||||
height = f.get_height()
|
||||
self.assertTrue(isinstance(height, int))
|
||||
self.assertTrue(height > 0)
|
||||
s = f.render("X", False, (255, 255, 255))
|
||||
self.assertTrue(s.get_size()[1] == height)
|
||||
|
||||
def test_get_linesize(self):
|
||||
# Ckecking linesize would need a custom test font to do properly.
|
||||
# Questions: How do linesize, height and descent relate?
|
||||
f = pygame_font.Font(None, 20)
|
||||
linesize = f.get_linesize()
|
||||
self.assertTrue(isinstance(linesize, int))
|
||||
self.assertTrue(linesize > 0)
|
||||
|
||||
def test_metrics(self):
|
||||
# Ensure bytes decoding works correctly. Can only compare results
|
||||
# with unicode for now.
|
||||
f = pygame_font.Font(None, 20)
|
||||
um = f.metrics(".")
|
||||
bm = f.metrics(b".")
|
||||
|
||||
self.assertEqual(len(um), 1)
|
||||
self.assertEqual(len(bm), 1)
|
||||
self.assertIsNotNone(um[0])
|
||||
self.assertEqual(um, bm)
|
||||
|
||||
u = "\u212A"
|
||||
b = u.encode("UTF-16")[2:] # Keep byte order consistent. [2:] skips BOM
|
||||
bm = f.metrics(b)
|
||||
|
||||
self.assertEqual(len(bm), 2)
|
||||
|
||||
try: # FIXME why do we do this try/except ?
|
||||
um = f.metrics(u)
|
||||
except pygame.error:
|
||||
pass
|
||||
else:
|
||||
self.assertEqual(len(um), 1)
|
||||
self.assertNotEqual(bm[0], um[0])
|
||||
self.assertNotEqual(bm[1], um[0])
|
||||
|
||||
u = "\U00013000"
|
||||
bm = f.metrics(u)
|
||||
|
||||
self.assertEqual(len(bm), 1)
|
||||
self.assertIsNone(bm[0])
|
||||
|
||||
return # unfinished
|
||||
# The documentation is useless here. How large a list?
|
||||
# How do list positions relate to character codes?
|
||||
# What about unicode characters?
|
||||
|
||||
# __doc__ (as of 2008-08-02) for pygame_font.Font.metrics:
|
||||
|
||||
# Font.metrics(text): return list
|
||||
# Gets the metrics for each character in the passed string.
|
||||
#
|
||||
# The list contains tuples for each character, which contain the
|
||||
# minimum X offset, the maximum X offset, the minimum Y offset, the
|
||||
# maximum Y offset and the advance offset (bearing plus width) of the
|
||||
# character. [(minx, maxx, miny, maxy, advance), (minx, maxx, miny,
|
||||
# maxy, advance), ...]
|
||||
|
||||
self.fail()
|
||||
|
||||
def test_render(self):
|
||||
f = pygame_font.Font(None, 20)
|
||||
s = f.render("foo", True, [0, 0, 0], [255, 255, 255])
|
||||
s = f.render("xxx", True, [0, 0, 0], [255, 255, 255])
|
||||
s = f.render("", True, [0, 0, 0], [255, 255, 255])
|
||||
s = f.render("foo", False, [0, 0, 0], [255, 255, 255])
|
||||
s = f.render("xxx", False, [0, 0, 0], [255, 255, 255])
|
||||
s = f.render("xxx", False, [0, 0, 0])
|
||||
s = f.render(" ", False, [0, 0, 0])
|
||||
s = f.render(" ", False, [0, 0, 0], [255, 255, 255])
|
||||
# null text should be 0 pixel wide.
|
||||
s = f.render("", False, [0, 0, 0], [255, 255, 255])
|
||||
self.assertEqual(s.get_size()[0], 0)
|
||||
# None text should be 0 pixel wide.
|
||||
s = f.render(None, False, [0, 0, 0], [255, 255, 255])
|
||||
self.assertEqual(s.get_size()[0], 0)
|
||||
# Non-text should raise a TypeError.
|
||||
self.assertRaises(TypeError, f.render, [], False, [0, 0, 0], [255, 255, 255])
|
||||
self.assertRaises(TypeError, f.render, 1, False, [0, 0, 0], [255, 255, 255])
|
||||
# is background transparent for antialiasing?
|
||||
s = f.render(".", True, [255, 255, 255])
|
||||
self.assertEqual(s.get_at((0, 0))[3], 0)
|
||||
# is Unicode and bytes encoding correct?
|
||||
# Cannot really test if the correct characters are rendered, but
|
||||
# at least can assert the encodings differ.
|
||||
su = f.render(".", False, [0, 0, 0], [255, 255, 255])
|
||||
sb = f.render(b".", False, [0, 0, 0], [255, 255, 255])
|
||||
self.assertTrue(equal_images(su, sb))
|
||||
u = "\u212A"
|
||||
b = u.encode("UTF-16")[2:] # Keep byte order consistent. [2:] skips BOM
|
||||
sb = f.render(b, False, [0, 0, 0], [255, 255, 255])
|
||||
try: # FIXME why do we do this try/except ?
|
||||
su = f.render(u, False, [0, 0, 0], [255, 255, 255])
|
||||
except pygame.error:
|
||||
pass
|
||||
else:
|
||||
self.assertFalse(equal_images(su, sb))
|
||||
|
||||
# test for internal null bytes
|
||||
self.assertRaises(ValueError, f.render, b"ab\x00cd", 0, [0, 0, 0])
|
||||
self.assertRaises(ValueError, f.render, "ab\x00cd", 0, [0, 0, 0])
|
||||
|
||||
def test_render_ucs2_ucs4(self):
|
||||
"""that it renders without raising if there is a new enough SDL_ttf."""
|
||||
f = pygame_font.Font(None, 20)
|
||||
# If the font module is SDL_ttf < 2.0.15 based, then it only supports UCS-2
|
||||
# it will raise an exception for an out-of-range UCS-4 code point.
|
||||
if hasattr(pygame_font, "UCS4"):
|
||||
ucs_2 = "\uFFEE"
|
||||
s = f.render(ucs_2, False, [0, 0, 0], [255, 255, 255])
|
||||
ucs_4 = "\U00010000"
|
||||
s = f.render(ucs_4, False, [0, 0, 0], [255, 255, 255])
|
||||
|
||||
def test_set_bold(self):
|
||||
f = pygame_font.Font(None, 20)
|
||||
self.assertFalse(f.get_bold())
|
||||
f.set_bold(True)
|
||||
self.assertTrue(f.get_bold())
|
||||
f.set_bold(False)
|
||||
self.assertFalse(f.get_bold())
|
||||
|
||||
def test_set_italic(self):
|
||||
f = pygame_font.Font(None, 20)
|
||||
self.assertFalse(f.get_italic())
|
||||
f.set_italic(True)
|
||||
self.assertTrue(f.get_italic())
|
||||
f.set_italic(False)
|
||||
self.assertFalse(f.get_italic())
|
||||
|
||||
def test_set_underline(self):
|
||||
f = pygame_font.Font(None, 20)
|
||||
self.assertFalse(f.get_underline())
|
||||
f.set_underline(True)
|
||||
self.assertTrue(f.get_underline())
|
||||
f.set_underline(False)
|
||||
self.assertFalse(f.get_underline())
|
||||
|
||||
def test_set_strikethrough(self):
|
||||
if pygame_font.__name__ != "pygame.ftfont":
|
||||
f = pygame_font.Font(None, 20)
|
||||
self.assertFalse(f.get_strikethrough())
|
||||
f.set_strikethrough(True)
|
||||
self.assertTrue(f.get_strikethrough())
|
||||
f.set_strikethrough(False)
|
||||
self.assertFalse(f.get_strikethrough())
|
||||
|
||||
def test_bold_attr(self):
|
||||
f = pygame_font.Font(None, 20)
|
||||
self.assertFalse(f.bold)
|
||||
f.bold = True
|
||||
self.assertTrue(f.bold)
|
||||
f.bold = False
|
||||
self.assertFalse(f.bold)
|
||||
|
||||
def test_set_italic_property(self):
|
||||
f = pygame_font.Font(None, 20)
|
||||
self.assertFalse(f.italic)
|
||||
f.italic = True
|
||||
self.assertTrue(f.italic)
|
||||
f.italic = False
|
||||
self.assertFalse(f.italic)
|
||||
|
||||
def test_set_underline_property(self):
|
||||
f = pygame_font.Font(None, 20)
|
||||
self.assertFalse(f.underline)
|
||||
f.underline = True
|
||||
self.assertTrue(f.underline)
|
||||
f.underline = False
|
||||
self.assertFalse(f.underline)
|
||||
|
||||
def test_set_strikethrough_property(self):
|
||||
if pygame_font.__name__ != "pygame.ftfont":
|
||||
f = pygame_font.Font(None, 20)
|
||||
self.assertFalse(f.strikethrough)
|
||||
f.strikethrough = True
|
||||
self.assertTrue(f.strikethrough)
|
||||
f.strikethrough = False
|
||||
self.assertFalse(f.strikethrough)
|
||||
|
||||
def test_size(self):
|
||||
f = pygame_font.Font(None, 20)
|
||||
text = "Xg"
|
||||
size = f.size(text)
|
||||
w, h = size
|
||||
s = f.render(text, False, (255, 255, 255))
|
||||
btext = text.encode("ascii")
|
||||
|
||||
self.assertIsInstance(w, int)
|
||||
self.assertIsInstance(h, int)
|
||||
self.assertEqual(s.get_size(), size)
|
||||
self.assertEqual(f.size(btext), size)
|
||||
|
||||
text = "\u212A"
|
||||
btext = text.encode("UTF-16")[2:] # Keep the byte order consistent.
|
||||
bsize = f.size(btext)
|
||||
size = f.size(text)
|
||||
|
||||
self.assertNotEqual(size, bsize)
|
||||
|
||||
def test_font_file_not_found(self):
|
||||
# A per BUG reported by Bo Jangeborg on pygame-user mailing list,
|
||||
# http://www.mail-archive.com/pygame-users@seul.org/msg11675.html
|
||||
|
||||
pygame_font.init()
|
||||
self.assertRaises(
|
||||
FileNotFoundError, pygame_font.Font, "some-fictional-font.ttf", 20
|
||||
)
|
||||
|
||||
def test_load_from_file(self):
|
||||
font_name = pygame_font.get_default_font()
|
||||
font_path = os.path.join(
|
||||
os.path.split(pygame.__file__)[0], pygame_font.get_default_font()
|
||||
)
|
||||
f = pygame_font.Font(font_path, 20)
|
||||
|
||||
def test_load_from_file_default(self):
|
||||
font_name = pygame_font.get_default_font()
|
||||
font_path = os.path.join(
|
||||
os.path.split(pygame.__file__)[0], pygame_font.get_default_font()
|
||||
)
|
||||
f = pygame_font.Font(font_path)
|
||||
|
||||
def test_load_from_pathlib(self):
|
||||
font_name = pygame_font.get_default_font()
|
||||
font_path = os.path.join(
|
||||
os.path.split(pygame.__file__)[0], pygame_font.get_default_font()
|
||||
)
|
||||
f = pygame_font.Font(pathlib.Path(font_path), 20)
|
||||
f = pygame_font.Font(pathlib.Path(font_path))
|
||||
|
||||
def test_load_from_pathlib_default(self):
|
||||
font_name = pygame_font.get_default_font()
|
||||
font_path = os.path.join(
|
||||
os.path.split(pygame.__file__)[0], pygame_font.get_default_font()
|
||||
)
|
||||
f = pygame_font.Font(pathlib.Path(font_path))
|
||||
|
||||
def test_load_from_file_obj(self):
|
||||
font_name = pygame_font.get_default_font()
|
||||
font_path = os.path.join(
|
||||
os.path.split(pygame.__file__)[0], pygame_font.get_default_font()
|
||||
)
|
||||
with open(font_path, "rb") as f:
|
||||
font = pygame_font.Font(f, 20)
|
||||
|
||||
def test_load_from_file_obj_default(self):
|
||||
font_name = pygame_font.get_default_font()
|
||||
font_path = os.path.join(
|
||||
os.path.split(pygame.__file__)[0], pygame_font.get_default_font()
|
||||
)
|
||||
with open(font_path, "rb") as f:
|
||||
font = pygame_font.Font(f)
|
||||
|
||||
def test_load_default_font_filename(self):
|
||||
# In font_init, a special case is when the filename argument is
|
||||
# identical to the default font file name.
|
||||
f = pygame_font.Font(pygame_font.get_default_font(), 20)
|
||||
|
||||
def test_load_default_font_filename_default(self):
|
||||
# In font_init, a special case is when the filename argument is
|
||||
# identical to the default font file name.
|
||||
f = pygame_font.Font(pygame_font.get_default_font())
|
||||
|
||||
def _load_unicode(self, path):
|
||||
import shutil
|
||||
|
||||
fdir = str(FONTDIR)
|
||||
temp = os.path.join(fdir, path)
|
||||
pgfont = os.path.join(fdir, "test_sans.ttf")
|
||||
shutil.copy(pgfont, temp)
|
||||
try:
|
||||
with open(temp, "rb") as f:
|
||||
pass
|
||||
except FileNotFoundError:
|
||||
raise unittest.SkipTest("the path cannot be opened")
|
||||
try:
|
||||
pygame_font.Font(temp, 20)
|
||||
finally:
|
||||
os.remove(temp)
|
||||
|
||||
def test_load_from_file_unicode_0(self):
|
||||
"""ASCII string as a unicode object"""
|
||||
self._load_unicode("temp_file.ttf")
|
||||
|
||||
def test_load_from_file_unicode_1(self):
|
||||
self._load_unicode("你好.ttf")
|
||||
|
||||
def test_load_from_file_bytes(self):
|
||||
font_path = os.path.join(
|
||||
os.path.split(pygame.__file__)[0], pygame_font.get_default_font()
|
||||
)
|
||||
filesystem_encoding = sys.getfilesystemencoding()
|
||||
filesystem_errors = "replace" if sys.platform == "win32" else "surrogateescape"
|
||||
try: # FIXME why do we do this try/except ?
|
||||
font_path = font_path.decode(filesystem_encoding, filesystem_errors)
|
||||
except AttributeError:
|
||||
pass
|
||||
bfont_path = font_path.encode(filesystem_encoding, filesystem_errors)
|
||||
f = pygame_font.Font(bfont_path, 20)
|
||||
|
||||
def test_issue_3144(self):
|
||||
fpath = os.path.join(FONTDIR, "PlayfairDisplaySemibold.ttf")
|
||||
|
||||
# issue in SDL_ttf 2.0.18 DLL on Windows
|
||||
# tested to make us aware of any regressions
|
||||
for size in (60, 40, 10, 20, 70, 45, 50, 10):
|
||||
font = pygame_font.Font(fpath, size)
|
||||
font.render("WHERE", True, "black")
|
||||
|
||||
def test_font_set_script(self):
|
||||
if pygame_font.__name__ == "pygame.ftfont":
|
||||
return # this ain't a pygame.ftfont thing!
|
||||
|
||||
font = pygame_font.Font(None, 16)
|
||||
|
||||
ttf_version = pygame_font.get_sdl_ttf_version()
|
||||
if ttf_version >= (2, 20, 0):
|
||||
self.assertRaises(TypeError, pygame.font.Font.set_script)
|
||||
self.assertRaises(TypeError, pygame.font.Font.set_script, font)
|
||||
self.assertRaises(TypeError, pygame.font.Font.set_script, "hey", "Deva")
|
||||
self.assertRaises(TypeError, font.set_script, 1)
|
||||
self.assertRaises(TypeError, font.set_script, ["D", "e", "v", "a"])
|
||||
|
||||
self.assertRaises(ValueError, font.set_script, "too long by far")
|
||||
self.assertRaises(ValueError, font.set_script, "")
|
||||
self.assertRaises(ValueError, font.set_script, "a")
|
||||
|
||||
font.set_script("Deva")
|
||||
else:
|
||||
self.assertRaises(pygame.error, font.set_script, "Deva")
|
||||
|
||||
|
||||
@unittest.skipIf(IS_PYPY, "pypy skip known failure") # TODO
|
||||
class VisualTests(unittest.TestCase):
|
||||
__tags__ = ["interactive"]
|
||||
|
||||
screen = None
|
||||
aborted = False
|
||||
|
||||
def setUp(self):
|
||||
if self.screen is None:
|
||||
pygame.init()
|
||||
self.screen = pygame.display.set_mode((600, 200))
|
||||
self.screen.fill((255, 255, 255))
|
||||
pygame.display.flip()
|
||||
self.f = pygame_font.Font(None, 32)
|
||||
|
||||
def abort(self):
|
||||
if self.screen is not None:
|
||||
pygame.quit()
|
||||
self.aborted = True
|
||||
|
||||
def query(
|
||||
self,
|
||||
bold=False,
|
||||
italic=False,
|
||||
underline=False,
|
||||
strikethrough=False,
|
||||
antialiase=False,
|
||||
):
|
||||
if self.aborted:
|
||||
return False
|
||||
spacing = 10
|
||||
offset = 20
|
||||
y = spacing
|
||||
f = self.f
|
||||
screen = self.screen
|
||||
screen.fill((255, 255, 255))
|
||||
pygame.display.flip()
|
||||
if not (bold or italic or underline or strikethrough or antialiase):
|
||||
text = "normal"
|
||||
else:
|
||||
modes = []
|
||||
if bold:
|
||||
modes.append("bold")
|
||||
if italic:
|
||||
modes.append("italic")
|
||||
if underline:
|
||||
modes.append("underlined")
|
||||
if strikethrough:
|
||||
modes.append("strikethrough")
|
||||
if antialiase:
|
||||
modes.append("antialiased")
|
||||
text = f"{'-'.join(modes)} (y/n):"
|
||||
f.set_bold(bold)
|
||||
f.set_italic(italic)
|
||||
f.set_underline(underline)
|
||||
if pygame_font.__name__ != "pygame.ftfont":
|
||||
f.set_strikethrough(strikethrough)
|
||||
s = f.render(text, antialiase, (0, 0, 0))
|
||||
screen.blit(s, (offset, y))
|
||||
y += s.get_size()[1] + spacing
|
||||
f.set_bold(False)
|
||||
f.set_italic(False)
|
||||
f.set_underline(False)
|
||||
if pygame_font.__name__ != "pygame.ftfont":
|
||||
f.set_strikethrough(False)
|
||||
s = f.render("(some comparison text)", False, (0, 0, 0))
|
||||
screen.blit(s, (offset, y))
|
||||
pygame.display.flip()
|
||||
while True:
|
||||
for evt in pygame.event.get():
|
||||
if evt.type == pygame.KEYDOWN:
|
||||
if evt.key == pygame.K_ESCAPE:
|
||||
self.abort()
|
||||
return False
|
||||
if evt.key == pygame.K_y:
|
||||
return True
|
||||
if evt.key == pygame.K_n:
|
||||
return False
|
||||
if evt.type == pygame.QUIT:
|
||||
self.abort()
|
||||
return False
|
||||
|
||||
def test_bold(self):
|
||||
self.assertTrue(self.query(bold=True))
|
||||
|
||||
def test_italic(self):
|
||||
self.assertTrue(self.query(italic=True))
|
||||
|
||||
def test_underline(self):
|
||||
self.assertTrue(self.query(underline=True))
|
||||
|
||||
def test_strikethrough(self):
|
||||
if pygame_font.__name__ != "pygame.ftfont":
|
||||
self.assertTrue(self.query(strikethrough=True))
|
||||
|
||||
def test_antialiase(self):
|
||||
self.assertTrue(self.query(antialiase=True))
|
||||
|
||||
def test_bold_antialiase(self):
|
||||
self.assertTrue(self.query(bold=True, antialiase=True))
|
||||
|
||||
def test_italic_underline(self):
|
||||
self.assertTrue(self.query(italic=True, underline=True))
|
||||
|
||||
def test_bold_strikethrough(self):
|
||||
if pygame_font.__name__ != "pygame.ftfont":
|
||||
self.assertTrue(self.query(bold=True, strikethrough=True))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
@@ -0,0 +1,11 @@
|
||||
__tags__ = ["development"]
|
||||
|
||||
exclude = False
|
||||
|
||||
try:
|
||||
import pygame.freetype
|
||||
except ImportError:
|
||||
exclude = True
|
||||
|
||||
if exclude:
|
||||
__tags__.extend(["ignore", "subprocess_ignore"])
|
1796
.venv/lib/python3.7/site-packages/pygame/tests/freetype_test.py
Normal file
1796
.venv/lib/python3.7/site-packages/pygame/tests/freetype_test.py
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,11 @@
|
||||
__tags__ = ["development"]
|
||||
|
||||
exclude = False
|
||||
|
||||
try:
|
||||
import pygame.ftfont
|
||||
except ImportError:
|
||||
exclude = True
|
||||
|
||||
if exclude:
|
||||
__tags__.extend(["ignore", "subprocess_ignore"])
|
@@ -0,0 +1,17 @@
|
||||
import sys
|
||||
import os
|
||||
import unittest
|
||||
from pygame.tests import font_test
|
||||
|
||||
import pygame.ftfont
|
||||
|
||||
font_test.pygame_font = pygame.ftfont
|
||||
|
||||
for name in dir(font_test):
|
||||
obj = getattr(font_test, name)
|
||||
if isinstance(obj, type) and issubclass(obj, unittest.TestCase): # conditional and
|
||||
new_name = f"Ft{name}"
|
||||
globals()[new_name] = type(new_name, (obj,), {})
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
876
.venv/lib/python3.7/site-packages/pygame/tests/gfxdraw_test.py
Normal file
876
.venv/lib/python3.7/site-packages/pygame/tests/gfxdraw_test.py
Normal file
@@ -0,0 +1,876 @@
|
||||
import unittest
|
||||
import pygame
|
||||
import pygame.gfxdraw
|
||||
from pygame.locals import *
|
||||
from pygame.tests.test_utils import SurfaceSubclass
|
||||
|
||||
|
||||
def intensity(c, i):
|
||||
"""Return color c changed by intensity i
|
||||
|
||||
For 0 <= i <= 127 the color is a shade, with 0 being black, 127 being the
|
||||
unaltered color.
|
||||
|
||||
For 128 <= i <= 255 the color is a tint, with 255 being white, 128 the
|
||||
unaltered color.
|
||||
|
||||
"""
|
||||
r, g, b = c[0:3]
|
||||
if 0 <= i <= 127:
|
||||
# Darken
|
||||
return ((r * i) // 127, (g * i) // 127, (b * i) // 127)
|
||||
# Lighten
|
||||
return (
|
||||
r + ((255 - r) * (255 - i)) // 127,
|
||||
g + ((255 - g) * (255 - i)) // 127,
|
||||
b + ((255 - b) * (255 - i)) // 127,
|
||||
)
|
||||
|
||||
|
||||
class GfxdrawDefaultTest(unittest.TestCase):
|
||||
is_started = False
|
||||
|
||||
foreground_color = (128, 64, 8)
|
||||
background_color = (255, 255, 255)
|
||||
|
||||
def make_palette(base_color):
|
||||
"""Return color palette that is various intensities of base_color"""
|
||||
# Need this function for Python 3.x so the base_color
|
||||
# is within the scope of the list comprehension.
|
||||
return [intensity(base_color, i) for i in range(0, 256)]
|
||||
|
||||
default_palette = make_palette(foreground_color)
|
||||
|
||||
default_size = (100, 100)
|
||||
|
||||
def check_at(self, surf, posn, color):
|
||||
sc = surf.get_at(posn)
|
||||
fail_msg = "%s != %s at %s, bitsize: %i, flags: %i, masks: %s" % (
|
||||
sc,
|
||||
color,
|
||||
posn,
|
||||
surf.get_bitsize(),
|
||||
surf.get_flags(),
|
||||
surf.get_masks(),
|
||||
)
|
||||
self.assertEqual(sc, color, fail_msg)
|
||||
|
||||
def check_not_at(self, surf, posn, color):
|
||||
sc = surf.get_at(posn)
|
||||
fail_msg = "%s != %s at %s, bitsize: %i, flags: %i, masks: %s" % (
|
||||
sc,
|
||||
color,
|
||||
posn,
|
||||
surf.get_bitsize(),
|
||||
surf.get_flags(),
|
||||
surf.get_masks(),
|
||||
)
|
||||
self.assertNotEqual(sc, color, fail_msg)
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
# Necessary for Surface.set_palette.
|
||||
pygame.init()
|
||||
pygame.display.set_mode((1, 1))
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
pygame.quit()
|
||||
|
||||
def setUp(self):
|
||||
# This makes sure pygame is always initialized before each test (in
|
||||
# case a test calls pygame.quit()).
|
||||
if not pygame.get_init():
|
||||
pygame.init()
|
||||
|
||||
Surface = pygame.Surface
|
||||
size = self.default_size
|
||||
palette = self.default_palette
|
||||
if not self.is_started:
|
||||
# Create test surfaces
|
||||
self.surfaces = [
|
||||
Surface(size, 0, 8),
|
||||
Surface(size, SRCALPHA, 16),
|
||||
Surface(size, SRCALPHA, 32),
|
||||
]
|
||||
self.surfaces[0].set_palette(palette)
|
||||
nonpalette_fmts = (
|
||||
# (8, (0xe0, 0x1c, 0x3, 0x0)),
|
||||
(12, (0xF00, 0xF0, 0xF, 0x0)),
|
||||
(15, (0x7C00, 0x3E0, 0x1F, 0x0)),
|
||||
(15, (0x1F, 0x3E0, 0x7C00, 0x0)),
|
||||
(16, (0xF00, 0xF0, 0xF, 0xF000)),
|
||||
(16, (0xF000, 0xF00, 0xF0, 0xF)),
|
||||
(16, (0xF, 0xF0, 0xF00, 0xF000)),
|
||||
(16, (0xF0, 0xF00, 0xF000, 0xF)),
|
||||
(16, (0x7C00, 0x3E0, 0x1F, 0x8000)),
|
||||
(16, (0xF800, 0x7C0, 0x3E, 0x1)),
|
||||
(16, (0x1F, 0x3E0, 0x7C00, 0x8000)),
|
||||
(16, (0x3E, 0x7C0, 0xF800, 0x1)),
|
||||
(16, (0xF800, 0x7E0, 0x1F, 0x0)),
|
||||
(16, (0x1F, 0x7E0, 0xF800, 0x0)),
|
||||
(24, (0xFF, 0xFF00, 0xFF0000, 0x0)),
|
||||
(24, (0xFF0000, 0xFF00, 0xFF, 0x0)),
|
||||
(32, (0xFF0000, 0xFF00, 0xFF, 0x0)),
|
||||
(32, (0xFF000000, 0xFF0000, 0xFF00, 0x0)),
|
||||
(32, (0xFF, 0xFF00, 0xFF0000, 0x0)),
|
||||
(32, (0xFF00, 0xFF0000, 0xFF000000, 0x0)),
|
||||
(32, (0xFF0000, 0xFF00, 0xFF, 0xFF000000)),
|
||||
(32, (0xFF000000, 0xFF0000, 0xFF00, 0xFF)),
|
||||
(32, (0xFF, 0xFF00, 0xFF0000, 0xFF000000)),
|
||||
(32, (0xFF00, 0xFF0000, 0xFF000000, 0xFF)),
|
||||
)
|
||||
for bitsize, masks in nonpalette_fmts:
|
||||
self.surfaces.append(Surface(size, 0, bitsize, masks))
|
||||
for surf in self.surfaces:
|
||||
surf.fill(self.background_color)
|
||||
|
||||
def test_gfxdraw__subclassed_surface(self):
|
||||
"""Ensure pygame.gfxdraw works on subclassed surfaces."""
|
||||
surface = SurfaceSubclass((11, 13), SRCALPHA, 32)
|
||||
surface.fill(pygame.Color("blue"))
|
||||
expected_color = pygame.Color("red")
|
||||
x, y = 1, 2
|
||||
|
||||
pygame.gfxdraw.pixel(surface, x, y, expected_color)
|
||||
|
||||
self.assertEqual(surface.get_at((x, y)), expected_color)
|
||||
|
||||
def test_pixel(self):
|
||||
"""pixel(surface, x, y, color): return None"""
|
||||
fg = self.foreground_color
|
||||
bg = self.background_color
|
||||
for surf in self.surfaces:
|
||||
fg_adjusted = surf.unmap_rgb(surf.map_rgb(fg))
|
||||
bg_adjusted = surf.unmap_rgb(surf.map_rgb(bg))
|
||||
pygame.gfxdraw.pixel(surf, 2, 2, fg)
|
||||
for x in range(1, 4):
|
||||
for y in range(1, 4):
|
||||
if x == 2 and y == 2:
|
||||
self.check_at(surf, (x, y), fg_adjusted)
|
||||
else:
|
||||
self.check_at(surf, (x, y), bg_adjusted)
|
||||
|
||||
def test_hline(self):
|
||||
"""hline(surface, x1, x2, y, color): return None"""
|
||||
fg = self.foreground_color
|
||||
bg = self.background_color
|
||||
startx = 10
|
||||
stopx = 80
|
||||
y = 50
|
||||
fg_test_points = [(startx, y), (stopx, y), ((stopx - startx) // 2, y)]
|
||||
bg_test_points = [
|
||||
(startx - 1, y),
|
||||
(stopx + 1, y),
|
||||
(startx, y - 1),
|
||||
(startx, y + 1),
|
||||
(stopx, y - 1),
|
||||
(stopx, y + 1),
|
||||
]
|
||||
for surf in self.surfaces:
|
||||
fg_adjusted = surf.unmap_rgb(surf.map_rgb(fg))
|
||||
bg_adjusted = surf.unmap_rgb(surf.map_rgb(bg))
|
||||
pygame.gfxdraw.hline(surf, startx, stopx, y, fg)
|
||||
for posn in fg_test_points:
|
||||
self.check_at(surf, posn, fg_adjusted)
|
||||
for posn in bg_test_points:
|
||||
self.check_at(surf, posn, bg_adjusted)
|
||||
|
||||
def test_vline(self):
|
||||
"""vline(surface, x, y1, y2, color): return None"""
|
||||
fg = self.foreground_color
|
||||
bg = self.background_color
|
||||
x = 50
|
||||
starty = 10
|
||||
stopy = 80
|
||||
fg_test_points = [(x, starty), (x, stopy), (x, (stopy - starty) // 2)]
|
||||
bg_test_points = [
|
||||
(x, starty - 1),
|
||||
(x, stopy + 1),
|
||||
(x - 1, starty),
|
||||
(x + 1, starty),
|
||||
(x - 1, stopy),
|
||||
(x + 1, stopy),
|
||||
]
|
||||
for surf in self.surfaces:
|
||||
fg_adjusted = surf.unmap_rgb(surf.map_rgb(fg))
|
||||
bg_adjusted = surf.unmap_rgb(surf.map_rgb(bg))
|
||||
pygame.gfxdraw.vline(surf, x, starty, stopy, fg)
|
||||
for posn in fg_test_points:
|
||||
self.check_at(surf, posn, fg_adjusted)
|
||||
for posn in bg_test_points:
|
||||
self.check_at(surf, posn, bg_adjusted)
|
||||
|
||||
def test_rectangle(self):
|
||||
"""rectangle(surface, rect, color): return None"""
|
||||
fg = self.foreground_color
|
||||
bg = self.background_color
|
||||
rect = pygame.Rect(10, 15, 55, 62)
|
||||
rect_tuple = tuple(rect)
|
||||
fg_test_points = [
|
||||
rect.topleft,
|
||||
(rect.right - 1, rect.top),
|
||||
(rect.left, rect.bottom - 1),
|
||||
(rect.right - 1, rect.bottom - 1),
|
||||
]
|
||||
bg_test_points = [
|
||||
(rect.left - 1, rect.top - 1),
|
||||
(rect.left + 1, rect.top + 1),
|
||||
(rect.right, rect.top - 1),
|
||||
(rect.right - 2, rect.top + 1),
|
||||
(rect.left - 1, rect.bottom),
|
||||
(rect.left + 1, rect.bottom - 2),
|
||||
(rect.right, rect.bottom),
|
||||
(rect.right - 2, rect.bottom - 2),
|
||||
]
|
||||
for surf in self.surfaces:
|
||||
fg_adjusted = surf.unmap_rgb(surf.map_rgb(fg))
|
||||
bg_adjusted = surf.unmap_rgb(surf.map_rgb(bg))
|
||||
pygame.gfxdraw.rectangle(surf, rect, fg)
|
||||
for posn in fg_test_points:
|
||||
self.check_at(surf, posn, fg_adjusted)
|
||||
for posn in bg_test_points:
|
||||
self.check_at(surf, posn, bg_adjusted)
|
||||
surf.fill(bg)
|
||||
pygame.gfxdraw.rectangle(surf, rect_tuple, fg)
|
||||
for posn in fg_test_points:
|
||||
self.check_at(surf, posn, fg_adjusted)
|
||||
for posn in bg_test_points:
|
||||
self.check_at(surf, posn, bg_adjusted)
|
||||
|
||||
def test_box(self):
|
||||
"""box(surface, rect, color): return None"""
|
||||
fg = self.foreground_color
|
||||
bg = self.background_color
|
||||
rect = pygame.Rect(10, 15, 55, 62)
|
||||
rect_tuple = tuple(rect)
|
||||
fg_test_points = [
|
||||
rect.topleft,
|
||||
(rect.left + 1, rect.top + 1),
|
||||
(rect.right - 1, rect.top),
|
||||
(rect.right - 2, rect.top + 1),
|
||||
(rect.left, rect.bottom - 1),
|
||||
(rect.left + 1, rect.bottom - 2),
|
||||
(rect.right - 1, rect.bottom - 1),
|
||||
(rect.right - 2, rect.bottom - 2),
|
||||
]
|
||||
bg_test_points = [
|
||||
(rect.left - 1, rect.top - 1),
|
||||
(rect.right, rect.top - 1),
|
||||
(rect.left - 1, rect.bottom),
|
||||
(rect.right, rect.bottom),
|
||||
]
|
||||
for surf in self.surfaces:
|
||||
fg_adjusted = surf.unmap_rgb(surf.map_rgb(fg))
|
||||
bg_adjusted = surf.unmap_rgb(surf.map_rgb(bg))
|
||||
pygame.gfxdraw.box(surf, rect, fg)
|
||||
for posn in fg_test_points:
|
||||
self.check_at(surf, posn, fg_adjusted)
|
||||
for posn in bg_test_points:
|
||||
self.check_at(surf, posn, bg_adjusted)
|
||||
surf.fill(bg)
|
||||
pygame.gfxdraw.box(surf, rect_tuple, fg)
|
||||
for posn in fg_test_points:
|
||||
self.check_at(surf, posn, fg_adjusted)
|
||||
for posn in bg_test_points:
|
||||
self.check_at(surf, posn, bg_adjusted)
|
||||
|
||||
def test_line(self):
|
||||
"""line(surface, x1, y1, x2, y2, color): return None"""
|
||||
fg = self.foreground_color
|
||||
bg = self.background_color
|
||||
x1 = 10
|
||||
y1 = 15
|
||||
x2 = 92
|
||||
y2 = 77
|
||||
fg_test_points = [(x1, y1), (x2, y2)]
|
||||
bg_test_points = [
|
||||
(x1 - 1, y1),
|
||||
(x1, y1 - 1),
|
||||
(x1 - 1, y1 - 1),
|
||||
(x2 + 1, y2),
|
||||
(x2, y2 + 1),
|
||||
(x2 + 1, y2 + 1),
|
||||
]
|
||||
for surf in self.surfaces:
|
||||
fg_adjusted = surf.unmap_rgb(surf.map_rgb(fg))
|
||||
bg_adjusted = surf.unmap_rgb(surf.map_rgb(bg))
|
||||
pygame.gfxdraw.line(surf, x1, y1, x2, y2, fg)
|
||||
for posn in fg_test_points:
|
||||
self.check_at(surf, posn, fg_adjusted)
|
||||
for posn in bg_test_points:
|
||||
self.check_at(surf, posn, bg_adjusted)
|
||||
|
||||
def test_circle(self):
|
||||
"""circle(surface, x, y, r, color): return None"""
|
||||
fg = self.foreground_color
|
||||
bg = self.background_color
|
||||
x = 45
|
||||
y = 40
|
||||
r = 30
|
||||
fg_test_points = [(x, y - r), (x, y + r), (x - r, y), (x + r, y)]
|
||||
bg_test_points = [
|
||||
(x, y),
|
||||
(x, y - r + 1),
|
||||
(x, y - r - 1),
|
||||
(x, y + r + 1),
|
||||
(x, y + r - 1),
|
||||
(x - r - 1, y),
|
||||
(x - r + 1, y),
|
||||
(x + r + 1, y),
|
||||
(x + r - 1, y),
|
||||
]
|
||||
for surf in self.surfaces:
|
||||
fg_adjusted = surf.unmap_rgb(surf.map_rgb(fg))
|
||||
bg_adjusted = surf.unmap_rgb(surf.map_rgb(bg))
|
||||
pygame.gfxdraw.circle(surf, x, y, r, fg)
|
||||
for posn in fg_test_points:
|
||||
self.check_at(surf, posn, fg_adjusted)
|
||||
for posn in bg_test_points:
|
||||
self.check_at(surf, posn, bg_adjusted)
|
||||
|
||||
def test_arc(self):
|
||||
"""arc(surface, x, y, r, start, end, color): return None"""
|
||||
fg = self.foreground_color
|
||||
bg = self.background_color
|
||||
x = 45
|
||||
y = 40
|
||||
r = 30
|
||||
start = 0 # +x direction, but not (x + r, y) (?)
|
||||
end = 90 # -y direction, including (x, y + r)
|
||||
fg_test_points = [(x, y + r), (x + r, y + 1)]
|
||||
bg_test_points = [
|
||||
(x, y),
|
||||
(x, y - r),
|
||||
(x - r, y),
|
||||
(x, y + r + 1),
|
||||
(x, y + r - 1),
|
||||
(x - 1, y + r),
|
||||
(x + r + 1, y),
|
||||
(x + r - 1, y),
|
||||
(x + r, y),
|
||||
]
|
||||
for surf in self.surfaces:
|
||||
fg_adjusted = surf.unmap_rgb(surf.map_rgb(fg))
|
||||
bg_adjusted = surf.unmap_rgb(surf.map_rgb(bg))
|
||||
pygame.gfxdraw.arc(surf, x, y, r, start, end, fg)
|
||||
for posn in fg_test_points:
|
||||
self.check_at(surf, posn, fg_adjusted)
|
||||
for posn in bg_test_points:
|
||||
self.check_at(surf, posn, bg_adjusted)
|
||||
|
||||
def test_aacircle(self):
|
||||
"""aacircle(surface, x, y, r, color): return None"""
|
||||
fg = self.foreground_color
|
||||
bg = self.background_color
|
||||
x = 45
|
||||
y = 40
|
||||
r = 30
|
||||
fg_test_points = [(x, y - r), (x, y + r), (x - r, y), (x + r, y)]
|
||||
bg_test_points = [
|
||||
(x, y),
|
||||
(x, y - r + 1),
|
||||
(x, y - r - 1),
|
||||
(x, y + r + 1),
|
||||
(x, y + r - 1),
|
||||
(x - r - 1, y),
|
||||
(x - r + 1, y),
|
||||
(x + r + 1, y),
|
||||
(x + r - 1, y),
|
||||
]
|
||||
for surf in self.surfaces:
|
||||
fg_adjusted = surf.unmap_rgb(surf.map_rgb(fg))
|
||||
bg_adjusted = surf.unmap_rgb(surf.map_rgb(bg))
|
||||
pygame.gfxdraw.aacircle(surf, x, y, r, fg)
|
||||
for posn in fg_test_points:
|
||||
self.check_not_at(surf, posn, bg_adjusted)
|
||||
for posn in bg_test_points:
|
||||
self.check_at(surf, posn, bg_adjusted)
|
||||
|
||||
def test_filled_circle(self):
|
||||
"""filled_circle(surface, x, y, r, color): return None"""
|
||||
fg = self.foreground_color
|
||||
bg = self.background_color
|
||||
x = 45
|
||||
y = 40
|
||||
r = 30
|
||||
fg_test_points = [
|
||||
(x, y - r),
|
||||
(x, y - r + 1),
|
||||
(x, y + r),
|
||||
(x, y + r - 1),
|
||||
(x - r, y),
|
||||
(x - r + 1, y),
|
||||
(x + r, y),
|
||||
(x + r - 1, y),
|
||||
(x, y),
|
||||
]
|
||||
bg_test_points = [
|
||||
(x, y - r - 1),
|
||||
(x, y + r + 1),
|
||||
(x - r - 1, y),
|
||||
(x + r + 1, y),
|
||||
]
|
||||
for surf in self.surfaces:
|
||||
fg_adjusted = surf.unmap_rgb(surf.map_rgb(fg))
|
||||
bg_adjusted = surf.unmap_rgb(surf.map_rgb(bg))
|
||||
pygame.gfxdraw.filled_circle(surf, x, y, r, fg)
|
||||
for posn in fg_test_points:
|
||||
self.check_at(surf, posn, fg_adjusted)
|
||||
for posn in bg_test_points:
|
||||
self.check_at(surf, posn, bg_adjusted)
|
||||
|
||||
def test_ellipse(self):
|
||||
"""ellipse(surface, x, y, rx, ry, color): return None"""
|
||||
fg = self.foreground_color
|
||||
bg = self.background_color
|
||||
x = 45
|
||||
y = 40
|
||||
rx = 30
|
||||
ry = 35
|
||||
fg_test_points = [(x, y - ry), (x, y + ry), (x - rx, y), (x + rx, y)]
|
||||
bg_test_points = [
|
||||
(x, y),
|
||||
(x, y - ry + 1),
|
||||
(x, y - ry - 1),
|
||||
(x, y + ry + 1),
|
||||
(x, y + ry - 1),
|
||||
(x - rx - 1, y),
|
||||
(x - rx + 1, y),
|
||||
(x + rx + 1, y),
|
||||
(x + rx - 1, y),
|
||||
]
|
||||
for surf in self.surfaces:
|
||||
fg_adjusted = surf.unmap_rgb(surf.map_rgb(fg))
|
||||
bg_adjusted = surf.unmap_rgb(surf.map_rgb(bg))
|
||||
pygame.gfxdraw.ellipse(surf, x, y, rx, ry, fg)
|
||||
for posn in fg_test_points:
|
||||
self.check_at(surf, posn, fg_adjusted)
|
||||
for posn in bg_test_points:
|
||||
self.check_at(surf, posn, bg_adjusted)
|
||||
|
||||
def test_aaellipse(self):
|
||||
"""aaellipse(surface, x, y, rx, ry, color): return None"""
|
||||
fg = self.foreground_color
|
||||
bg = self.background_color
|
||||
x = 45
|
||||
y = 40
|
||||
rx = 30
|
||||
ry = 35
|
||||
fg_test_points = [(x, y - ry), (x, y + ry), (x - rx, y), (x + rx, y)]
|
||||
bg_test_points = [
|
||||
(x, y),
|
||||
(x, y - ry + 1),
|
||||
(x, y - ry - 1),
|
||||
(x, y + ry + 1),
|
||||
(x, y + ry - 1),
|
||||
(x - rx - 1, y),
|
||||
(x - rx + 1, y),
|
||||
(x + rx + 1, y),
|
||||
(x + rx - 1, y),
|
||||
]
|
||||
for surf in self.surfaces:
|
||||
fg_adjusted = surf.unmap_rgb(surf.map_rgb(fg))
|
||||
bg_adjusted = surf.unmap_rgb(surf.map_rgb(bg))
|
||||
pygame.gfxdraw.aaellipse(surf, x, y, rx, ry, fg)
|
||||
for posn in fg_test_points:
|
||||
self.check_not_at(surf, posn, bg_adjusted)
|
||||
for posn in bg_test_points:
|
||||
self.check_at(surf, posn, bg_adjusted)
|
||||
|
||||
def test_filled_ellipse(self):
|
||||
"""filled_ellipse(surface, x, y, rx, ry, color): return None"""
|
||||
fg = self.foreground_color
|
||||
bg = self.background_color
|
||||
x = 45
|
||||
y = 40
|
||||
rx = 30
|
||||
ry = 35
|
||||
fg_test_points = [
|
||||
(x, y - ry),
|
||||
(x, y - ry + 1),
|
||||
(x, y + ry),
|
||||
(x, y + ry - 1),
|
||||
(x - rx, y),
|
||||
(x - rx + 1, y),
|
||||
(x + rx, y),
|
||||
(x + rx - 1, y),
|
||||
(x, y),
|
||||
]
|
||||
bg_test_points = [
|
||||
(x, y - ry - 1),
|
||||
(x, y + ry + 1),
|
||||
(x - rx - 1, y),
|
||||
(x + rx + 1, y),
|
||||
]
|
||||
for surf in self.surfaces:
|
||||
fg_adjusted = surf.unmap_rgb(surf.map_rgb(fg))
|
||||
bg_adjusted = surf.unmap_rgb(surf.map_rgb(bg))
|
||||
pygame.gfxdraw.filled_ellipse(surf, x, y, rx, ry, fg)
|
||||
for posn in fg_test_points:
|
||||
self.check_at(surf, posn, fg_adjusted)
|
||||
for posn in bg_test_points:
|
||||
self.check_at(surf, posn, bg_adjusted)
|
||||
|
||||
def test_pie(self):
|
||||
"""pie(surface, x, y, r, start, end, color): return None"""
|
||||
fg = self.foreground_color
|
||||
bg = self.background_color
|
||||
x = 45
|
||||
y = 40
|
||||
r = 30
|
||||
start = 0 # +x direction, including (x + r, y)
|
||||
end = 90 # -y direction, but not (x, y + r) (?)
|
||||
fg_test_points = [(x, y), (x + 1, y), (x, y + 1), (x + r, y)]
|
||||
bg_test_points = [
|
||||
(x - 1, y),
|
||||
(x, y - 1),
|
||||
(x - 1, y - 1),
|
||||
(x + 1, y + 1),
|
||||
(x + r + 1, y),
|
||||
(x + r, y - 1),
|
||||
(x, y + r + 1),
|
||||
]
|
||||
for surf in self.surfaces:
|
||||
fg_adjusted = surf.unmap_rgb(surf.map_rgb(fg))
|
||||
bg_adjusted = surf.unmap_rgb(surf.map_rgb(bg))
|
||||
pygame.gfxdraw.pie(surf, x, y, r, start, end, fg)
|
||||
for posn in fg_test_points:
|
||||
self.check_at(surf, posn, fg_adjusted)
|
||||
for posn in bg_test_points:
|
||||
self.check_at(surf, posn, bg_adjusted)
|
||||
|
||||
def test_trigon(self):
|
||||
"""trigon(surface, x1, y1, x2, y2, x3, y3, color): return None"""
|
||||
fg = self.foreground_color
|
||||
bg = self.background_color
|
||||
x1 = 10
|
||||
y1 = 15
|
||||
x2 = 92
|
||||
y2 = 77
|
||||
x3 = 20
|
||||
y3 = 60
|
||||
fg_test_points = [(x1, y1), (x2, y2), (x3, y3)]
|
||||
bg_test_points = [
|
||||
(x1 - 1, y1 - 1),
|
||||
(x2 + 1, y2 + 1),
|
||||
(x3 - 1, y3 + 1),
|
||||
(x1 + 10, y1 + 30),
|
||||
]
|
||||
for surf in self.surfaces:
|
||||
fg_adjusted = surf.unmap_rgb(surf.map_rgb(fg))
|
||||
bg_adjusted = surf.unmap_rgb(surf.map_rgb(bg))
|
||||
pygame.gfxdraw.trigon(surf, x1, y1, x2, y2, x3, y3, fg)
|
||||
for posn in fg_test_points:
|
||||
self.check_at(surf, posn, fg_adjusted)
|
||||
for posn in bg_test_points:
|
||||
self.check_at(surf, posn, bg_adjusted)
|
||||
|
||||
def test_aatrigon(self):
|
||||
"""aatrigon(surface, x1, y1, x2, y2, x3, y3, color): return None"""
|
||||
fg = self.foreground_color
|
||||
bg = self.background_color
|
||||
x1 = 10
|
||||
y1 = 15
|
||||
x2 = 92
|
||||
y2 = 77
|
||||
x3 = 20
|
||||
y3 = 60
|
||||
fg_test_points = [(x1, y1), (x2, y2), (x3, y3)]
|
||||
bg_test_points = [
|
||||
(x1 - 1, y1 - 1),
|
||||
(x2 + 1, y2 + 1),
|
||||
(x3 - 1, y3 + 1),
|
||||
(x1 + 10, y1 + 30),
|
||||
]
|
||||
for surf in self.surfaces:
|
||||
fg_adjusted = surf.unmap_rgb(surf.map_rgb(fg))
|
||||
bg_adjusted = surf.unmap_rgb(surf.map_rgb(bg))
|
||||
pygame.gfxdraw.aatrigon(surf, x1, y1, x2, y2, x3, y3, fg)
|
||||
for posn in fg_test_points:
|
||||
self.check_not_at(surf, posn, bg_adjusted)
|
||||
for posn in bg_test_points:
|
||||
self.check_at(surf, posn, bg_adjusted)
|
||||
|
||||
def test_aatrigon__with_horizontal_edge(self):
|
||||
"""Ensure aatrigon draws horizontal edges correctly.
|
||||
|
||||
This test creates 2 surfaces and draws an aatrigon on each. The pixels
|
||||
on each surface are compared to ensure they are the same. The only
|
||||
difference between the 2 aatrigons is the order the points are drawn.
|
||||
The order of the points should have no impact on the final drawing.
|
||||
|
||||
Related to issue #622.
|
||||
"""
|
||||
bg_color = pygame.Color("white")
|
||||
line_color = pygame.Color("black")
|
||||
width, height = 11, 10
|
||||
expected_surface = pygame.Surface((width, height), 0, 32)
|
||||
expected_surface.fill(bg_color)
|
||||
surface = pygame.Surface((width, height), 0, 32)
|
||||
surface.fill(bg_color)
|
||||
|
||||
x1, y1 = width - 1, 0
|
||||
x2, y2 = (width - 1) // 2, height - 1
|
||||
x3, y3 = 0, 0
|
||||
|
||||
# The points in this order draw as expected.
|
||||
pygame.gfxdraw.aatrigon(expected_surface, x1, y1, x2, y2, x3, y3, line_color)
|
||||
|
||||
# The points in reverse order fail to draw the horizontal edge along
|
||||
# the top.
|
||||
pygame.gfxdraw.aatrigon(surface, x3, y3, x2, y2, x1, y1, line_color)
|
||||
|
||||
# The surfaces are locked for a possible speed up of pixel access.
|
||||
expected_surface.lock()
|
||||
surface.lock()
|
||||
for x in range(width):
|
||||
for y in range(height):
|
||||
self.assertEqual(
|
||||
expected_surface.get_at((x, y)),
|
||||
surface.get_at((x, y)),
|
||||
f"pos=({x}, {y})",
|
||||
)
|
||||
|
||||
surface.unlock()
|
||||
expected_surface.unlock()
|
||||
|
||||
def test_filled_trigon(self):
|
||||
"""filled_trigon(surface, x1, y1, x2, y2, x3, y3, color): return None"""
|
||||
fg = self.foreground_color
|
||||
bg = self.background_color
|
||||
x1 = 10
|
||||
y1 = 15
|
||||
x2 = 92
|
||||
y2 = 77
|
||||
x3 = 20
|
||||
y3 = 60
|
||||
fg_test_points = [(x1, y1), (x2, y2), (x3, y3), (x1 + 10, y1 + 30)]
|
||||
bg_test_points = [(x1 - 1, y1 - 1), (x2 + 1, y2 + 1), (x3 - 1, y3 + 1)]
|
||||
for surf in self.surfaces:
|
||||
fg_adjusted = surf.unmap_rgb(surf.map_rgb(fg))
|
||||
bg_adjusted = surf.unmap_rgb(surf.map_rgb(bg))
|
||||
pygame.gfxdraw.filled_trigon(surf, x1, y1, x2, y2, x3, y3, fg)
|
||||
for posn in fg_test_points:
|
||||
self.check_at(surf, posn, fg_adjusted)
|
||||
for posn in bg_test_points:
|
||||
self.check_at(surf, posn, bg_adjusted)
|
||||
|
||||
def test_polygon(self):
|
||||
"""polygon(surface, points, color): return None"""
|
||||
fg = self.foreground_color
|
||||
bg = self.background_color
|
||||
points = [(10, 80), (10, 15), (92, 25), (92, 80)]
|
||||
fg_test_points = points + [
|
||||
(points[0][0], points[0][1] - 1),
|
||||
(points[0][0] + 1, points[0][1]),
|
||||
(points[3][0] - 1, points[3][1]),
|
||||
(points[3][0], points[3][1] - 1),
|
||||
(points[2][0], points[2][1] + 1),
|
||||
]
|
||||
bg_test_points = [
|
||||
(points[0][0] - 1, points[0][1]),
|
||||
(points[0][0], points[0][1] + 1),
|
||||
(points[0][0] - 1, points[0][1] + 1),
|
||||
(points[0][0] + 1, points[0][1] - 1),
|
||||
(points[3][0] + 1, points[3][1]),
|
||||
(points[3][0], points[3][1] + 1),
|
||||
(points[3][0] + 1, points[3][1] + 1),
|
||||
(points[3][0] - 1, points[3][1] - 1),
|
||||
(points[2][0] + 1, points[2][1]),
|
||||
(points[2][0] - 1, points[2][1] + 1),
|
||||
(points[1][0] - 1, points[1][1]),
|
||||
(points[1][0], points[1][1] - 1),
|
||||
(points[1][0] - 1, points[1][1] - 1),
|
||||
]
|
||||
for surf in self.surfaces:
|
||||
fg_adjusted = surf.unmap_rgb(surf.map_rgb(fg))
|
||||
bg_adjusted = surf.unmap_rgb(surf.map_rgb(bg))
|
||||
pygame.gfxdraw.polygon(surf, points, fg)
|
||||
for posn in fg_test_points:
|
||||
self.check_at(surf, posn, fg_adjusted)
|
||||
for posn in bg_test_points:
|
||||
self.check_at(surf, posn, bg_adjusted)
|
||||
|
||||
def test_aapolygon(self):
|
||||
"""aapolygon(surface, points, color): return None"""
|
||||
fg = self.foreground_color
|
||||
bg = self.background_color
|
||||
points = [(10, 80), (10, 15), (92, 25), (92, 80)]
|
||||
fg_test_points = points
|
||||
bg_test_points = [
|
||||
(points[0][0] - 1, points[0][1]),
|
||||
(points[0][0], points[0][1] + 1),
|
||||
(points[0][0] - 1, points[0][1] + 1),
|
||||
(points[0][0] + 1, points[0][1] - 1),
|
||||
(points[3][0] + 1, points[3][1]),
|
||||
(points[3][0], points[3][1] + 1),
|
||||
(points[3][0] + 1, points[3][1] + 1),
|
||||
(points[3][0] - 1, points[3][1] - 1),
|
||||
(points[2][0] + 1, points[2][1]),
|
||||
(points[2][0] - 1, points[2][1] + 1),
|
||||
(points[1][0] - 1, points[1][1]),
|
||||
(points[1][0], points[1][1] - 1),
|
||||
(points[1][0] - 1, points[1][1] - 1),
|
||||
]
|
||||
for surf in self.surfaces:
|
||||
fg_adjusted = surf.unmap_rgb(surf.map_rgb(fg))
|
||||
bg_adjusted = surf.unmap_rgb(surf.map_rgb(bg))
|
||||
pygame.gfxdraw.aapolygon(surf, points, fg)
|
||||
for posn in fg_test_points:
|
||||
self.check_at(surf, posn, fg_adjusted)
|
||||
for posn in bg_test_points:
|
||||
self.check_not_at(surf, posn, fg_adjusted)
|
||||
for posn in bg_test_points:
|
||||
self.check_at(surf, posn, bg_adjusted)
|
||||
|
||||
def test_aapolygon__with_horizontal_edge(self):
|
||||
"""Ensure aapolygon draws horizontal edges correctly.
|
||||
|
||||
This test creates 2 surfaces and draws a polygon on each. The pixels
|
||||
on each surface are compared to ensure they are the same. The only
|
||||
difference between the 2 polygons is that one is drawn using
|
||||
aapolygon() and the other using multiple line() calls. They should
|
||||
produce the same final drawing.
|
||||
|
||||
Related to issue #622.
|
||||
"""
|
||||
bg_color = pygame.Color("white")
|
||||
line_color = pygame.Color("black")
|
||||
width, height = 11, 10
|
||||
expected_surface = pygame.Surface((width, height), 0, 32)
|
||||
expected_surface.fill(bg_color)
|
||||
surface = pygame.Surface((width, height), 0, 32)
|
||||
surface.fill(bg_color)
|
||||
|
||||
points = ((0, 0), (0, height - 1), (width - 1, height - 1), (width - 1, 0))
|
||||
|
||||
# The points are used to draw the expected aapolygon using the line()
|
||||
# function.
|
||||
for (x1, y1), (x2, y2) in zip(points, points[1:] + points[:1]):
|
||||
pygame.gfxdraw.line(expected_surface, x1, y1, x2, y2, line_color)
|
||||
|
||||
# The points in this order fail to draw the horizontal edge along
|
||||
# the top.
|
||||
pygame.gfxdraw.aapolygon(surface, points, line_color)
|
||||
|
||||
# The surfaces are locked for a possible speed up of pixel access.
|
||||
expected_surface.lock()
|
||||
surface.lock()
|
||||
for x in range(width):
|
||||
for y in range(height):
|
||||
self.assertEqual(
|
||||
expected_surface.get_at((x, y)),
|
||||
surface.get_at((x, y)),
|
||||
f"pos=({x}, {y})",
|
||||
)
|
||||
|
||||
surface.unlock()
|
||||
expected_surface.unlock()
|
||||
|
||||
def test_filled_polygon(self):
|
||||
"""filled_polygon(surface, points, color): return None"""
|
||||
fg = self.foreground_color
|
||||
bg = self.background_color
|
||||
points = [(10, 80), (10, 15), (92, 25), (92, 80)]
|
||||
fg_test_points = points + [
|
||||
(points[0][0], points[0][1] - 1),
|
||||
(points[0][0] + 1, points[0][1]),
|
||||
(points[0][0] + 1, points[0][1] - 1),
|
||||
(points[3][0] - 1, points[3][1]),
|
||||
(points[3][0], points[3][1] - 1),
|
||||
(points[3][0] - 1, points[3][1] - 1),
|
||||
(points[2][0], points[2][1] + 1),
|
||||
(points[2][0] - 1, points[2][1] + 1),
|
||||
]
|
||||
bg_test_points = [
|
||||
(points[0][0] - 1, points[0][1]),
|
||||
(points[0][0], points[0][1] + 1),
|
||||
(points[0][0] - 1, points[0][1] + 1),
|
||||
(points[3][0] + 1, points[3][1]),
|
||||
(points[3][0], points[3][1] + 1),
|
||||
(points[3][0] + 1, points[3][1] + 1),
|
||||
(points[2][0] + 1, points[2][1]),
|
||||
(points[1][0] - 1, points[1][1]),
|
||||
(points[1][0], points[1][1] - 1),
|
||||
(points[1][0] - 1, points[1][1] - 1),
|
||||
]
|
||||
for surf in self.surfaces:
|
||||
fg_adjusted = surf.unmap_rgb(surf.map_rgb(fg))
|
||||
bg_adjusted = surf.unmap_rgb(surf.map_rgb(bg))
|
||||
pygame.gfxdraw.filled_polygon(surf, points, fg)
|
||||
for posn in fg_test_points:
|
||||
self.check_at(surf, posn, fg_adjusted)
|
||||
for posn in bg_test_points:
|
||||
self.check_at(surf, posn, bg_adjusted)
|
||||
|
||||
def test_textured_polygon(self):
|
||||
"""textured_polygon(surface, points, texture, tx, ty): return None"""
|
||||
w, h = self.default_size
|
||||
fg = self.foreground_color
|
||||
bg = self.background_color
|
||||
tx = 0
|
||||
ty = 0
|
||||
texture = pygame.Surface((w + tx, h + ty), 0, 24)
|
||||
texture.fill(fg, (0, 0, w, h))
|
||||
points = [(10, 80), (10, 15), (92, 25), (92, 80)]
|
||||
# Don't know how to really check this as boarder points may
|
||||
# or may not be included in the textured polygon.
|
||||
fg_test_points = [(points[1][0] + 30, points[1][1] + 40)]
|
||||
bg_test_points = [
|
||||
(points[0][0] - 1, points[0][1]),
|
||||
(points[0][0], points[0][1] + 1),
|
||||
(points[0][0] - 1, points[0][1] + 1),
|
||||
(points[3][0] + 1, points[3][1]),
|
||||
(points[3][0], points[3][1] + 1),
|
||||
(points[3][0] + 1, points[3][1] + 1),
|
||||
(points[2][0] + 1, points[2][1]),
|
||||
(points[1][0] - 1, points[1][1]),
|
||||
(points[1][0], points[1][1] - 1),
|
||||
(points[1][0] - 1, points[1][1] - 1),
|
||||
]
|
||||
for surf in self.surfaces[1:]:
|
||||
fg_adjusted = surf.unmap_rgb(surf.map_rgb(fg))
|
||||
bg_adjusted = surf.unmap_rgb(surf.map_rgb(bg))
|
||||
pygame.gfxdraw.textured_polygon(surf, points, texture, -tx, -ty)
|
||||
for posn in fg_test_points:
|
||||
self.check_at(surf, posn, fg_adjusted)
|
||||
for posn in bg_test_points:
|
||||
self.check_at(surf, posn, bg_adjusted)
|
||||
|
||||
# Alpha blit to 8 bits-per-pixel surface forbidden.
|
||||
texture = pygame.Surface(self.default_size, SRCALPHA, 32)
|
||||
self.assertRaises(
|
||||
ValueError,
|
||||
pygame.gfxdraw.textured_polygon,
|
||||
self.surfaces[0],
|
||||
points,
|
||||
texture,
|
||||
0,
|
||||
0,
|
||||
)
|
||||
|
||||
def test_bezier(self):
|
||||
"""bezier(surface, points, steps, color): return None"""
|
||||
fg = self.foreground_color
|
||||
bg = self.background_color
|
||||
points = [(10, 50), (25, 15), (60, 80), (92, 30)]
|
||||
fg_test_points = [points[0], points[3]]
|
||||
bg_test_points = [
|
||||
(points[0][0] - 1, points[0][1]),
|
||||
(points[3][0] + 1, points[3][1]),
|
||||
(points[1][0], points[1][1] + 3),
|
||||
(points[2][0], points[2][1] - 3),
|
||||
]
|
||||
for surf in self.surfaces:
|
||||
fg_adjusted = surf.unmap_rgb(surf.map_rgb(fg))
|
||||
bg_adjusted = surf.unmap_rgb(surf.map_rgb(bg))
|
||||
pygame.gfxdraw.bezier(surf, points, 30, fg)
|
||||
for posn in fg_test_points:
|
||||
self.check_at(surf, posn, fg_adjusted)
|
||||
for posn in bg_test_points:
|
||||
self.check_at(surf, posn, bg_adjusted)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
@@ -0,0 +1,46 @@
|
||||
import os
|
||||
import unittest
|
||||
|
||||
from pygame.tests import test_utils
|
||||
import pygame
|
||||
from pygame.locals import *
|
||||
|
||||
|
||||
@unittest.skipIf(
|
||||
os.environ.get("SDL_VIDEODRIVER") == "dummy",
|
||||
'OpenGL requires a non-"dummy" SDL_VIDEODRIVER',
|
||||
)
|
||||
class GL_ImageSave(unittest.TestCase):
|
||||
def test_image_save_works_with_opengl_surfaces(self):
|
||||
"""
|
||||
|tags:display,slow,opengl|
|
||||
"""
|
||||
|
||||
pygame.display.init()
|
||||
screen = pygame.display.set_mode((640, 480), OPENGL | DOUBLEBUF)
|
||||
pygame.display.flip()
|
||||
|
||||
tmp_dir = test_utils.get_tmp_dir()
|
||||
# Try the imageext module.
|
||||
tmp_file = os.path.join(tmp_dir, "opengl_save_surface_test.png")
|
||||
pygame.image.save(screen, tmp_file)
|
||||
|
||||
self.assertTrue(os.path.exists(tmp_file))
|
||||
|
||||
os.remove(tmp_file)
|
||||
|
||||
# Only test the image module.
|
||||
tmp_file = os.path.join(tmp_dir, "opengl_save_surface_test.bmp")
|
||||
pygame.image.save(screen, tmp_file)
|
||||
|
||||
self.assertTrue(os.path.exists(tmp_file))
|
||||
|
||||
os.remove(tmp_file)
|
||||
|
||||
# stops tonnes of tmp dirs building up in trunk dir
|
||||
os.rmdir(tmp_dir)
|
||||
pygame.display.quit()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
@@ -0,0 +1,7 @@
|
||||
__tags__ = []
|
||||
|
||||
import pygame
|
||||
import sys
|
||||
|
||||
if "pygame.image" not in sys.modules:
|
||||
__tags__.extend(("ignore", "subprocess_ignore"))
|
1271
.venv/lib/python3.7/site-packages/pygame/tests/image_test.py
Normal file
1271
.venv/lib/python3.7/site-packages/pygame/tests/image_test.py
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,7 @@
|
||||
__tags__ = []
|
||||
|
||||
import pygame
|
||||
import sys
|
||||
|
||||
if "pygame.imageext" not in sys.modules:
|
||||
__tags__.extend(("ignore", "subprocess_ignore"))
|
@@ -0,0 +1,93 @@
|
||||
import os
|
||||
import os.path
|
||||
import sys
|
||||
import unittest
|
||||
|
||||
from pygame.tests.test_utils import example_path
|
||||
import pygame, pygame.image, pygame.pkgdata
|
||||
|
||||
|
||||
imageext = sys.modules["pygame.imageext"]
|
||||
|
||||
|
||||
class ImageextModuleTest(unittest.TestCase):
|
||||
# Most of the testing is done indirectly through image_test.py
|
||||
# This just confirms file path encoding and error handling.
|
||||
def test_save_non_string_file(self):
|
||||
im = pygame.Surface((10, 10), 0, 32)
|
||||
self.assertRaises(TypeError, imageext.save_extended, im, [])
|
||||
|
||||
def test_load_non_string_file(self):
|
||||
self.assertRaises(TypeError, imageext.load_extended, [])
|
||||
|
||||
@unittest.skip("SDL silently removes invalid characters")
|
||||
def test_save_bad_filename(self):
|
||||
im = pygame.Surface((10, 10), 0, 32)
|
||||
u = "a\x00b\x00c.png"
|
||||
self.assertRaises(pygame.error, imageext.save_extended, im, u)
|
||||
|
||||
@unittest.skip("SDL silently removes invalid characters")
|
||||
def test_load_bad_filename(self):
|
||||
u = "a\x00b\x00c.png"
|
||||
self.assertRaises(pygame.error, imageext.load_extended, u)
|
||||
|
||||
def test_save_unknown_extension(self):
|
||||
im = pygame.Surface((10, 10), 0, 32)
|
||||
s = "foo.bar"
|
||||
self.assertRaises(pygame.error, imageext.save_extended, im, s)
|
||||
|
||||
def test_load_unknown_extension(self):
|
||||
s = "foo.bar"
|
||||
self.assertRaises(FileNotFoundError, imageext.load_extended, s)
|
||||
|
||||
def test_load_unknown_file(self):
|
||||
s = "nonexistent.png"
|
||||
self.assertRaises(FileNotFoundError, imageext.load_extended, s)
|
||||
|
||||
def test_load_unicode_path_0(self):
|
||||
u = example_path("data/alien1.png")
|
||||
im = imageext.load_extended(u)
|
||||
|
||||
def test_load_unicode_path_1(self):
|
||||
"""non-ASCII unicode"""
|
||||
import shutil
|
||||
|
||||
orig = example_path("data/alien1.png")
|
||||
temp = os.path.join(example_path("data"), "你好.png")
|
||||
shutil.copy(orig, temp)
|
||||
try:
|
||||
im = imageext.load_extended(temp)
|
||||
finally:
|
||||
os.remove(temp)
|
||||
|
||||
def _unicode_save(self, temp_file):
|
||||
im = pygame.Surface((10, 10), 0, 32)
|
||||
try:
|
||||
with open(temp_file, "w") as f:
|
||||
pass
|
||||
os.remove(temp_file)
|
||||
except OSError:
|
||||
raise unittest.SkipTest("the path cannot be opened")
|
||||
|
||||
self.assertFalse(os.path.exists(temp_file))
|
||||
|
||||
try:
|
||||
imageext.save_extended(im, temp_file)
|
||||
|
||||
self.assertGreater(os.path.getsize(temp_file), 10)
|
||||
finally:
|
||||
try:
|
||||
os.remove(temp_file)
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
def test_save_unicode_path_0(self):
|
||||
"""unicode object with ASCII chars"""
|
||||
self._unicode_save("temp_file.png")
|
||||
|
||||
def test_save_unicode_path_1(self):
|
||||
self._unicode_save("你好.png")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
166
.venv/lib/python3.7/site-packages/pygame/tests/joystick_test.py
Normal file
166
.venv/lib/python3.7/site-packages/pygame/tests/joystick_test.py
Normal file
@@ -0,0 +1,166 @@
|
||||
import unittest
|
||||
from pygame.tests.test_utils import question, prompt
|
||||
|
||||
import pygame
|
||||
import pygame._sdl2.controller
|
||||
|
||||
|
||||
class JoystickTypeTest(unittest.TestCase):
|
||||
def todo_test_Joystick(self):
|
||||
# __doc__ (as of 2008-08-02) for pygame.joystick.Joystick:
|
||||
|
||||
# pygame.joystick.Joystick(id): return Joystick
|
||||
# create a new Joystick object
|
||||
#
|
||||
# Create a new joystick to access a physical device. The id argument
|
||||
# must be a value from 0 to pygame.joystick.get_count()-1.
|
||||
#
|
||||
# To access most of the Joystick methods, you'll need to init() the
|
||||
# Joystick. This is separate from making sure the joystick module is
|
||||
# initialized. When multiple Joysticks objects are created for the
|
||||
# same physical joystick device (i.e., they have the same ID number),
|
||||
# the state and values for those Joystick objects will be shared.
|
||||
#
|
||||
# The Joystick object allows you to get information about the types of
|
||||
# controls on a joystick device. Once the device is initialized the
|
||||
# Pygame event queue will start receiving events about its input.
|
||||
#
|
||||
# You can call the Joystick.get_name() and Joystick.get_id() functions
|
||||
# without initializing the Joystick object.
|
||||
#
|
||||
|
||||
self.fail()
|
||||
|
||||
|
||||
class JoystickModuleTest(unittest.TestCase):
|
||||
def test_get_init(self):
|
||||
# Check that get_init() matches what is actually happening
|
||||
def error_check_get_init():
|
||||
try:
|
||||
pygame.joystick.get_count()
|
||||
except pygame.error:
|
||||
return False
|
||||
return True
|
||||
|
||||
# Start uninitialised
|
||||
self.assertEqual(pygame.joystick.get_init(), False)
|
||||
|
||||
pygame.joystick.init()
|
||||
self.assertEqual(pygame.joystick.get_init(), error_check_get_init()) # True
|
||||
pygame.joystick.quit()
|
||||
self.assertEqual(pygame.joystick.get_init(), error_check_get_init()) # False
|
||||
|
||||
pygame.joystick.init()
|
||||
pygame.joystick.init()
|
||||
self.assertEqual(pygame.joystick.get_init(), error_check_get_init()) # True
|
||||
pygame.joystick.quit()
|
||||
self.assertEqual(pygame.joystick.get_init(), error_check_get_init()) # False
|
||||
|
||||
pygame.joystick.quit()
|
||||
self.assertEqual(pygame.joystick.get_init(), error_check_get_init()) # False
|
||||
|
||||
for i in range(100):
|
||||
pygame.joystick.init()
|
||||
self.assertEqual(pygame.joystick.get_init(), error_check_get_init()) # True
|
||||
pygame.joystick.quit()
|
||||
self.assertEqual(pygame.joystick.get_init(), error_check_get_init()) # False
|
||||
|
||||
for i in range(100):
|
||||
pygame.joystick.quit()
|
||||
self.assertEqual(pygame.joystick.get_init(), error_check_get_init()) # False
|
||||
|
||||
def test_init(self):
|
||||
"""
|
||||
This unit test is for joystick.init()
|
||||
It was written to help reduce maintenance costs
|
||||
and to help test against changes to the code or
|
||||
different platforms.
|
||||
"""
|
||||
pygame.quit()
|
||||
# test that pygame.init automatically calls joystick.init
|
||||
pygame.init()
|
||||
self.assertEqual(pygame.joystick.get_init(), True)
|
||||
|
||||
# Controller module interferes with the joystick module.
|
||||
pygame._sdl2.controller.quit()
|
||||
|
||||
# test that get_count doesn't work w/o joystick init
|
||||
# this is done before and after an init to test
|
||||
# that init activates the joystick functions
|
||||
pygame.joystick.quit()
|
||||
with self.assertRaises(pygame.error):
|
||||
pygame.joystick.get_count()
|
||||
|
||||
# test explicit call(s) to joystick.init.
|
||||
# Also test that get_count works once init is called
|
||||
iterations = 20
|
||||
for i in range(iterations):
|
||||
pygame.joystick.init()
|
||||
self.assertEqual(pygame.joystick.get_init(), True)
|
||||
self.assertIsNotNone(pygame.joystick.get_count())
|
||||
|
||||
def test_quit(self):
|
||||
"""Test if joystick.quit works."""
|
||||
|
||||
pygame.joystick.init()
|
||||
|
||||
self.assertIsNotNone(pygame.joystick.get_count()) # Is not None before quit
|
||||
|
||||
pygame.joystick.quit()
|
||||
|
||||
with self.assertRaises(pygame.error): # Raises error if quit worked
|
||||
pygame.joystick.get_count()
|
||||
|
||||
def test_get_count(self):
|
||||
# Test that get_count correctly returns a non-negative number of joysticks
|
||||
pygame.joystick.init()
|
||||
|
||||
try:
|
||||
count = pygame.joystick.get_count()
|
||||
self.assertGreaterEqual(
|
||||
count, 0, ("joystick.get_count() must " "return a value >= 0")
|
||||
)
|
||||
finally:
|
||||
pygame.joystick.quit()
|
||||
|
||||
|
||||
class JoystickInteractiveTest(unittest.TestCase):
|
||||
__tags__ = ["interactive"]
|
||||
|
||||
def test_get_count_interactive(self):
|
||||
# Test get_count correctly identifies number of connected joysticks
|
||||
prompt(
|
||||
"Please connect any joysticks/controllers now before starting the "
|
||||
"joystick.get_count() test."
|
||||
)
|
||||
|
||||
pygame.joystick.init()
|
||||
# pygame.joystick.get_count(): return count
|
||||
# number of joysticks on the system, 0 means no joysticks connected
|
||||
count = pygame.joystick.get_count()
|
||||
|
||||
response = question(
|
||||
"NOTE: Having Steam open may add an extra virtual controller for "
|
||||
"each joystick/controller physically plugged in.\n"
|
||||
f"joystick.get_count() thinks there is [{count}] joystick(s)/controller(s)"
|
||||
"connected to this system. Is this correct?"
|
||||
)
|
||||
|
||||
self.assertTrue(response)
|
||||
|
||||
# When you create Joystick objects using Joystick(id), you pass an
|
||||
# integer that must be lower than this count.
|
||||
# Test Joystick(id) for each connected joystick
|
||||
if count != 0:
|
||||
for x in range(count):
|
||||
pygame.joystick.Joystick(x)
|
||||
with self.assertRaises(pygame.error):
|
||||
pygame.joystick.Joystick(count)
|
||||
|
||||
pygame.joystick.quit()
|
||||
|
||||
|
||||
################################################################################
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
306
.venv/lib/python3.7/site-packages/pygame/tests/key_test.py
Normal file
306
.venv/lib/python3.7/site-packages/pygame/tests/key_test.py
Normal file
@@ -0,0 +1,306 @@
|
||||
import os
|
||||
import time
|
||||
import unittest
|
||||
|
||||
import pygame
|
||||
import pygame.key
|
||||
|
||||
# keys that are not tested for const-name match
|
||||
SKIPPED_KEYS = {"K_UNKNOWN"}
|
||||
|
||||
# This is the expected compat output
|
||||
KEY_NAME_COMPAT = {
|
||||
"K_0": "0",
|
||||
"K_1": "1",
|
||||
"K_2": "2",
|
||||
"K_3": "3",
|
||||
"K_4": "4",
|
||||
"K_5": "5",
|
||||
"K_6": "6",
|
||||
"K_7": "7",
|
||||
"K_8": "8",
|
||||
"K_9": "9",
|
||||
"K_AC_BACK": "AC Back",
|
||||
"K_AMPERSAND": "&",
|
||||
"K_ASTERISK": "*",
|
||||
"K_AT": "@",
|
||||
"K_BACKQUOTE": "`",
|
||||
"K_BACKSLASH": "\\",
|
||||
"K_BACKSPACE": "backspace",
|
||||
"K_BREAK": "break",
|
||||
"K_CAPSLOCK": "caps lock",
|
||||
"K_CARET": "^",
|
||||
"K_CLEAR": "clear",
|
||||
"K_COLON": ":",
|
||||
"K_COMMA": ",",
|
||||
"K_CURRENCYSUBUNIT": "CurrencySubUnit",
|
||||
"K_CURRENCYUNIT": "euro",
|
||||
"K_DELETE": "delete",
|
||||
"K_DOLLAR": "$",
|
||||
"K_DOWN": "down",
|
||||
"K_END": "end",
|
||||
"K_EQUALS": "=",
|
||||
"K_ESCAPE": "escape",
|
||||
"K_EURO": "euro",
|
||||
"K_EXCLAIM": "!",
|
||||
"K_F1": "f1",
|
||||
"K_F10": "f10",
|
||||
"K_F11": "f11",
|
||||
"K_F12": "f12",
|
||||
"K_F13": "f13",
|
||||
"K_F14": "f14",
|
||||
"K_F15": "f15",
|
||||
"K_F2": "f2",
|
||||
"K_F3": "f3",
|
||||
"K_F4": "f4",
|
||||
"K_F5": "f5",
|
||||
"K_F6": "f6",
|
||||
"K_F7": "f7",
|
||||
"K_F8": "f8",
|
||||
"K_F9": "f9",
|
||||
"K_GREATER": ">",
|
||||
"K_HASH": "#",
|
||||
"K_HELP": "help",
|
||||
"K_HOME": "home",
|
||||
"K_INSERT": "insert",
|
||||
"K_KP0": "[0]",
|
||||
"K_KP1": "[1]",
|
||||
"K_KP2": "[2]",
|
||||
"K_KP3": "[3]",
|
||||
"K_KP4": "[4]",
|
||||
"K_KP5": "[5]",
|
||||
"K_KP6": "[6]",
|
||||
"K_KP7": "[7]",
|
||||
"K_KP8": "[8]",
|
||||
"K_KP9": "[9]",
|
||||
"K_KP_0": "[0]",
|
||||
"K_KP_1": "[1]",
|
||||
"K_KP_2": "[2]",
|
||||
"K_KP_3": "[3]",
|
||||
"K_KP_4": "[4]",
|
||||
"K_KP_5": "[5]",
|
||||
"K_KP_6": "[6]",
|
||||
"K_KP_7": "[7]",
|
||||
"K_KP_8": "[8]",
|
||||
"K_KP_9": "[9]",
|
||||
"K_KP_DIVIDE": "[/]",
|
||||
"K_KP_ENTER": "enter",
|
||||
"K_KP_EQUALS": "equals",
|
||||
"K_KP_MINUS": "[-]",
|
||||
"K_KP_MULTIPLY": "[*]",
|
||||
"K_KP_PERIOD": "[.]",
|
||||
"K_KP_PLUS": "[+]",
|
||||
"K_LALT": "left alt",
|
||||
"K_LCTRL": "left ctrl",
|
||||
"K_LEFT": "left",
|
||||
"K_LEFTBRACKET": "[",
|
||||
"K_LEFTPAREN": "(",
|
||||
"K_LESS": "<",
|
||||
"K_LGUI": "left meta",
|
||||
"K_LMETA": "left meta",
|
||||
"K_LSHIFT": "left shift",
|
||||
"K_LSUPER": "left meta",
|
||||
"K_MENU": "menu",
|
||||
"K_MINUS": "-",
|
||||
"K_MODE": "alt gr",
|
||||
"K_NUMLOCK": "numlock",
|
||||
"K_NUMLOCKCLEAR": "numlock",
|
||||
"K_PAGEDOWN": "page down",
|
||||
"K_PAGEUP": "page up",
|
||||
"K_PAUSE": "break",
|
||||
"K_PERCENT": "%",
|
||||
"K_PERIOD": ".",
|
||||
"K_PLUS": "+",
|
||||
"K_POWER": "power",
|
||||
"K_PRINT": "print screen",
|
||||
"K_PRINTSCREEN": "print screen",
|
||||
"K_QUESTION": "?",
|
||||
"K_QUOTE": "'",
|
||||
"K_QUOTEDBL": '"',
|
||||
"K_RALT": "right alt",
|
||||
"K_RCTRL": "right ctrl",
|
||||
"K_RETURN": "return",
|
||||
"K_RGUI": "right meta",
|
||||
"K_RIGHT": "right",
|
||||
"K_RIGHTBRACKET": "]",
|
||||
"K_RIGHTPAREN": ")",
|
||||
"K_RMETA": "right meta",
|
||||
"K_RSHIFT": "right shift",
|
||||
"K_RSUPER": "right meta",
|
||||
"K_SCROLLLOCK": "scroll lock",
|
||||
"K_SCROLLOCK": "scroll lock",
|
||||
"K_SEMICOLON": ";",
|
||||
"K_SLASH": "/",
|
||||
"K_SPACE": "space",
|
||||
"K_SYSREQ": "sys req",
|
||||
"K_TAB": "tab",
|
||||
"K_UNDERSCORE": "_",
|
||||
"K_UP": "up",
|
||||
"K_a": "a",
|
||||
"K_b": "b",
|
||||
"K_c": "c",
|
||||
"K_d": "d",
|
||||
"K_e": "e",
|
||||
"K_f": "f",
|
||||
"K_g": "g",
|
||||
"K_h": "h",
|
||||
"K_i": "i",
|
||||
"K_j": "j",
|
||||
"K_k": "k",
|
||||
"K_l": "l",
|
||||
"K_m": "m",
|
||||
"K_n": "n",
|
||||
"K_o": "o",
|
||||
"K_p": "p",
|
||||
"K_q": "q",
|
||||
"K_r": "r",
|
||||
"K_s": "s",
|
||||
"K_t": "t",
|
||||
"K_u": "u",
|
||||
"K_v": "v",
|
||||
"K_w": "w",
|
||||
"K_x": "x",
|
||||
"K_y": "y",
|
||||
"K_z": "z",
|
||||
}
|
||||
|
||||
|
||||
class KeyModuleTest(unittest.TestCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
pygame.init()
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
pygame.quit()
|
||||
|
||||
def setUp(self):
|
||||
# This makes sure pygame is always initialized before each test (in
|
||||
# case a test calls pygame.quit()).
|
||||
if not pygame.get_init():
|
||||
pygame.init()
|
||||
if not pygame.display.get_init():
|
||||
pygame.display.init()
|
||||
|
||||
def test_import(self):
|
||||
"""does it import?"""
|
||||
import pygame.key
|
||||
|
||||
# fixme: test_get_focused failing systematically in some linux
|
||||
# fixme: test_get_focused failing on SDL 2.0.18 on Windows
|
||||
@unittest.skip("flaky test, and broken on 2.0.18 windows")
|
||||
def test_get_focused(self):
|
||||
# This test fails in SDL2 in some linux
|
||||
# This test was skipped in SDL1.
|
||||
focused = pygame.key.get_focused()
|
||||
self.assertFalse(focused) # No window to focus
|
||||
self.assertIsInstance(focused, int)
|
||||
# Dummy video driver never gets keyboard focus.
|
||||
if os.environ.get("SDL_VIDEODRIVER") != "dummy":
|
||||
# Positive test, fullscreen with events grabbed
|
||||
display_sizes = pygame.display.list_modes()
|
||||
if display_sizes == -1:
|
||||
display_sizes = [(500, 500)]
|
||||
pygame.display.set_mode(size=display_sizes[-1], flags=pygame.FULLSCREEN)
|
||||
pygame.event.set_grab(True)
|
||||
# Pump event queue to get window focus on macos
|
||||
pygame.event.pump()
|
||||
focused = pygame.key.get_focused()
|
||||
self.assertIsInstance(focused, int)
|
||||
self.assertTrue(focused)
|
||||
# Now test negative, iconify takes away focus
|
||||
pygame.event.clear()
|
||||
# TODO: iconify test fails in windows
|
||||
if os.name != "nt":
|
||||
pygame.display.iconify()
|
||||
# Apparent need to pump event queue in order to make sure iconify
|
||||
# happens. See display_test.py's test_get_active_iconify
|
||||
for _ in range(50):
|
||||
time.sleep(0.01)
|
||||
pygame.event.pump()
|
||||
self.assertFalse(pygame.key.get_focused())
|
||||
# Test if focus is returned when iconify is gone
|
||||
pygame.display.set_mode(size=display_sizes[-1], flags=pygame.FULLSCREEN)
|
||||
for i in range(50):
|
||||
time.sleep(0.01)
|
||||
pygame.event.pump()
|
||||
self.assertTrue(pygame.key.get_focused())
|
||||
# Test if a quit display raises an error:
|
||||
pygame.display.quit()
|
||||
with self.assertRaises(pygame.error) as cm:
|
||||
pygame.key.get_focused()
|
||||
|
||||
def test_get_pressed(self):
|
||||
states = pygame.key.get_pressed()
|
||||
self.assertEqual(states[pygame.K_RIGHT], 0)
|
||||
|
||||
# def test_get_pressed_not_iter(self):
|
||||
# states = pygame.key.get_pressed()
|
||||
# with self.assertRaises(TypeError):
|
||||
# next(states)
|
||||
# with self.assertRaises(TypeError):
|
||||
# for k in states:
|
||||
# pass
|
||||
|
||||
def test_name_and_key_code(self):
|
||||
for const_name in dir(pygame):
|
||||
if not const_name.startswith("K_") or const_name in SKIPPED_KEYS:
|
||||
continue
|
||||
|
||||
try:
|
||||
expected_str_name = KEY_NAME_COMPAT[const_name]
|
||||
except KeyError:
|
||||
self.fail(
|
||||
"If you are seeing this error in a test run, you probably added a "
|
||||
"new pygame key constant, but forgot to update key_test unitests"
|
||||
)
|
||||
|
||||
const_val = getattr(pygame, const_name)
|
||||
|
||||
# with these tests below, we also make sure that key.name and key.key_code
|
||||
# can work together and handle each others outputs
|
||||
|
||||
# test positional args
|
||||
self.assertEqual(pygame.key.name(const_val), expected_str_name)
|
||||
# test kwarg
|
||||
self.assertEqual(pygame.key.name(key=const_val), expected_str_name)
|
||||
|
||||
# test positional args
|
||||
self.assertEqual(pygame.key.key_code(expected_str_name), const_val)
|
||||
# test kwarg
|
||||
self.assertEqual(pygame.key.key_code(name=expected_str_name), const_val)
|
||||
|
||||
alt_name = pygame.key.name(const_val, use_compat=False)
|
||||
self.assertIsInstance(alt_name, str)
|
||||
|
||||
# This is a test for an implementation detail of name with use_compat=False
|
||||
# If this test breaks in the future for any key, it is safe to put skips on
|
||||
# failing keys (the implementation detail is documented as being unreliable)
|
||||
self.assertEqual(pygame.key.key_code(alt_name), const_val)
|
||||
|
||||
self.assertRaises(TypeError, pygame.key.name, "fizzbuzz")
|
||||
self.assertRaises(TypeError, pygame.key.key_code, pygame.K_a)
|
||||
|
||||
self.assertRaises(ValueError, pygame.key.key_code, "fizzbuzz")
|
||||
|
||||
def test_set_and_get_mods(self):
|
||||
pygame.key.set_mods(pygame.KMOD_CTRL)
|
||||
self.assertEqual(pygame.key.get_mods(), pygame.KMOD_CTRL)
|
||||
|
||||
pygame.key.set_mods(pygame.KMOD_ALT)
|
||||
self.assertEqual(pygame.key.get_mods(), pygame.KMOD_ALT)
|
||||
pygame.key.set_mods(pygame.KMOD_CTRL | pygame.KMOD_ALT)
|
||||
self.assertEqual(pygame.key.get_mods(), pygame.KMOD_CTRL | pygame.KMOD_ALT)
|
||||
|
||||
def test_set_and_get_repeat(self):
|
||||
self.assertEqual(pygame.key.get_repeat(), (0, 0))
|
||||
|
||||
pygame.key.set_repeat(10, 15)
|
||||
self.assertEqual(pygame.key.get_repeat(), (10, 15))
|
||||
|
||||
pygame.key.set_repeat()
|
||||
self.assertEqual(pygame.key.get_repeat(), (0, 0))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
@@ -0,0 +1,17 @@
|
||||
import unittest
|
||||
|
||||
import pygame.constants
|
||||
import pygame.locals
|
||||
|
||||
|
||||
class LocalsTest(unittest.TestCase):
|
||||
def test_locals_has_all_constants(self):
|
||||
constants_set = set(pygame.constants.__all__)
|
||||
locals_set = set(pygame.locals.__all__)
|
||||
|
||||
# locals should have everything that constants has
|
||||
self.assertEqual(constants_set - locals_set, set())
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
6441
.venv/lib/python3.7/site-packages/pygame/tests/mask_test.py
Normal file
6441
.venv/lib/python3.7/site-packages/pygame/tests/mask_test.py
Normal file
File diff suppressed because it is too large
Load Diff
2930
.venv/lib/python3.7/site-packages/pygame/tests/math_test.py
Normal file
2930
.venv/lib/python3.7/site-packages/pygame/tests/math_test.py
Normal file
File diff suppressed because it is too large
Load Diff
463
.venv/lib/python3.7/site-packages/pygame/tests/midi_test.py
Normal file
463
.venv/lib/python3.7/site-packages/pygame/tests/midi_test.py
Normal file
@@ -0,0 +1,463 @@
|
||||
import unittest
|
||||
|
||||
|
||||
import pygame
|
||||
|
||||
|
||||
class MidiInputTest(unittest.TestCase):
|
||||
__tags__ = ["interactive"]
|
||||
|
||||
def setUp(self):
|
||||
import pygame.midi
|
||||
|
||||
pygame.midi.init()
|
||||
in_id = pygame.midi.get_default_input_id()
|
||||
if in_id != -1:
|
||||
self.midi_input = pygame.midi.Input(in_id)
|
||||
else:
|
||||
self.midi_input = None
|
||||
|
||||
def tearDown(self):
|
||||
if self.midi_input:
|
||||
self.midi_input.close()
|
||||
pygame.midi.quit()
|
||||
|
||||
def test_Input(self):
|
||||
i = pygame.midi.get_default_input_id()
|
||||
if self.midi_input:
|
||||
self.assertEqual(self.midi_input.device_id, i)
|
||||
|
||||
# try feeding it an input id.
|
||||
i = pygame.midi.get_default_output_id()
|
||||
|
||||
# can handle some invalid input too.
|
||||
self.assertRaises(pygame.midi.MidiException, pygame.midi.Input, i)
|
||||
self.assertRaises(pygame.midi.MidiException, pygame.midi.Input, 9009)
|
||||
self.assertRaises(pygame.midi.MidiException, pygame.midi.Input, -1)
|
||||
self.assertRaises(TypeError, pygame.midi.Input, "1234")
|
||||
self.assertRaises(OverflowError, pygame.midi.Input, pow(2, 99))
|
||||
|
||||
def test_poll(self):
|
||||
if not self.midi_input:
|
||||
self.skipTest("No midi Input device")
|
||||
|
||||
self.assertFalse(self.midi_input.poll())
|
||||
# TODO fake some incoming data
|
||||
|
||||
pygame.midi.quit()
|
||||
self.assertRaises(RuntimeError, self.midi_input.poll)
|
||||
# set midi_input to None to avoid error in tearDown
|
||||
self.midi_input = None
|
||||
|
||||
def test_read(self):
|
||||
if not self.midi_input:
|
||||
self.skipTest("No midi Input device")
|
||||
|
||||
read = self.midi_input.read(5)
|
||||
self.assertEqual(read, [])
|
||||
# TODO fake some incoming data
|
||||
|
||||
pygame.midi.quit()
|
||||
self.assertRaises(RuntimeError, self.midi_input.read, 52)
|
||||
# set midi_input to None to avoid error in tearDown
|
||||
self.midi_input = None
|
||||
|
||||
def test_close(self):
|
||||
if not self.midi_input:
|
||||
self.skipTest("No midi Input device")
|
||||
|
||||
self.assertIsNotNone(self.midi_input._input)
|
||||
self.midi_input.close()
|
||||
self.assertIsNone(self.midi_input._input)
|
||||
|
||||
|
||||
class MidiOutputTest(unittest.TestCase):
|
||||
__tags__ = ["interactive"]
|
||||
|
||||
def setUp(self):
|
||||
import pygame.midi
|
||||
|
||||
pygame.midi.init()
|
||||
m_out_id = pygame.midi.get_default_output_id()
|
||||
if m_out_id != -1:
|
||||
self.midi_output = pygame.midi.Output(m_out_id)
|
||||
else:
|
||||
self.midi_output = None
|
||||
|
||||
def tearDown(self):
|
||||
if self.midi_output:
|
||||
self.midi_output.close()
|
||||
pygame.midi.quit()
|
||||
|
||||
def test_Output(self):
|
||||
i = pygame.midi.get_default_output_id()
|
||||
if self.midi_output:
|
||||
self.assertEqual(self.midi_output.device_id, i)
|
||||
|
||||
# try feeding it an input id.
|
||||
i = pygame.midi.get_default_input_id()
|
||||
|
||||
# can handle some invalid input too.
|
||||
self.assertRaises(pygame.midi.MidiException, pygame.midi.Output, i)
|
||||
self.assertRaises(pygame.midi.MidiException, pygame.midi.Output, 9009)
|
||||
self.assertRaises(pygame.midi.MidiException, pygame.midi.Output, -1)
|
||||
self.assertRaises(TypeError, pygame.midi.Output, "1234")
|
||||
self.assertRaises(OverflowError, pygame.midi.Output, pow(2, 99))
|
||||
|
||||
def test_note_off(self):
|
||||
if self.midi_output:
|
||||
out = self.midi_output
|
||||
out.note_on(5, 30, 0)
|
||||
out.note_off(5, 30, 0)
|
||||
with self.assertRaises(ValueError) as cm:
|
||||
out.note_off(5, 30, 25)
|
||||
self.assertEqual(str(cm.exception), "Channel not between 0 and 15.")
|
||||
with self.assertRaises(ValueError) as cm:
|
||||
out.note_off(5, 30, -1)
|
||||
self.assertEqual(str(cm.exception), "Channel not between 0 and 15.")
|
||||
|
||||
def test_note_on(self):
|
||||
if self.midi_output:
|
||||
out = self.midi_output
|
||||
out.note_on(5, 30, 0)
|
||||
out.note_on(5, 42, 10)
|
||||
with self.assertRaises(ValueError) as cm:
|
||||
out.note_on(5, 30, 25)
|
||||
self.assertEqual(str(cm.exception), "Channel not between 0 and 15.")
|
||||
with self.assertRaises(ValueError) as cm:
|
||||
out.note_on(5, 30, -1)
|
||||
self.assertEqual(str(cm.exception), "Channel not between 0 and 15.")
|
||||
|
||||
def test_set_instrument(self):
|
||||
if not self.midi_output:
|
||||
self.skipTest("No midi device")
|
||||
out = self.midi_output
|
||||
out.set_instrument(5)
|
||||
out.set_instrument(42, channel=2)
|
||||
with self.assertRaises(ValueError) as cm:
|
||||
out.set_instrument(-6)
|
||||
self.assertEqual(str(cm.exception), "Undefined instrument id: -6")
|
||||
with self.assertRaises(ValueError) as cm:
|
||||
out.set_instrument(156)
|
||||
self.assertEqual(str(cm.exception), "Undefined instrument id: 156")
|
||||
with self.assertRaises(ValueError) as cm:
|
||||
out.set_instrument(5, -1)
|
||||
self.assertEqual(str(cm.exception), "Channel not between 0 and 15.")
|
||||
with self.assertRaises(ValueError) as cm:
|
||||
out.set_instrument(5, 16)
|
||||
self.assertEqual(str(cm.exception), "Channel not between 0 and 15.")
|
||||
|
||||
def test_write(self):
|
||||
if not self.midi_output:
|
||||
self.skipTest("No midi device")
|
||||
|
||||
out = self.midi_output
|
||||
out.write([[[0xC0, 0, 0], 20000]])
|
||||
# is equivalent to
|
||||
out.write([[[0xC0], 20000]])
|
||||
# example from the docstring :
|
||||
# 1. choose program change 1 at time 20000 and
|
||||
# 2. send note 65 with velocity 100 500 ms later
|
||||
out.write([[[0xC0, 0, 0], 20000], [[0x90, 60, 100], 20500]])
|
||||
|
||||
out.write([])
|
||||
verrry_long = [[[0x90, 60, i % 100], 20000 + 100 * i] for i in range(1024)]
|
||||
out.write(verrry_long)
|
||||
|
||||
too_long = [[[0x90, 60, i % 100], 20000 + 100 * i] for i in range(1025)]
|
||||
self.assertRaises(IndexError, out.write, too_long)
|
||||
# test wrong data
|
||||
with self.assertRaises(TypeError) as cm:
|
||||
out.write("Non sens ?")
|
||||
error_msg = "unsupported operand type(s) for &: 'str' and 'int'"
|
||||
self.assertEqual(str(cm.exception), error_msg)
|
||||
|
||||
with self.assertRaises(TypeError) as cm:
|
||||
out.write(["Hey what's that?"])
|
||||
self.assertEqual(str(cm.exception), error_msg)
|
||||
|
||||
def test_write_short(self):
|
||||
if not self.midi_output:
|
||||
self.skipTest("No midi device")
|
||||
|
||||
out = self.midi_output
|
||||
# program change
|
||||
out.write_short(0xC0)
|
||||
# put a note on, then off.
|
||||
out.write_short(0x90, 65, 100)
|
||||
out.write_short(0x80, 65, 100)
|
||||
out.write_short(0x90)
|
||||
|
||||
def test_write_sys_ex(self):
|
||||
if not self.midi_output:
|
||||
self.skipTest("No midi device")
|
||||
|
||||
out = self.midi_output
|
||||
out.write_sys_ex(pygame.midi.time(), [0xF0, 0x7D, 0x10, 0x11, 0x12, 0x13, 0xF7])
|
||||
|
||||
def test_pitch_bend(self):
|
||||
# FIXME : pitch_bend in the code, but not in documentation
|
||||
if not self.midi_output:
|
||||
self.skipTest("No midi device")
|
||||
|
||||
out = self.midi_output
|
||||
with self.assertRaises(ValueError) as cm:
|
||||
out.pitch_bend(5, channel=-1)
|
||||
self.assertEqual(str(cm.exception), "Channel not between 0 and 15.")
|
||||
with self.assertRaises(ValueError) as cm:
|
||||
out.pitch_bend(5, channel=16)
|
||||
with self.assertRaises(ValueError) as cm:
|
||||
out.pitch_bend(-10001, 1)
|
||||
self.assertEqual(
|
||||
str(cm.exception),
|
||||
"Pitch bend value must be between " "-8192 and +8191, not -10001.",
|
||||
)
|
||||
with self.assertRaises(ValueError) as cm:
|
||||
out.pitch_bend(10665, 2)
|
||||
|
||||
def test_close(self):
|
||||
if not self.midi_output:
|
||||
self.skipTest("No midi device")
|
||||
self.assertIsNotNone(self.midi_output._output)
|
||||
self.midi_output.close()
|
||||
self.assertIsNone(self.midi_output._output)
|
||||
|
||||
def test_abort(self):
|
||||
if not self.midi_output:
|
||||
self.skipTest("No midi device")
|
||||
self.assertEqual(self.midi_output._aborted, 0)
|
||||
self.midi_output.abort()
|
||||
self.assertEqual(self.midi_output._aborted, 1)
|
||||
|
||||
|
||||
class MidiModuleTest(unittest.TestCase):
|
||||
"""Midi module tests that require midi hardware or midi.init().
|
||||
|
||||
See MidiModuleNonInteractiveTest for non-interactive module tests.
|
||||
"""
|
||||
|
||||
__tags__ = ["interactive"]
|
||||
|
||||
def setUp(self):
|
||||
import pygame.midi
|
||||
|
||||
pygame.midi.init()
|
||||
|
||||
def tearDown(self):
|
||||
pygame.midi.quit()
|
||||
|
||||
def test_get_count(self):
|
||||
c = pygame.midi.get_count()
|
||||
self.assertIsInstance(c, int)
|
||||
self.assertTrue(c >= 0)
|
||||
|
||||
def test_get_default_input_id(self):
|
||||
midin_id = pygame.midi.get_default_input_id()
|
||||
# if there is a not None return make sure it is an int.
|
||||
self.assertIsInstance(midin_id, int)
|
||||
self.assertTrue(midin_id >= -1)
|
||||
pygame.midi.quit()
|
||||
self.assertRaises(RuntimeError, pygame.midi.get_default_output_id)
|
||||
|
||||
def test_get_default_output_id(self):
|
||||
c = pygame.midi.get_default_output_id()
|
||||
self.assertIsInstance(c, int)
|
||||
self.assertTrue(c >= -1)
|
||||
pygame.midi.quit()
|
||||
self.assertRaises(RuntimeError, pygame.midi.get_default_output_id)
|
||||
|
||||
def test_get_device_info(self):
|
||||
an_id = pygame.midi.get_default_output_id()
|
||||
if an_id != -1:
|
||||
interf, name, input, output, opened = pygame.midi.get_device_info(an_id)
|
||||
self.assertEqual(output, 1)
|
||||
self.assertEqual(input, 0)
|
||||
self.assertEqual(opened, 0)
|
||||
|
||||
an_in_id = pygame.midi.get_default_input_id()
|
||||
if an_in_id != -1:
|
||||
r = pygame.midi.get_device_info(an_in_id)
|
||||
# if r is None, it means that the id is out of range.
|
||||
interf, name, input, output, opened = r
|
||||
|
||||
self.assertEqual(output, 0)
|
||||
self.assertEqual(input, 1)
|
||||
self.assertEqual(opened, 0)
|
||||
out_of_range = pygame.midi.get_count()
|
||||
for num in range(out_of_range):
|
||||
self.assertIsNotNone(pygame.midi.get_device_info(num))
|
||||
info = pygame.midi.get_device_info(out_of_range)
|
||||
self.assertIsNone(info)
|
||||
|
||||
def test_init(self):
|
||||
pygame.midi.quit()
|
||||
self.assertRaises(RuntimeError, pygame.midi.get_count)
|
||||
# initialising many times should be fine.
|
||||
pygame.midi.init()
|
||||
pygame.midi.init()
|
||||
pygame.midi.init()
|
||||
pygame.midi.init()
|
||||
|
||||
self.assertTrue(pygame.midi.get_init())
|
||||
|
||||
def test_quit(self):
|
||||
# It is safe to call this more than once.
|
||||
pygame.midi.quit()
|
||||
pygame.midi.init()
|
||||
pygame.midi.quit()
|
||||
pygame.midi.quit()
|
||||
pygame.midi.init()
|
||||
pygame.midi.init()
|
||||
pygame.midi.quit()
|
||||
|
||||
self.assertFalse(pygame.midi.get_init())
|
||||
|
||||
def test_get_init(self):
|
||||
# Already initialized as pygame.midi.init() was called in setUp().
|
||||
self.assertTrue(pygame.midi.get_init())
|
||||
|
||||
def test_time(self):
|
||||
mtime = pygame.midi.time()
|
||||
self.assertIsInstance(mtime, int)
|
||||
# should be close to 2-3... since the timer is just init'd.
|
||||
self.assertTrue(0 <= mtime < 100)
|
||||
|
||||
|
||||
class MidiModuleNonInteractiveTest(unittest.TestCase):
|
||||
"""Midi module tests that do not require midi hardware or midi.init().
|
||||
|
||||
See MidiModuleTest for interactive module tests.
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
import pygame.midi
|
||||
|
||||
def test_midiin(self):
|
||||
"""Ensures the MIDIIN event id exists in the midi module.
|
||||
|
||||
The MIDIIN event id can be accessed via the midi module for backward
|
||||
compatibility.
|
||||
"""
|
||||
self.assertEqual(pygame.midi.MIDIIN, pygame.MIDIIN)
|
||||
self.assertEqual(pygame.midi.MIDIIN, pygame.locals.MIDIIN)
|
||||
|
||||
self.assertNotEqual(pygame.midi.MIDIIN, pygame.MIDIOUT)
|
||||
self.assertNotEqual(pygame.midi.MIDIIN, pygame.locals.MIDIOUT)
|
||||
|
||||
def test_midiout(self):
|
||||
"""Ensures the MIDIOUT event id exists in the midi module.
|
||||
|
||||
The MIDIOUT event id can be accessed via the midi module for backward
|
||||
compatibility.
|
||||
"""
|
||||
self.assertEqual(pygame.midi.MIDIOUT, pygame.MIDIOUT)
|
||||
self.assertEqual(pygame.midi.MIDIOUT, pygame.locals.MIDIOUT)
|
||||
|
||||
self.assertNotEqual(pygame.midi.MIDIOUT, pygame.MIDIIN)
|
||||
self.assertNotEqual(pygame.midi.MIDIOUT, pygame.locals.MIDIIN)
|
||||
|
||||
def test_MidiException(self):
|
||||
"""Ensures the MidiException is raised as expected."""
|
||||
|
||||
def raiseit():
|
||||
raise pygame.midi.MidiException("Hello Midi param")
|
||||
|
||||
with self.assertRaises(pygame.midi.MidiException) as cm:
|
||||
raiseit()
|
||||
|
||||
self.assertEqual(cm.exception.parameter, "Hello Midi param")
|
||||
|
||||
def test_midis2events(self):
|
||||
"""Ensures midi events are properly converted to pygame events."""
|
||||
# List/tuple indexes.
|
||||
MIDI_DATA = 0
|
||||
MD_STATUS = 0
|
||||
MD_DATA1 = 1
|
||||
MD_DATA2 = 2
|
||||
MD_DATA3 = 3
|
||||
|
||||
TIMESTAMP = 1
|
||||
|
||||
# Midi events take the form of:
|
||||
# ((status, data1, data2, data3), timestamp)
|
||||
midi_events = (
|
||||
((0xC0, 0, 1, 2), 20000),
|
||||
((0x90, 60, 1000, "string_data"), 20001),
|
||||
(("0", "1", "2", "3"), "4"),
|
||||
)
|
||||
expected_num_events = len(midi_events)
|
||||
|
||||
# Test different device ids.
|
||||
for device_id in range(3):
|
||||
pg_events = pygame.midi.midis2events(midi_events, device_id)
|
||||
|
||||
self.assertEqual(len(pg_events), expected_num_events)
|
||||
|
||||
for i, pg_event in enumerate(pg_events):
|
||||
# Get the original midi data for comparison.
|
||||
midi_event = midi_events[i]
|
||||
midi_event_data = midi_event[MIDI_DATA]
|
||||
|
||||
# Can't directly check event instance as pygame.event.Event is
|
||||
# a function.
|
||||
# self.assertIsInstance(pg_event, pygame.event.Event)
|
||||
self.assertEqual(pg_event.__class__.__name__, "Event")
|
||||
self.assertEqual(pg_event.type, pygame.MIDIIN)
|
||||
self.assertEqual(pg_event.status, midi_event_data[MD_STATUS])
|
||||
self.assertEqual(pg_event.data1, midi_event_data[MD_DATA1])
|
||||
self.assertEqual(pg_event.data2, midi_event_data[MD_DATA2])
|
||||
self.assertEqual(pg_event.data3, midi_event_data[MD_DATA3])
|
||||
self.assertEqual(pg_event.timestamp, midi_event[TIMESTAMP])
|
||||
self.assertEqual(pg_event.vice_id, device_id)
|
||||
|
||||
def test_midis2events__missing_event_data(self):
|
||||
"""Ensures midi events with missing values are handled properly."""
|
||||
midi_event_missing_data = ((0xC0, 0, 1), 20000)
|
||||
midi_event_missing_timestamp = ((0xC0, 0, 1, 2),)
|
||||
|
||||
for midi_event in (midi_event_missing_data, midi_event_missing_timestamp):
|
||||
with self.assertRaises(ValueError):
|
||||
events = pygame.midi.midis2events([midi_event], 0)
|
||||
|
||||
def test_midis2events__extra_event_data(self):
|
||||
"""Ensures midi events with extra values are handled properly."""
|
||||
midi_event_extra_data = ((0xC0, 0, 1, 2, "extra"), 20000)
|
||||
midi_event_extra_timestamp = ((0xC0, 0, 1, 2), 20000, "extra")
|
||||
|
||||
for midi_event in (midi_event_extra_data, midi_event_extra_timestamp):
|
||||
with self.assertRaises(ValueError):
|
||||
events = pygame.midi.midis2events([midi_event], 0)
|
||||
|
||||
def test_midis2events__extra_event_data_missing_timestamp(self):
|
||||
"""Ensures midi events with extra data and no timestamps are handled
|
||||
properly.
|
||||
"""
|
||||
midi_event_extra_data_no_timestamp = ((0xC0, 0, 1, 2, "extra"),)
|
||||
|
||||
with self.assertRaises(ValueError):
|
||||
events = pygame.midi.midis2events([midi_event_extra_data_no_timestamp], 0)
|
||||
|
||||
def test_conversions(self):
|
||||
"""of frequencies to midi note numbers and ansi note names."""
|
||||
from pygame.midi import frequency_to_midi, midi_to_frequency, midi_to_ansi_note
|
||||
|
||||
self.assertEqual(frequency_to_midi(27.5), 21)
|
||||
self.assertEqual(frequency_to_midi(36.7), 26)
|
||||
self.assertEqual(frequency_to_midi(4186.0), 108)
|
||||
self.assertEqual(midi_to_frequency(21), 27.5)
|
||||
self.assertEqual(midi_to_frequency(26), 36.7)
|
||||
self.assertEqual(midi_to_frequency(108), 4186.0)
|
||||
self.assertEqual(midi_to_ansi_note(21), "A0")
|
||||
self.assertEqual(midi_to_ansi_note(71), "B4")
|
||||
self.assertEqual(midi_to_ansi_note(82), "A#5")
|
||||
self.assertEqual(midi_to_ansi_note(83), "B5")
|
||||
self.assertEqual(midi_to_ansi_note(93), "A6")
|
||||
self.assertEqual(midi_to_ansi_note(94), "A#6")
|
||||
self.assertEqual(midi_to_ansi_note(95), "B6")
|
||||
self.assertEqual(midi_to_ansi_note(96), "C7")
|
||||
self.assertEqual(midi_to_ansi_note(102), "F#7")
|
||||
self.assertEqual(midi_to_ansi_note(108), "C8")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
@@ -0,0 +1,7 @@
|
||||
__tags__ = []
|
||||
|
||||
import pygame
|
||||
import sys
|
||||
|
||||
if "pygame.mixer_music" not in sys.modules:
|
||||
__tags__.extend(("ignore", "subprocess_ignore"))
|
@@ -0,0 +1,437 @@
|
||||
import os
|
||||
import sys
|
||||
import platform
|
||||
import unittest
|
||||
import time
|
||||
|
||||
from pygame.tests.test_utils import example_path
|
||||
import pygame
|
||||
|
||||
|
||||
class MixerMusicModuleTest(unittest.TestCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
# Initializing the mixer is slow, so minimize the times it is called.
|
||||
pygame.mixer.init()
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
pygame.mixer.quit()
|
||||
|
||||
def setUp(cls):
|
||||
# This makes sure the mixer is always initialized before each test (in
|
||||
# case a test calls pygame.mixer.quit()).
|
||||
if pygame.mixer.get_init() is None:
|
||||
pygame.mixer.init()
|
||||
|
||||
def test_load_mp3(self):
|
||||
"|tags:music|"
|
||||
self.music_load("mp3")
|
||||
|
||||
def test_load_ogg(self):
|
||||
"|tags:music|"
|
||||
self.music_load("ogg")
|
||||
|
||||
def test_load_wav(self):
|
||||
"|tags:music|"
|
||||
self.music_load("wav")
|
||||
|
||||
def music_load(self, format):
|
||||
data_fname = example_path("data")
|
||||
|
||||
path = os.path.join(data_fname, f"house_lo.{format}")
|
||||
if os.sep == "\\":
|
||||
path = path.replace("\\", "\\\\")
|
||||
umusfn = str(path)
|
||||
bmusfn = umusfn.encode()
|
||||
|
||||
pygame.mixer.music.load(umusfn)
|
||||
pygame.mixer.music.load(bmusfn)
|
||||
|
||||
def test_load_object(self):
|
||||
"""test loading music from file-like objects."""
|
||||
formats = ["ogg", "wav"]
|
||||
data_fname = example_path("data")
|
||||
for f in formats:
|
||||
path = os.path.join(data_fname, f"house_lo.{f}")
|
||||
if os.sep == "\\":
|
||||
path = path.replace("\\", "\\\\")
|
||||
bmusfn = path.encode()
|
||||
|
||||
with open(bmusfn, "rb") as musf:
|
||||
pygame.mixer.music.load(musf)
|
||||
|
||||
def test_object_namehint(self):
|
||||
"""test loading & queuing music from file-like objects with namehint argument."""
|
||||
formats = ["wav", "ogg"]
|
||||
data_fname = example_path("data")
|
||||
for f in formats:
|
||||
path = os.path.join(data_fname, f"house_lo.{f}")
|
||||
if os.sep == "\\":
|
||||
path = path.replace("\\", "\\\\")
|
||||
bmusfn = path.encode()
|
||||
|
||||
# these two "with open" blocks need to be separate, which is kinda weird
|
||||
with open(bmusfn, "rb") as musf:
|
||||
pygame.mixer.music.load(musf, f)
|
||||
|
||||
with open(bmusfn, "rb") as musf:
|
||||
pygame.mixer.music.queue(musf, f)
|
||||
|
||||
with open(bmusfn, "rb") as musf:
|
||||
pygame.mixer.music.load(musf, namehint=f)
|
||||
|
||||
with open(bmusfn, "rb") as musf:
|
||||
pygame.mixer.music.queue(musf, namehint=f)
|
||||
|
||||
def test_load_unicode(self):
|
||||
"""test non-ASCII unicode path"""
|
||||
import shutil
|
||||
|
||||
ep = example_path("data")
|
||||
temp_file = os.path.join(ep, "你好.wav")
|
||||
org_file = os.path.join(ep, "house_lo.wav")
|
||||
try:
|
||||
with open(temp_file, "w") as f:
|
||||
pass
|
||||
os.remove(temp_file)
|
||||
except OSError:
|
||||
raise unittest.SkipTest("the path cannot be opened")
|
||||
shutil.copy(org_file, temp_file)
|
||||
try:
|
||||
pygame.mixer.music.load(temp_file)
|
||||
pygame.mixer.music.load(org_file) # unload
|
||||
finally:
|
||||
os.remove(temp_file)
|
||||
|
||||
def test_unload(self):
|
||||
import shutil
|
||||
import tempfile
|
||||
|
||||
ep = example_path("data")
|
||||
org_file = os.path.join(ep, "house_lo.wav")
|
||||
tmpfd, tmppath = tempfile.mkstemp(".wav")
|
||||
os.close(tmpfd)
|
||||
shutil.copy(org_file, tmppath)
|
||||
try:
|
||||
pygame.mixer.music.load(tmppath)
|
||||
pygame.mixer.music.unload()
|
||||
finally:
|
||||
os.remove(tmppath)
|
||||
|
||||
def test_queue_mp3(self):
|
||||
"""Ensures queue() accepts mp3 files.
|
||||
|
||||
|tags:music|
|
||||
"""
|
||||
filename = example_path(os.path.join("data", "house_lo.mp3"))
|
||||
pygame.mixer.music.queue(filename)
|
||||
|
||||
def test_queue_ogg(self):
|
||||
"""Ensures queue() accepts ogg files.
|
||||
|
||||
|tags:music|
|
||||
"""
|
||||
filename = example_path(os.path.join("data", "house_lo.ogg"))
|
||||
pygame.mixer.music.queue(filename)
|
||||
|
||||
def test_queue_wav(self):
|
||||
"""Ensures queue() accepts wav files.
|
||||
|
||||
|tags:music|
|
||||
"""
|
||||
filename = example_path(os.path.join("data", "house_lo.wav"))
|
||||
pygame.mixer.music.queue(filename)
|
||||
|
||||
def test_queue__multiple_calls(self):
|
||||
"""Ensures queue() can be called multiple times."""
|
||||
ogg_file = example_path(os.path.join("data", "house_lo.ogg"))
|
||||
wav_file = example_path(os.path.join("data", "house_lo.wav"))
|
||||
|
||||
pygame.mixer.music.queue(ogg_file)
|
||||
pygame.mixer.music.queue(wav_file)
|
||||
|
||||
def test_queue__arguments(self):
|
||||
"""Ensures queue() can be called with proper arguments."""
|
||||
wav_file = example_path(os.path.join("data", "house_lo.wav"))
|
||||
|
||||
pygame.mixer.music.queue(wav_file, loops=2)
|
||||
pygame.mixer.music.queue(wav_file, namehint="")
|
||||
pygame.mixer.music.queue(wav_file, "")
|
||||
pygame.mixer.music.queue(wav_file, "", 2)
|
||||
|
||||
def test_queue__no_file(self):
|
||||
"""Ensures queue() correctly handles missing the file argument."""
|
||||
with self.assertRaises(TypeError):
|
||||
pygame.mixer.music.queue()
|
||||
|
||||
def test_queue__invalid_sound_type(self):
|
||||
"""Ensures queue() correctly handles invalid file types."""
|
||||
not_a_sound_file = example_path(os.path.join("data", "city.png"))
|
||||
|
||||
with self.assertRaises(pygame.error):
|
||||
pygame.mixer.music.queue(not_a_sound_file)
|
||||
|
||||
def test_queue__invalid_filename(self):
|
||||
"""Ensures queue() correctly handles invalid filenames."""
|
||||
with self.assertRaises(pygame.error):
|
||||
pygame.mixer.music.queue("")
|
||||
|
||||
def test_music_pause__unpause(self):
|
||||
"""Ensure music has the correct position immediately after unpausing
|
||||
|
||||
|tags:music|
|
||||
"""
|
||||
filename = example_path(os.path.join("data", "house_lo.mp3"))
|
||||
pygame.mixer.music.load(filename)
|
||||
pygame.mixer.music.play()
|
||||
|
||||
# Wait 0.05s, then pause
|
||||
time.sleep(0.05)
|
||||
pygame.mixer.music.pause()
|
||||
# Wait 0.05s, get position, unpause, then get position again
|
||||
time.sleep(0.05)
|
||||
before_unpause = pygame.mixer.music.get_pos()
|
||||
pygame.mixer.music.unpause()
|
||||
after_unpause = pygame.mixer.music.get_pos()
|
||||
|
||||
self.assertEqual(before_unpause, after_unpause)
|
||||
|
||||
def test_stop(self):
|
||||
# __doc__ (as of 2008-08-02) for pygame.mixer_music.stop:
|
||||
|
||||
# Stops the music playback if it is currently playing.
|
||||
filename = example_path(os.path.join("data", "house_lo.mp3"))
|
||||
pygame.mixer.music.load(filename)
|
||||
pygame.mixer.music.play()
|
||||
|
||||
pygame.mixer.music.stop()
|
||||
self.assertEqual(pygame.mixer.music.get_busy(), False)
|
||||
|
||||
def todo_test_rewind(self):
|
||||
# __doc__ (as of 2008-08-02) for pygame.mixer_music.rewind:
|
||||
|
||||
# Resets playback of the current music to the beginning.
|
||||
|
||||
self.fail()
|
||||
|
||||
def todo_test_get_pos(self):
|
||||
# __doc__ (as of 2008-08-02) for pygame.mixer_music.get_pos:
|
||||
|
||||
# This gets the number of milliseconds that the music has been playing
|
||||
# for. The returned time only represents how long the music has been
|
||||
# playing; it does not take into account any starting position
|
||||
# offsets.
|
||||
#
|
||||
|
||||
self.fail()
|
||||
|
||||
# def test_fadeout(self):
|
||||
# filename = example_path(os.path.join("data", "house_lo.mp3"))
|
||||
# pygame.mixer.music.load(filename)
|
||||
# pygame.mixer.music.play()
|
||||
|
||||
# pygame.mixer.music.fadeout(50)
|
||||
# time.sleep(0.3)
|
||||
# self.assertEqual(pygame.mixer.music.get_busy(), False)
|
||||
|
||||
@unittest.skipIf(
|
||||
os.environ.get("SDL_AUDIODRIVER") == "disk",
|
||||
'disk audio driver "playback" writing to disk is slow',
|
||||
)
|
||||
def test_play__start_time(self):
|
||||
pygame.display.init()
|
||||
|
||||
# music file is 7 seconds long
|
||||
filename = example_path(os.path.join("data", "house_lo.ogg"))
|
||||
pygame.mixer.music.load(filename)
|
||||
start_time_in_seconds = 6.0 # 6 seconds
|
||||
|
||||
music_finished = False
|
||||
clock = pygame.time.Clock()
|
||||
start_time_in_ms = clock.tick()
|
||||
# should play the last 1 second
|
||||
pygame.mixer.music.play(0, start=start_time_in_seconds)
|
||||
running = True
|
||||
while running:
|
||||
pygame.event.pump()
|
||||
|
||||
if not (pygame.mixer.music.get_busy() or music_finished):
|
||||
music_finished = True
|
||||
time_to_finish = (clock.tick() - start_time_in_ms) // 1000
|
||||
self.assertEqual(time_to_finish, 1)
|
||||
running = False
|
||||
|
||||
def test_play(self):
|
||||
# __doc__ (as of 2008-08-02) for pygame.mixer_music.play:
|
||||
|
||||
# This will play the loaded music stream. If the music is already
|
||||
# playing it will be restarted.
|
||||
#
|
||||
# The loops argument controls the number of repeats a music will play.
|
||||
# play(5) will cause the music to played once, then repeated five
|
||||
# times, for a total of six. If the loops is -1 then the music will
|
||||
# repeat indefinitely.
|
||||
#
|
||||
# The starting position argument controls where in the music the song
|
||||
# starts playing. The starting position is dependent on the format of
|
||||
# music playing. MP3 and OGG use the position as time (in seconds).
|
||||
# MOD music it is the pattern order number. Passing a startpos will
|
||||
# raise a NotImplementedError if it cannot set the start position
|
||||
#
|
||||
filename = example_path(os.path.join("data", "house_lo.mp3"))
|
||||
pygame.mixer.music.load(filename)
|
||||
pygame.mixer.music.play()
|
||||
|
||||
self.assertTrue(pygame.mixer.music.get_busy())
|
||||
|
||||
pygame.mixer.music.stop()
|
||||
|
||||
def todo_test_load(self):
|
||||
# __doc__ (as of 2008-08-02) for pygame.mixer_music.load:
|
||||
|
||||
# This will load a music file and prepare it for playback. If a music
|
||||
# stream is already playing it will be stopped. This does not start
|
||||
# the music playing.
|
||||
#
|
||||
# Music can only be loaded from filenames, not python file objects
|
||||
# like the other pygame loading functions.
|
||||
#
|
||||
|
||||
self.fail()
|
||||
|
||||
def test_get_volume(self):
|
||||
# __doc__ (as of 2008-08-02) for pygame.mixer_music.get_volume:
|
||||
|
||||
# Returns the current volume for the mixer. The value will be between
|
||||
# 0.0 and 1.0.
|
||||
#
|
||||
filename = example_path(os.path.join("data", "house_lo.mp3"))
|
||||
pygame.mixer.music.load(filename)
|
||||
pygame.mixer.music.play()
|
||||
|
||||
vol = pygame.mixer.music.get_volume()
|
||||
self.assertGreaterEqual(vol, 0)
|
||||
self.assertLessEqual(vol, 1)
|
||||
|
||||
pygame.mixer.music.stop()
|
||||
|
||||
def todo_test_set_endevent(self):
|
||||
# __doc__ (as of 2008-08-02) for pygame.mixer_music.set_endevent:
|
||||
|
||||
# This causes Pygame to signal (by means of the event queue) when the
|
||||
# music is done playing. The argument determines the type of event
|
||||
# that will be queued.
|
||||
#
|
||||
# The event will be queued every time the music finishes, not just the
|
||||
# first time. To stop the event from being queued, call this method
|
||||
# with no argument.
|
||||
#
|
||||
|
||||
self.fail()
|
||||
|
||||
def test_pause(self):
|
||||
# __doc__ (as of 2008-08-02) for pygame.mixer_music.pause:
|
||||
|
||||
# Temporarily stop playback of the music stream. It can be resumed
|
||||
# with the pygame.mixer.music.unpause() function.
|
||||
#
|
||||
self.music_load("ogg")
|
||||
self.assertFalse(pygame.mixer.music.get_busy())
|
||||
pygame.mixer.music.play()
|
||||
self.assertTrue(pygame.mixer.music.get_busy())
|
||||
pygame.mixer.music.pause()
|
||||
self.assertFalse(pygame.mixer.music.get_busy())
|
||||
|
||||
def test_get_busy(self):
|
||||
# __doc__ (as of 2008-08-02) for pygame.mixer_music.get_busy:
|
||||
|
||||
# Returns True when the music stream is actively playing. When the
|
||||
# music is idle this returns False.
|
||||
#
|
||||
|
||||
self.music_load("ogg")
|
||||
self.assertFalse(pygame.mixer.music.get_busy())
|
||||
pygame.mixer.music.play()
|
||||
self.assertTrue(pygame.mixer.music.get_busy())
|
||||
pygame.mixer.music.pause()
|
||||
self.assertFalse(pygame.mixer.music.get_busy())
|
||||
|
||||
def todo_test_get_endevent(self):
|
||||
# __doc__ (as of 2008-08-02) for pygame.mixer_music.get_endevent:
|
||||
|
||||
# Returns the event type to be sent every time the music finishes
|
||||
# playback. If there is no endevent the function returns
|
||||
# pygame.NOEVENT.
|
||||
#
|
||||
|
||||
self.fail()
|
||||
|
||||
def test_unpause(self):
|
||||
# __doc__ (as of 2008-08-02) for pygame.mixer_music.unpause:
|
||||
|
||||
# This will resume the playback of a music stream after it has been paused.
|
||||
|
||||
filename = example_path(os.path.join("data", "house_lo.mp3"))
|
||||
pygame.mixer.music.load(filename)
|
||||
pygame.mixer.music.play()
|
||||
self.assertTrue(pygame.mixer.music.get_busy())
|
||||
time.sleep(0.1)
|
||||
pygame.mixer.music.pause()
|
||||
self.assertFalse(pygame.mixer.music.get_busy())
|
||||
before = pygame.mixer.music.get_pos()
|
||||
pygame.mixer.music.unpause()
|
||||
after = pygame.mixer.music.get_pos()
|
||||
self.assertTrue(pygame.mixer.music.get_busy())
|
||||
self.assertEqual(before, after)
|
||||
|
||||
pygame.mixer.music.stop()
|
||||
|
||||
def test_set_volume(self):
|
||||
# __doc__ (as of 2008-08-02) for pygame.mixer_music.set_volume:
|
||||
|
||||
# Set the volume of the music playback. The value argument is between
|
||||
# 0.0 and 1.0. When new music is loaded the volume is reset.
|
||||
#
|
||||
filename = example_path(os.path.join("data", "house_lo.mp3"))
|
||||
pygame.mixer.music.load(filename)
|
||||
pygame.mixer.music.play()
|
||||
|
||||
pygame.mixer.music.set_volume(0.5)
|
||||
vol = pygame.mixer.music.get_volume()
|
||||
self.assertEqual(vol, 0.5)
|
||||
|
||||
pygame.mixer.music.stop()
|
||||
|
||||
def todo_test_set_pos(self):
|
||||
# __doc__ (as of 2010-24-05) for pygame.mixer_music.set_pos:
|
||||
|
||||
# This sets the position in the music file where playback will start. The
|
||||
# meaning of "pos", a float (or a number that can be converted to a float),
|
||||
# depends on the music format. Newer versions of SDL_mixer have better
|
||||
# positioning support than earlier. An SDLError is raised if a particular
|
||||
# format does not support positioning.
|
||||
#
|
||||
|
||||
self.fail()
|
||||
|
||||
def test_init(self):
|
||||
"""issue #955. unload music whenever mixer.quit() is called"""
|
||||
import tempfile
|
||||
import shutil
|
||||
|
||||
testfile = example_path(os.path.join("data", "house_lo.wav"))
|
||||
tempcopy = os.path.join(tempfile.gettempdir(), "tempfile.wav")
|
||||
|
||||
for i in range(10):
|
||||
pygame.mixer.init()
|
||||
try:
|
||||
shutil.copy2(testfile, tempcopy)
|
||||
pygame.mixer.music.load(tempcopy)
|
||||
pygame.mixer.quit()
|
||||
finally:
|
||||
os.remove(tempcopy)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user