From 0c357c383c0617ae53b28b896e12aa4c3a7b7a2c Mon Sep 17 00:00:00 2001 From: Benjamin Kirkbride Date: Tue, 20 May 2025 13:27:57 -0400 Subject: [PATCH 1/2] fix the format exclusions and format --- doc/conf.py | 215 +++++++------- pyproject.toml | 10 +- tests/__init__.py | 1 + tests/conftest.py | 20 +- tests/doc/check_examples_2.py | 8 +- tests/doc/check_samples.py | 5 +- tests/integration/examples/test_examples.py | 29 +- tests/integration/tutorials/test_tutorials.py | 3 +- .../sprite_collision_inspector.py | 67 ++--- tests/unit/atlas/conftest.py | 3 +- tests/unit/atlas/test_basics.py | 6 +- tests/unit/atlas/test_gc.py | 58 +++- tests/unit/atlas/test_rebuild_resize.py | 24 +- tests/unit/atlas/test_region.py | 15 +- .../test_update_texture_image_from_atlas.py | 1 + tests/unit/camera/test_camera2d.py | 6 +- .../camera/test_camera_controller_methods.py | 8 +- tests/unit/camera/test_camera_shake.py | 52 +++- .../camera/test_orthographic_projector.py | 54 ++-- .../unit/camera/test_perspective_projector.py | 35 +-- tests/unit/camera/test_viewport_projector.py | 7 +- tests/unit/color/test_color_type.py | 7 +- tests/unit/color/test_module_csscolor.py | 2 +- tests/unit/draw/test_drawing_primitives.py | 59 +--- tests/unit/draw/test_rect.py | 2 +- tests/unit/geometry/test_is_point_in_box.py | 8 +- tests/unit/gl/backends/gl/test_gl_program.py | 75 ++--- tests/unit/gl/test_gl_buffer.py | 44 +-- tests/unit/gl/test_gl_buffer_description.py | 4 +- tests/unit/gl/test_gl_context.py | 18 +- tests/unit/gl/test_gl_framebuffer.py | 27 +- tests/unit/gl/test_gl_gc.py | 4 +- tests/unit/gl/test_gl_geometry.py | 1 + tests/unit/gl/test_gl_texture.py | 60 ++-- tests/unit/gl/test_gl_texture_array.py | 2 +- tests/unit/gl/test_gl_types.py | 26 +- tests/unit/gl/test_gl_vertex_array.py | 60 ++-- tests/unit/gui/test_exp_restricted_input.py | 1 - tests/unit/gui/test_focus.py | 3 + tests/unit/gui/test_ninepatch_draw.py | 18 +- tests/unit/hitbox/test_black_image.py | 1 + tests/unit/hitbox/test_hitbox.py | 2 +- tests/unit/hitbox/test_hitbox_algo_legacy.py | 4 +- tests/unit/paths/test_astar.py | 75 +++-- tests/unit/paths/test_line_of_sight.py | 8 +- .../physics_engine/test_physics_engine2.py | 19 +- .../test_physics_engine_platformer.py | 10 +- tests/unit/physics_engine/test_pymunk.py | 31 +- tests/unit/rect/test_rect_creation_helpers.py | 3 +- tests/unit/rect/test_rect_instances.py | 28 +- tests/unit/resources/test_handles.py | 1 - tests/unit/scene/test_scene_dunder_methods.py | 2 +- .../scene/test_scene_remove_sprite_lists.py | 3 + .../unit/shape_list/test_buffered_drawing.py | 32 +- .../shape_list/test_buffered_line_strip.py | 5 +- tests/unit/sprite/test_copy_dunders.py | 4 +- tests/unit/sprite/test_sprite.py | 74 ++--- .../sprite/test_sprite_animated_walking.py | 25 +- tests/unit/sprite/test_sprite_collision.py | 4 +- tests/unit/sprite/test_sprite_colored.py | 1 + tests/unit/sprite/test_sprite_hitbox.py | 4 +- tests/unit/spritelist/test_spatial_hash.py | 13 +- tests/unit/spritelist/test_spritelist.py | 16 +- .../spritelist/test_spritelist_buffers.py | 13 +- tests/unit/spritelist/test_spritelist_draw.py | 2 + tests/unit/spritelist/test_spritelist_lazy.py | 6 +- tests/unit/spritelist/test_spritesequence.py | 6 +- tests/unit/test_arcade.py | 9 +- tests/unit/test_clock.py | 15 +- tests/unit/test_example_docstrings.py | 2 - tests/unit/test_isometric.py | 19 +- tests/unit/test_key.py | 7 +- tests/unit/test_screenshot.py | 4 +- tests/unit/test_shadertoy.py | 31 +- tests/unit/test_utils.py | 6 +- tests/unit/test_version.py | 58 ++-- tests/unit/text/test_text.py | 168 ++++++++--- tests/unit/text/test_text_error_handling.py | 20 +- .../text/test_text_instance_properties.py | 14 +- tests/unit/text/test_text_sprite.py | 4 +- tests/unit/texture/test_manager.py | 9 +- tests/unit/texture/test_sprite_sheet.py | 37 ++- tests/unit/texture/test_texture.py | 15 +- tests/unit/texture/test_texture_tools.py | 2 +- .../texture/test_texture_transform_render.py | 9 +- .../texture/test_texture_transform_values.py | 7 +- tests/unit/texture/test_textures.py | 4 +- tests/unit/tilemap/test_img_layer.py | 6 +- tests/unit/tilemap/test_rotation_flip.py | 57 ++-- tests/unit/tilemap/test_tilemap_objects.py | 7 +- tests/unit/window/test_view.py | 3 +- tests/unit/window/test_window.py | 5 +- util/create_resources_listing.py | 1 + util/doc_helpers/__init__.py | 56 ++-- util/doc_helpers/real_filesystem.py | 18 +- util/doc_helpers/vfs.py | 3 +- util/generate_example_thumbnails.py | 12 +- util/generate_hit_box_cache.py | 3 +- util/sphinx_static_file_temp_fix.py | 29 +- util/sync_example_code_with_rst.py | 3 +- util/update_quick_index.py | 279 ++++++------------ 101 files changed, 1200 insertions(+), 1162 deletions(-) diff --git a/doc/conf.py b/doc/conf.py index c3b187d76e..21558432d2 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -1,5 +1,6 @@ #!/usr/bin/env python """Sphinx configuration file""" + import os from functools import cache import logging @@ -17,7 +18,7 @@ ARCADE_MODULE = REPO_LOCAL_ROOT / "arcade" UTIL_DIR = REPO_LOCAL_ROOT / "util" -log = logging.getLogger('conf.py') +log = logging.getLogger("conf.py") logging.basicConfig(level=logging.WARNING) # logging.basicConfig(level=logging.INFO) @@ -37,8 +38,8 @@ READTHEDOCS = dict() ENV = dict() for k, v in os.environ.items(): - if k.startswith('READTHEDOCS_'): - READTHEDOCS[k.removeprefix('READTHEDOCS_')] = v + if k.startswith("READTHEDOCS_"): + READTHEDOCS[k.removeprefix("READTHEDOCS_")] = v ENV[k] = v from util.doc_helpers.real_filesystem import copy_media @@ -68,14 +69,15 @@ # Don't change to # from arcade.version import VERSION # or read the docs build will fail. -from version import VERSION # pyright: ignore [reportMissingImports] +from version import VERSION # pyright: ignore [reportMissingImports] + log.info(f" Got version {VERSION=!r}") print() -GIT_REF = 'development' +GIT_REF = "development" if READTHEDOCS: - if READTHEDOCS.get('VERSION') in ('latest', 'stable'): + if READTHEDOCS.get("VERSION") in ("latest", "stable"): log.info(" !!!!! APPEARS TO BE A REAL RELEASE !!!!!") else: log.info(" +++++ Building a PR or development +++++") @@ -85,8 +87,8 @@ # We'll pass this to our generation scripts to initialize their globals -REPO_URL_BASE="https://github.com/pythonarcade/arcade" -FMT_URL_REF_BASE=f"{REPO_URL_BASE}/blob/{GIT_REF}" +REPO_URL_BASE = "https://github.com/pythonarcade/arcade" +FMT_URL_REF_BASE = f"{REPO_URL_BASE}/blob/{GIT_REF}" RESOURCE_GLOBALS = dict( GIT_REF=GIT_REF, # pending: post-3.0 clean-up, not sure if things use it now? @@ -96,11 +98,11 @@ # This double-bracket escapes brackets in f-strings FMT_URL_REF_PAGE=f"{FMT_URL_REF_BASE}/{{}}", FMT_URL_REF_EMBED=f"{FMT_URL_REF_BASE}/{{}}?raw=true", - RTD_EVIL=READTHEDOCS['CANONICAL_URL'] if READTHEDOCS else "" # pending: post-3.0 cleanup + RTD_EVIL=READTHEDOCS["CANONICAL_URL"] if READTHEDOCS else "", # pending: post-3.0 cleanup ) -def run_util(filename, run_name="__main__", init_globals=None): +def run_util(filename, run_name="__main__", init_globals=None): full_absolute_path = UTIL_DIR / filename full_str = str(full_absolute_path) @@ -108,7 +110,7 @@ def run_util(filename, run_name="__main__", init_globals=None): log.info(f" run_name={run_name!r}") kwargs = dict(run_name=run_name) if init_globals is not None: - kwargs['init_globals'] = init_globals + kwargs["init_globals"] = init_globals log.info(f" init_globals={{") num_left = len(init_globals) for k, v in init_globals.items(): @@ -119,6 +121,7 @@ def run_util(filename, run_name="__main__", init_globals=None): runpy.run_path(full_str, **kwargs) + # Temp fix for Sphinx not copying static files # pending: post-3.0 refactor # Enable by creating a .ENABLE_DEVMACHINE_SPHINX_STATIC_FIX run_util("sphinx_static_file_temp_fix.py") @@ -128,56 +131,47 @@ def run_util(filename, run_name="__main__", init_globals=None): # Create a tabular representation of the resources with embeds run_util("create_resources_listing.py", init_globals=RESOURCE_GLOBALS) # Run the generate quick API index script -run_util('../util/update_quick_index.py') +run_util("../util/update_quick_index.py") -OUT_STATIC = REPO_LOCAL_ROOT / 'build/html/_static/' +OUT_STATIC = REPO_LOCAL_ROOT / "build/html/_static/" -src_res_dir = ARCADE_MODULE / 'resources/assets' -out_res_dir = REPO_LOCAL_ROOT / 'build/html/_static/assets' +src_res_dir = ARCADE_MODULE / "resources/assets" +out_res_dir = REPO_LOCAL_ROOT / "build/html/_static/assets" # pending: post-3.0 cleanup to find the right source events to make this work? # if exc or app.builder.format != "html": # return # static_dir = (app.outdir / '_static').resolve() copy_what = { # pending: post-3.0 cleanup to tie this into resource generation correctly - 'sounds': ('*.wav', '*.ogg', '*.mp3'), - 'music': ('*.wav', '*.ogg', '*.mp3'), - 'video': ('*.mp4', '*.webm', ) + "sounds": ("*.wav", "*.ogg", "*.mp3"), + "music": ("*.wav", "*.ogg", "*.mp3"), + "video": ( + "*.mp4", + "*.webm", + ), } copy_media(src_res_dir, out_res_dir, copy_what) # We are no longer asking. We are copying. -copy_media( - REPO_LOCAL_ROOT / "doc/_static/icons", - OUT_STATIC / "icons" , - { - 'tabler': ("*.svg",) - } -) -copy_media( - REPO_LOCAL_ROOT / "doc/_static/", - OUT_STATIC , - { - 'filetiles': ("*.png",) - } -) -#copy_media( +copy_media(REPO_LOCAL_ROOT / "doc/_static/icons", OUT_STATIC / "icons", {"tabler": ("*.svg",)}) +copy_media(REPO_LOCAL_ROOT / "doc/_static/", OUT_STATIC, {"filetiles": ("*.png",)}) +# copy_media( # REP / "" -#) +# ) autodoc_inherit_docstrings = False autodoc_default_options = { - 'members': True, + "members": True, # 'member-order': 'groupwise', - 'member-order': 'alphabetical', - 'undoc-members': True, - 'show-inheritance': True + "member-order": "alphabetical", + "undoc-members": True, + "show-inheritance": True, } -toc_object_entries_show_parents = 'hide' +toc_object_entries_show_parents = "hide" # Special methods in api docs gets a special prefix emoji -prettyspecialmethods_signature_prefix = '🧙' +prettyspecialmethods_signature_prefix = "🧙" RELEASE = VERSION @@ -187,17 +181,17 @@ def run_util(filename, run_name="__main__", init_globals=None): # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. extensions = [ - 'sphinx_rtd_theme', # Read the Docs theme - 'sphinx_rtd_dark_mode', # Dark mode for the RTD theme - 'sphinx.ext.autodoc', # API doc generation tools - 'sphinx.ext.napoleon', # Support for NumPy and Google style docstrings - 'sphinx.ext.imgconverter', # Converts .gif for PDF doc build - 'sphinx.ext.intersphinx', # Link to other projects' docs - 'sphinx.ext.viewcode', # display code with line numbers and line highlighting - 'sphinx_copybutton', # Adds a copy button to code blocks - 'sphinx_sitemap', # sitemap.xml generation - 'sphinx_togglebutton', #A way to toggle sections of text/code on or off. - 'doc.extensions.prettyspecialmethods', # Forker plugin for prettifying special methods + "sphinx_rtd_theme", # Read the Docs theme + "sphinx_rtd_dark_mode", # Dark mode for the RTD theme + "sphinx.ext.autodoc", # API doc generation tools + "sphinx.ext.napoleon", # Support for NumPy and Google style docstrings + "sphinx.ext.imgconverter", # Converts .gif for PDF doc build + "sphinx.ext.intersphinx", # Link to other projects' docs + "sphinx.ext.viewcode", # display code with line numbers and line highlighting + "sphinx_copybutton", # Adds a copy button to code blocks + "sphinx_sitemap", # sitemap.xml generation + "sphinx_togglebutton", # A way to toggle sections of text/code on or off. + "doc.extensions.prettyspecialmethods", # Forker plugin for prettifying special methods ] # pending: post-3.0 cleanup: @@ -207,19 +201,19 @@ def run_util(filename, run_name="__main__", init_globals=None): # copybutton_image_svg = (REPO_LOCAL_ROOT / "doc/_static/icons/tabler/copy.svg").read_text() # Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] +templates_path = ["_templates"] # The suffix(es) of source filenames. # You can specify multiple suffix as a list of string: -source_suffix = '.rst' +source_suffix = ".rst" # The master toctree document. -master_doc = 'index' +master_doc = "index" # General information about the project. -project = 'Python Arcade Library' -copyright = '2025, Paul Vincent Craven' -author = 'Paul Vincent Craven' +project = "Python Arcade Library" +copyright = "2025, Paul Vincent Craven" +author = "Paul Vincent Craven" # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the @@ -246,7 +240,7 @@ def run_util(filename, run_name="__main__", init_globals=None): ] # The name of the Pygments (syntax highlighting) style to use. -pygments_style = 'default' # will use "sphinx" or the theme's default +pygments_style = "default" # will use "sphinx" or the theme's default # If true, `todo` and `todoList` produce output, else they produce nothing. # todo_include_todos = True @@ -262,81 +256,79 @@ def run_util(filename, run_name="__main__", init_globals=None): # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. -html_theme = 'sphinx_rtd_theme' +html_theme = "sphinx_rtd_theme" # See sphinx-rtd-theme docs for details on each option: # https://sphinx-rtd-theme.readthedocs.io/en/stable/configuring.html html_theme_options = { - 'logo_only': False, - 'sticky_navigation': True, - 'navigation_depth': 3, - 'collapse_navigation': False, + "logo_only": False, + "sticky_navigation": True, + "navigation_depth": 3, + "collapse_navigation": False, } # The single config option provided by sphinx-rtd-dark-mode # https://github.com/MrDogeBro/sphinx_rtd_dark_mode#config default_dark_mode = True -html_title = f'Python Arcade {version}' +html_title = f"Python Arcade {version}" html_js_files = [ - 'https://code.jquery.com/jquery-3.6.3.min.js', - 'https://cdn.datatables.net/1.13.2/js/jquery.dataTables.min.js', + "https://code.jquery.com/jquery-3.6.3.min.js", + "https://cdn.datatables.net/1.13.2/js/jquery.dataTables.min.js", ] html_css_files = [ - 'https://cdn.datatables.net/1.13.2/css/jquery.dataTables.min.css', + "https://cdn.datatables.net/1.13.2/css/jquery.dataTables.min.css", ] # The name of an image file (relative to this directory) to place at the top # of the sidebar. -html_logo = '_static/android-chrome-192x192.png' +html_logo = "_static/android-chrome-192x192.png" # The name of an image file (within the static path) to use as favicon of the # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 # pixels large. -html_favicon = '_static/favicon.ico' +html_favicon = "_static/favicon.ico" # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['_static'] +html_static_path = ["_static"] # Add any extra paths that contain custom files (such as robots.txt or # .htaccess) here, relative to this directory. These files are copied # directly to the root of the documentation. -html_extra_path = ['html_extra'] +html_extra_path = ["html_extra"] # Output file base name for HTML help builder. -htmlhelp_basename = 'Arcade' -html_baseurl = 'https://api.arcade.academy/' +htmlhelp_basename = "Arcade" +html_baseurl = "https://api.arcade.academy/" # Fix line numbers on code listings until the RTD theme updates to sphinx 4+ # html_codeblock_linenos_style = 'table' # Configuration for intersphinx enabling linking other projects intersphinx_mapping = { - 'python': ('https://docs.python.org/3', None), + "python": ("https://docs.python.org/3", None), # As of January 25th, pyglet's 2.1.X branch is on this URL and their # development build on readthedocs is for their in-progress 3.0.0 alpha. - 'pyglet': ('https://pyglet.readthedocs.io/en/latest/', None), - 'PIL': ('https://pillow.readthedocs.io/en/stable', None), - 'pymunk': ('https://www.pymunk.org/en/latest/', None), + "pyglet": ("https://pyglet.readthedocs.io/en/latest/", None), + "PIL": ("https://pillow.readthedocs.io/en/stable", None), + "pymunk": ("https://www.pymunk.org/en/latest/", None), } # These will be joined as one block and prepended to every source file. # Substitutions for |version| and |release| are predefined by Sphinx. PROLOG_PARTS = [ - #".. include:: /links.rst", + # ".. include:: /links.rst", ".. |pyglet Player| replace:: pyglet :py:class:`~pyglet.media.player.Player`", ".. _Arcade's License File on GitHub: {FMT_URL_REF_BASE}/license.rst", - ( # Allows explaining how to copy anywhere in the doc. - '.. |Example Copy Button| raw:: html\n\n' + ".. |Example Copy Button| raw:: html\n\n" '
\n' ' \n\n' - '
\n\n' - ) - + " \n\n" + ), ] with open("_includes/links.rst") as f: PROLOG_PARTS.extend(f.readlines()) @@ -391,10 +383,12 @@ def inspect_docstring_for_member( if what == "class": doc = _obj.__init__.__doc__ if doc and isinstance(doc, str) and not doc.startswith("Initialize self"): - raise ValueError(( - f"Class {name} has a docstring on __init__. " - "The class docstring should cover docs for the initializer:\n {_obj.__init__.__doc__}" - )) + raise ValueError( + ( + f"Class {name} has a docstring on __init__. " + "The class docstring should cover docs for the initializer:\n {_obj.__init__.__doc__}" + ) + ) def generate_color_table(filename, source): @@ -411,7 +405,9 @@ def generate_color_table(filename, source): # green '(?P\d*)' followed by # blue '(?P\d*)' followed by # alpha '(?P\d*)' - color_match = re.compile(r'(?P[a-z_A-Z]*)(?:[ =]*Color[ (]*)(?P\d*)[ ,]*(?P\d*)[ ,]*(?P\d*)[ ,]*(?P\d*)') + color_match = re.compile( + r"(?P[a-z_A-Z]*)(?:[ =]*Color[ (]*)(?P\d*)[ ,]*(?P\d*)[ ,]*(?P\d*)[ ,]*(?P\d*)" + ) with open(filename) as color_file: for line in color_file: @@ -421,7 +417,7 @@ def generate_color_table(filename, source): continue name, r, g, b, a = matches.groupdict().values() - color_rgb_comma_sep= f"{r}, {g}, {b}" + color_rgb_comma_sep = f"{r}, {g}, {b}" # Generate the alpha for CSS color function rgba_css = f"rgba({color_rgb_comma_sep}, {int(a) / 255!s:.4})" @@ -429,12 +425,14 @@ def generate_color_table(filename, source): append_text += " " append_text += ( f"" - f"" - f"{name}" + f'' + f'{name}' f"" f"" ) - append_text += f"
 
" + append_text += ( + f'
 
' + ) append_text += f"({color_rgb_comma_sep}, {a})" append_text += "\n" @@ -461,6 +459,7 @@ def source_read_handler(_app, doc_name: str, source): Event handler for source-read event. Where we can modify the source of a document before it is parsed. """ + def _get_dir(app, path): path = get_module_root(_app.confdir) / path print(f"Generated corrected module path: {path!r}") @@ -474,6 +473,7 @@ def _get_dir(app, path): elif doc_name == "api_docs/arcade.uicolor": generate_color_table(_get_dir(_app, "uicolor.py"), source) + def on_autodoc_process_bases(app, name, obj, options, bases): """We don't care about the `object` base class, so remove it from the list of bases.""" bases[:] = [base for base in bases if base is not object] @@ -485,10 +485,10 @@ class A(NamedTuple): APP_CONFIG_DIRS = ( - A('outdir'), - A('srcdir', 'NOTE: This is reST source, not Python source!'), - A('confdir'), - A('doctreedir'), + A("outdir"), + A("srcdir", "NOTE: This is reST source, not Python source!"), + A("confdir"), + A("doctreedir"), ) @@ -497,18 +497,16 @@ class ResourceRole(SphinxRole): # pending: 3.1 This needs improvement. """ + def run(self) -> tuple[list[nodes.Node], list[nodes.system_message]]: raw = self.text.removeprefix(":resource:") - page_id = self.text\ - .replace(':', '')\ - .replace('/', '-')\ - .replace('_', '-')\ - .replace('.', '-') + page_id = self.text.replace(":", "").replace("/", "-").replace("_", "-").replace(".", "-") filename = f"'{raw.split('/')[-1]}'" - node = nodes.reference(text=filename, refuri=''.join([ - '/api_docs/resources.html#', page_id]), - ) + node = nodes.reference( + text=filename, + refuri="".join(["/api_docs/resources.html#", page_id]), + ) log.info(" Attempted ResourceRole", locals()) return [node], [] @@ -533,15 +531,16 @@ def setup(app): # IMPORTANT: We can't use app.add_autodocumenter! # See the docstring of ClassDocumenter above for why. # sphinx.ext.autodoc.ClassDocumenter = ClassDocumenter - app.connect('source-read', source_read_handler) + app.connect("source-read", source_read_handler) app.connect("autodoc-process-docstring", inspect_docstring_for_member) - app.connect('autodoc-process-signature', strip_init_return_typehint, -1000) - app.connect('autodoc-process-bases', on_autodoc_process_bases) + app.connect("autodoc-process-signature", strip_init_return_typehint, -1000) + app.connect("autodoc-process-bases", on_autodoc_process_bases) # app.add_transform(Transform) - app.add_role('resource', ResourceRole()) + app.add_role("resource", ResourceRole()) # Don't do anything that can fail on this event or it'll kill your build hard # app.connect('build-finished', throws_exception) + # ------------------------------------------------------ # Old hacks that breaks the api docs. !!! DO NOT USE !!! # ------------------------------------------------------ diff --git a/pyproject.toml b/pyproject.toml index e6f66f707a..e67436c235 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -84,7 +84,7 @@ build-backend = "setuptools.build_meta" [tool.ruff] line-length = 100 output-format = "full" -exclude = [ +lint.exclude = [ "venv", ".venv*", "tests", @@ -114,7 +114,7 @@ lint.select = [ [tool.ruff.format] docstring-code-format = false -exclude = ["arcade/examples/*", "benchmarks/*"] +exclude = ["arcade/examples/*", "benchmarks/*", "doc/*"] # This ignores __init__.py files and examples for import sorting [tool.ruff.lint.per-file-ignores] @@ -126,9 +126,7 @@ exclude = ["arcade/examples/*", "benchmarks/*"] [tool.mypy] disable_error_code = "annotation-unchecked" -exclude = [ - "arcade/gl/backends" -] +exclude = ["arcade/gl/backends"] [tool.pytest.ini_options] norecursedirs = [ @@ -143,7 +141,7 @@ norecursedirs = [ ] markers = [ "backendgl: Run OpenGL (or OpenGL ES) backend specific tests", - "backendwebgl: Run WebGL backend specific tests" + "backendwebgl: Run WebGL backend specific tests", ] [tool.pyright] diff --git a/tests/__init__.py b/tests/__init__.py index 40bd75a955..6a85605a56 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -3,4 +3,5 @@ # Headless mode if os.environ.get("ARCADE_HEADLESS_TEST"): import pyglet + pyglet.options.headless = True diff --git a/tests/conftest.py b/tests/conftest.py index ab5f3728e7..4310fb6288 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -17,6 +17,7 @@ from arcade.clock import GLOBAL_CLOCK, GLOBAL_FIXED_CLOCK from arcade import Rect, LBWH from arcade import gl + # from arcade.texture import default_texture_cache # NOTE: Load liberation fonts in unit tests arcade.resources.load_liberation_fonts() @@ -30,10 +31,7 @@ WINDOW = None OFFSCREEN = None -POSSIBLE_BACKENDS = [ - "backendopengl", - "backendwebgl" -] +POSSIBLE_BACKENDS = ["backendopengl", "backendwebgl"] arcade.resources.load_kenney_fonts() @@ -41,17 +39,22 @@ def pytest_addoption(parser): parser.addoption("--gl-backend", default="opengl") + def pytest_configure(config): global GL_BACKEND GL_BACKEND = config.option.gl_backend + def pytest_collection_modifyitems(config, items): desired_backend = "backend" + GL_BACKEND for item in items: for backend in POSSIBLE_BACKENDS: if backend in item.keywords: if backend != desired_backend: - item.add_marker(pytest.mark.skip(f"Skipping GL backend specific test for {backend}")) + item.add_marker( + pytest.mark.skip(f"Skipping GL backend specific test for {backend}") + ) + def make_window_caption(request=None, prefix="Testing", sep=" - ") -> str: """Centralizes test name customization. @@ -72,7 +75,12 @@ def create_window(width=1280, height=720, caption="Testing", **kwargs): global WINDOW if not WINDOW: WINDOW = REAL_WINDOW_CLASS( - width=width, height=height, title=caption, vsync=False, antialiasing=False, gl_api = GL_BACKEND + width=width, + height=height, + title=caption, + vsync=False, + antialiasing=False, + gl_api=GL_BACKEND, ) WINDOW.set_vsync(False) # This value is being monkey-patched into the Window class so that tests can identify if we are using diff --git a/tests/doc/check_examples_2.py b/tests/doc/check_examples_2.py index bb259d9096..b974732ef1 100644 --- a/tests/doc/check_examples_2.py +++ b/tests/doc/check_examples_2.py @@ -4,10 +4,11 @@ def get_references_in_index(): - txt = Path('../../doc/example_code/how_to_examples/index.rst').read_text() + txt = Path("../../doc/example_code/how_to_examples/index.rst").read_text() references_in_index = re.findall(":ref:`(.*)`", txt) return references_in_index + def get_references_in_rsts(): mypath = Path("../../doc/example_code/how_to_examples/") @@ -24,6 +25,7 @@ def get_references_in_rsts(): return references + def main(): references_in_index = get_references_in_index() files_to_reference = get_references_in_rsts() @@ -32,7 +34,9 @@ def main(): if not reference in references_in_index: print(f"index.rst is missing any mention of '{reference}'") - print("Done with checking to make sure references in doc/examples/*.rst are in doc/examples/index.rst") + print( + "Done with checking to make sure references in doc/examples/*.rst are in doc/examples/index.rst" + ) main() diff --git a/tests/doc/check_samples.py b/tests/doc/check_samples.py index a0b23bd577..e84ba7af31 100644 --- a/tests/doc/check_samples.py +++ b/tests/doc/check_samples.py @@ -27,7 +27,7 @@ def main(): # See if there are rst files for all the py files for py_file in python_example_filename_list: - base_name = py_file[:len(py_file) - 3] + base_name = py_file[: len(py_file) - 3] rst_name = base_name + ".rst" if rst_name not in python_rst_filename_list: print("Missing " + rst_name) @@ -35,9 +35,10 @@ def main(): # See if there are py files for all the rst files print() for rst_file in python_rst_filename_list: - base_name = rst_file[:len(rst_file) - 4] + base_name = rst_file[: len(rst_file) - 4] py_name = base_name + ".py" if py_name not in python_example_filename_list: print("Missing " + py_name) + main() diff --git a/tests/integration/examples/test_examples.py b/tests/integration/examples/test_examples.py index 84ddcb7057..f80c900048 100644 --- a/tests/integration/examples/test_examples.py +++ b/tests/integration/examples/test_examples.py @@ -1,6 +1,7 @@ """ Import and run all examples one frame """ + import contextlib import io import inspect @@ -15,24 +16,20 @@ # File path, module path EXAMPLE_LOCATIONS = [ - ( - Path(arcade.__file__).parent / "examples", - "arcade.examples" - ), + (Path(arcade.__file__).parent / "examples", "arcade.examples"), ( Path(arcade.__file__).parent / "examples" / "platform_tutorial", - "arcade.examples.platform_tutorial" - ), - ( - Path(arcade.__file__).parent / "examples" / "gl", - "arcade.examples.gl" + "arcade.examples.platform_tutorial", ), + (Path(arcade.__file__).parent / "examples" / "gl", "arcade.examples.gl"), ] # These examples are allowed to print to stdout -ALLOW_STDOUT = set([ - "arcade.examples.dual_stick_shooter", - "transform_multi", -]) +ALLOW_STDOUT = set( + [ + "arcade.examples.dual_stick_shooter", + "transform_multi", + ] +) IGNORE_PATTERNS = [ "net_process_animal_facts", # Starts network process "transform_emit", # Broken @@ -42,16 +39,19 @@ "bindless", # Bindless textures cannot be run in unit test ] + def list_examples(): for path, module_path in EXAMPLE_LOCATIONS: for example in path.glob("*.py"): if example.stem.startswith("_"): continue + def is_ignored(example): for pattern in IGNORE_PATTERNS: if pattern in example.stem: return True return False + if is_ignored(example): continue yield f"{module_path}.{example.stem}", example, True @@ -85,13 +85,12 @@ def test_examples(window_proxy, module_path, file_path, allow_stdout): # Manually load the module as __main__ so it runs on import loader = SourceFileLoader("__main__", str(file_path)) loader.exec_module(loader.load_module()) - + # Reset the global clock's tick speed # is this a good argument against a global scope clock? # yes. arcade.clock.GLOBAL_CLOCK.set_tick_speed(1.0) - if not allow_stdout: output = stdout.getvalue() assert not output, f"Example {module_path} printed to stdout: {output}" diff --git a/tests/integration/tutorials/test_tutorials.py b/tests/integration/tutorials/test_tutorials.py index 748cae5536..e7ee269f60 100644 --- a/tests/integration/tutorials/test_tutorials.py +++ b/tests/integration/tutorials/test_tutorials.py @@ -1,6 +1,7 @@ """ Find and run all tutorials in the doc/tutorials directory """ + import io import os import contextlib @@ -11,7 +12,7 @@ import pytest import arcade -TUTORIAL_DIR = Path(arcade.__file__).parent.parent / "doc" /"tutorials" +TUTORIAL_DIR = Path(arcade.__file__).parent.parent / "doc" / "tutorials" ALLOW_STDOUT = {} diff --git a/tests/manual_smoke/sprite_collision_inspector.py b/tests/manual_smoke/sprite_collision_inspector.py index 401c317098..b38b725c39 100644 --- a/tests/manual_smoke/sprite_collision_inspector.py +++ b/tests/manual_smoke/sprite_collision_inspector.py @@ -14,11 +14,12 @@ TEX_GREY_PANEL_RAW = load_texture(":resources:gui_basic_assets/window/grey_panel.png") -T = TypeVar('T') +T = TypeVar("T") + def _tname(t: Any) -> str: if not isinstance(t, builtins.type): - return t.__class__.__name__ + return t.__class__.__name__ else: return t.__name__ @@ -61,7 +62,7 @@ def __init__( size_hint=size_hint, size_hint_min=size_hint_min, size_hint_max=size_hint_max, - **kwargs + **kwargs, ) self._error_color = error_color self._parsed_type: Type[T] = parsed_type @@ -102,9 +103,7 @@ def color(self, new_color: RGBOrA255) -> None: return self.caret.color = validated - self.doc.set_style( - 0, len(self.text), dict(color=validated) - ) + self.doc.set_style(0, len(self.text), dict(color=validated)) self.trigger_full_render() @property @@ -123,7 +122,6 @@ def text(self, new_text: str) -> None: raise e - def draw_crosshair( where: tuple[float, float], color=arcade.color.BLACK, @@ -131,58 +129,40 @@ def draw_crosshair( border_width: float = 1.0, ) -> None: x, y = where - arcade.draw.circle.draw_circle_outline( - x, y, - radius, - color=color, - border_width=border_width - ) - arcade.draw.draw_line( - x, y - radius, x, y + radius, - color=color, line_width=border_width) + arcade.draw.circle.draw_circle_outline(x, y, radius, color=color, border_width=border_width) + arcade.draw.draw_line(x, y - radius, x, y + radius, color=color, line_width=border_width) - arcade.draw.draw_line( - x - radius, y, x + radius, y, - color=color, line_width=border_width) + arcade.draw.draw_line(x - radius, y, x + radius, y, color=color, line_width=border_width) class MyGame(arcade.Window): - def add_field_row(self, label_text: str, widget: UIWidget) -> None: children = ( arcade.gui.widgets.text.UITextArea( - text=label_text, - width=100, - height=20, - color=arcade.color.BLACK, - font_size=12 + text=label_text, width=100, height=20, color=arcade.color.BLACK, font_size=12 ), - widget + widget, ) row = UIBoxLayout(vertical=False, space_between=10, children=children) self.rows.add(row) - def __init__( - self, - width: int = 1280, - height: int = 720, - grid_tile_px: int = 100 - ): - + def __init__(self, width: int = 1280, height: int = 720, grid_tile_px: int = 100): super().__init__(width, height, "Collision Inspector") # why does this need a context again? self.nine_patch = NinePatchTexture( - left=5, right=5, top=5, bottom=5, texture=TEX_GREY_PANEL_RAW) + left=5, right=5, top=5, bottom=5, texture=TEX_GREY_PANEL_RAW + ) self.ui = UIManager() self.spritelist: SpriteList[Sprite] = arcade.SpriteList() - textbox_template = dict(width=40, height=20, text_color=arcade.color.BLACK) - self.cursor_x_field = UIInputText( - text="1.0", **textbox_template).with_background(texture=self.nine_patch) + self.cursor_x_field = UIInputText(text="1.0", **textbox_template).with_background( + texture=self.nine_patch + ) - self.cursor_y_field = UIInputText( - text="1.0", **textbox_template).with_background(texture=self.nine_patch) + self.cursor_y_field = UIInputText(text="1.0", **textbox_template).with_background( + texture=self.nine_patch + ) self.rows = UIBoxLayout(space_between=20).with_background(color=arcade.color.GRAY) @@ -206,11 +186,7 @@ def __init__( self.on_widget = False def build_sprite_grid( - self, - columns: int, - rows: int, - grid_tile_px: int, - offset: tuple[float, float] = (0, 0) + self, columns: int, rows: int, grid_tile_px: int, offset: tuple[float, float] = (0, 0) ): offset_x, offset_y = offset self.spritelist.clear() @@ -254,4 +230,5 @@ def on_draw(self): self.ui.draw() -MyGame().run() \ No newline at end of file + +MyGame().run() diff --git a/tests/unit/atlas/conftest.py b/tests/unit/atlas/conftest.py index 699182ff6e..68792dc623 100644 --- a/tests/unit/atlas/conftest.py +++ b/tests/unit/atlas/conftest.py @@ -8,7 +8,6 @@ def common(): class Common: - @staticmethod def check_internals( atlas: arcade.DefaultTextureAtlas, @@ -30,7 +29,7 @@ def check_internals( # Unique textures assert len(atlas._unique_textures) == unique_textures - assert len(atlas._texture_uvs) == unique_textures # potentially also test free slots + assert len(atlas._texture_uvs) == unique_textures # potentially also test free slots assert len(atlas._texture_regions) == unique_textures assert len(atlas._unique_texture_ref_count) == unique_textures diff --git a/tests/unit/atlas/test_basics.py b/tests/unit/atlas/test_basics.py index e7cdf371ef..1d682a2827 100644 --- a/tests/unit/atlas/test_basics.py +++ b/tests/unit/atlas/test_basics.py @@ -120,9 +120,9 @@ def test_update_texture_image(ctx): atlas.update_texture_image(tex_3) # Test pixels one pixel in the middle of each texture to verify # the images was replaced with colored textures - assert b'\xff\x00\x00\xff' == atlas.fbo.read(viewport=(32, 32, 1, 1), components=4) - assert b'\x00\xff\x00\xff' == atlas.fbo.read(viewport=(96, 32, 1, 1), components=4) - assert b'\x00\x00\xff\xff' == atlas.fbo.read(viewport=(160, 32, 1, 1), components=4) + assert b"\xff\x00\x00\xff" == atlas.fbo.read(viewport=(32, 32, 1, 1), components=4) + assert b"\x00\xff\x00\xff" == atlas.fbo.read(viewport=(96, 32, 1, 1), components=4) + assert b"\x00\x00\xff\xff" == atlas.fbo.read(viewport=(160, 32, 1, 1), components=4) def test_uv_buffers_after_change(ctx): diff --git a/tests/unit/atlas/test_gc.py b/tests/unit/atlas/test_gc.py index 946e4adead..e637e483b2 100644 --- a/tests/unit/atlas/test_gc.py +++ b/tests/unit/atlas/test_gc.py @@ -2,7 +2,6 @@ import arcade - def test_gc_image_multi_ref(ctx, common): """Test how atlas handles unique textures with the same image""" atlas = arcade.DefaultTextureAtlas((256, 256)) @@ -17,26 +16,45 @@ def test_gc_image_multi_ref(ctx, common): for i, texture in enumerate((texture_1, texture_2, texture_3, texture_4, texture_5, texture_6)): atlas.add(texture) - common.check_internals(atlas, images=1, textures=i + 1, unique_textures=i + 1, textures_added=i + 1, textures_removed=0) + common.check_internals( + atlas, + images=1, + textures=i + 1, + unique_textures=i + 1, + textures_added=i + 1, + textures_removed=0, + ) texture = None common.check_internals(atlas, images=1, textures=6, unique_textures=6) # # Remove a texture one by one texture_1 = None - common.check_internals(atlas, images=1, textures=5, unique_textures=5, textures_added=6, textures_removed=1) + common.check_internals( + atlas, images=1, textures=5, unique_textures=5, textures_added=6, textures_removed=1 + ) texture_2 = None - common.check_internals(atlas, images=1, textures=4, unique_textures=4, textures_added=6, textures_removed=2) + common.check_internals( + atlas, images=1, textures=4, unique_textures=4, textures_added=6, textures_removed=2 + ) texture_3 = None - common.check_internals(atlas, images=1, textures=3, unique_textures=3, textures_added=6, textures_removed=3) + common.check_internals( + atlas, images=1, textures=3, unique_textures=3, textures_added=6, textures_removed=3 + ) texture_4 = None - common.check_internals(atlas, images=1, textures=2, unique_textures=2, textures_added=6, textures_removed=4) + common.check_internals( + atlas, images=1, textures=2, unique_textures=2, textures_added=6, textures_removed=4 + ) texture_5 = None - common.check_internals(atlas, images=1, textures=1, unique_textures=1, textures_added=6, textures_removed=5) + common.check_internals( + atlas, images=1, textures=1, unique_textures=1, textures_added=6, textures_removed=5 + ) texture_6 = None gc.collect() gc.collect() - common.check_internals(atlas, images=0, textures=0, unique_textures=0, textures_added=6, textures_removed=6) + common.check_internals( + atlas, images=0, textures=0, unique_textures=0, textures_added=6, textures_removed=6 + ) def test_gc_image_multi_ref_duplicates(ctx, common): @@ -45,20 +63,30 @@ def test_gc_image_multi_ref_duplicates(ctx, common): # Load the texture multiple times texture_1 = arcade.load_texture(":assets:images/topdown_tanks/tank_sand.png") # unique 1 - texture_2 = texture_1.rotate_90() # unique 2 + texture_2 = texture_1.rotate_90() # unique 2 texture_3 = arcade.load_texture(":assets:images/topdown_tanks/tank_sand.png") # duplicate or 1 - texture_4 = texture_3.rotate_180() # unique 3 + texture_4 = texture_3.rotate_180() # unique 3 # Add them one by one and check the internals atlas.add(texture_1) - common.check_internals(atlas, images=1, textures=1, unique_textures=1, textures_added=1, textures_removed=0) + common.check_internals( + atlas, images=1, textures=1, unique_textures=1, textures_added=1, textures_removed=0 + ) atlas.add(texture_2) - common.check_internals(atlas, images=1, textures=2, unique_textures=2, textures_added=2, textures_removed=0) + common.check_internals( + atlas, images=1, textures=2, unique_textures=2, textures_added=2, textures_removed=0 + ) atlas.add(texture_3) - common.check_internals(atlas, images=1, textures=3, unique_textures=2, textures_added=3, textures_removed=0) + common.check_internals( + atlas, images=1, textures=3, unique_textures=2, textures_added=3, textures_removed=0 + ) atlas.add(texture_4) - common.check_internals(atlas, images=1, textures=4, unique_textures=3, textures_added=4, textures_removed=0) + common.check_internals( + atlas, images=1, textures=4, unique_textures=3, textures_added=4, textures_removed=0 + ) # Remove a texture one by one and check the internals texture_1 = None - common.check_internals(atlas, images=1, textures=3, unique_textures=3, textures_added=4, textures_removed=1) + common.check_internals( + atlas, images=1, textures=3, unique_textures=3, textures_added=4, textures_removed=1 + ) diff --git a/tests/unit/atlas/test_rebuild_resize.py b/tests/unit/atlas/test_rebuild_resize.py index 483967c79d..0b381c6911 100644 --- a/tests/unit/atlas/test_rebuild_resize.py +++ b/tests/unit/atlas/test_rebuild_resize.py @@ -17,7 +17,9 @@ def test_rebuild(ctx, common): slot_b, region_b = atlas.add(tex_small) region_a = atlas.get_texture_region_info(tex_big.atlas_name) region_b = atlas.get_texture_region_info(tex_small.atlas_name) - common.check_internals(atlas, images=2, textures=2, unique_textures=2, textures_added=2, textures_removed=0) + common.check_internals( + atlas, images=2, textures=2, unique_textures=2, textures_added=2, textures_removed=0 + ) # Re-build and check states atlas.rebuild() @@ -25,7 +27,9 @@ def test_rebuild(ctx, common): assert slot_b == atlas.get_texture_id(tex_small) region_aa = atlas.get_texture_region_info(tex_big.atlas_name) region_bb = atlas.get_texture_region_info(tex_small.atlas_name) - common.check_internals(atlas, images=2, textures=2, unique_textures=2, textures_added=2, textures_removed=0) + common.check_internals( + atlas, images=2, textures=2, unique_textures=2, textures_added=2, textures_removed=0 + ) # The textures have switched places in the atlas and should # have the same left position @@ -34,7 +38,9 @@ def test_rebuild(ctx, common): assert region_b.texture_coordinates[0] != region_bb.texture_coordinates[0] assert region_a.texture_coordinates[0] != region_aa.texture_coordinates[0] - common.check_internals(atlas, images=2, textures=2, unique_textures=2, textures_added=2, textures_removed=0) + common.check_internals( + atlas, images=2, textures=2, unique_textures=2, textures_added=2, textures_removed=0 + ) def test_resize(ctx, common): @@ -47,9 +53,13 @@ def test_resize(ctx, common): atlas.add(t1) atlas.add(t2) - common.check_internals(atlas, images=2, textures=2, unique_textures=2, textures_added=2, textures_removed=0) + common.check_internals( + atlas, images=2, textures=2, unique_textures=2, textures_added=2, textures_removed=0 + ) atlas.resize((50, 100)) - common.check_internals(atlas, images=2, textures=2, unique_textures=2, textures_added=2, textures_removed=0) + common.check_internals( + atlas, images=2, textures=2, unique_textures=2, textures_added=2, textures_removed=0 + ) assert atlas._textures_added == 2 assert atlas._finalizers_created == 2 @@ -65,7 +75,9 @@ def test_resize(ctx, common): t1 = arcade.Texture(image=PIL.Image.new("RGBA", (50, 50), (255, 0, 0, 255))) t2 = arcade.Texture(image=PIL.Image.new("RGBA", (50, 50), (0, 255, 0, 255))) atlas.add(t1) - common.check_internals(atlas, images=1, textures=1, unique_textures=1, textures_added=1, textures_removed=0) + common.check_internals( + atlas, images=1, textures=1, unique_textures=1, textures_added=1, textures_removed=0 + ) with pytest.raises(AllocatorException): atlas.add(t2) diff --git a/tests/unit/atlas/test_region.py b/tests/unit/atlas/test_region.py index 59dbdfdb0f..be03f8bbf2 100644 --- a/tests/unit/atlas/test_region.py +++ b/tests/unit/atlas/test_region.py @@ -1,5 +1,6 @@ """Test AtlasRegion class.""" -import pytest + +import pytest import PIL.Image from arcade.texture_atlas.region import AtlasRegion @@ -18,10 +19,14 @@ def test_region_coordinates_simple(ctx): # Simulate the half pixel location a, b = 0, 1.0 assert region.texture_coordinates == ( - a, a, - b, a, - a, b, - b, b, + a, + a, + b, + a, + a, + b, + b, + b, ) diff --git a/tests/unit/atlas/test_update_texture_image_from_atlas.py b/tests/unit/atlas/test_update_texture_image_from_atlas.py index 362830caf3..f44a4e6e82 100644 --- a/tests/unit/atlas/test_update_texture_image_from_atlas.py +++ b/tests/unit/atlas/test_update_texture_image_from_atlas.py @@ -1,6 +1,7 @@ """ Test syncing atlas textures back into PIL images. """ + from PIL import Image, ImageDraw import arcade diff --git a/tests/unit/camera/test_camera2d.py b/tests/unit/camera/test_camera2d.py index a7a199d1fd..0760405075 100644 --- a/tests/unit/camera/test_camera2d.py +++ b/tests/unit/camera/test_camera2d.py @@ -142,7 +142,8 @@ def test_move_camera_and_unproject(window: Window): assert screen_coordinate == (pytest.approx(0), pytest.approx(0)) -@pytest.mark.parametrize('angle', ROTATIONS) + +@pytest.mark.parametrize("angle", ROTATIONS) def test_rotate_camera_with_angle(window: Window, angle: float): camera = Camera2D() camera.angle = angle @@ -151,7 +152,8 @@ def test_rotate_camera_with_angle(window: Window, angle: float): assert camera.up.x == pytest.approx(up.x) assert camera.up.y == pytest.approx(up.y) -@pytest.mark.parametrize('angle', ROTATIONS) + +@pytest.mark.parametrize("angle", ROTATIONS) def test_camera_corner_properties(window: Window, angle: float): camera = Camera2D(projection=LRBT(-1.0, 1.0, -1.0, 1.0), position=(0.0, 0.0)) camera.angle = angle diff --git a/tests/unit/camera/test_camera_controller_methods.py b/tests/unit/camera/test_camera_controller_methods.py index c937d08daa..87848412fe 100644 --- a/tests/unit/camera/test_camera_controller_methods.py +++ b/tests/unit/camera/test_camera_controller_methods.py @@ -16,7 +16,9 @@ def test_strafe(): # Then for dirs in directions: camera_data.position = grips.strafe(camera_data, dirs) - assert camera_data.position == (dirs[0], dirs[1], 0.0), f"Strafe failed to move the camera data correctly, {dirs}" + assert camera_data.position == (dirs[0], dirs[1], 0.0), ( + f"Strafe failed to move the camera data correctly, {dirs}" + ) camera_data.position = (0.0, 0.0, 0.0) # Given @@ -25,7 +27,9 @@ def test_strafe(): for dirs in directions: camera_data.position = grips.strafe(camera_data, dirs) - assert camera_data.position == (0.0, dirs[1], dirs[0]), f"Strafe failed to move the camera data correctly, {dirs}" + assert camera_data.position == (0.0, dirs[1], dirs[0]), ( + f"Strafe failed to move the camera data correctly, {dirs}" + ) camera_data.position = (0.0, 0.0, 0.0) diff --git a/tests/unit/camera/test_camera_shake.py b/tests/unit/camera/test_camera_shake.py index 6e431bbfb4..7346f370c5 100644 --- a/tests/unit/camera/test_camera_shake.py +++ b/tests/unit/camera/test_camera_shake.py @@ -15,10 +15,18 @@ def test_reset(window: Window): screen_shaker.reset() # Then - assert screen_shaker._current_dir == 0.0, "ScreenShakeController failed to reset properly [current_dir]" - assert screen_shaker._last_vector == (0.0, 0.0, 0.0), "ScreenShakeController failed to reset properly [last_vector]" - assert screen_shaker._length_shaking == 0.0, "ScreenShakeController failed to reset properly [length_shaking]" - assert screen_shaker._last_update_time == 0.0, "ScreenShakeController failed to reset properly [last_update_time]" + assert screen_shaker._current_dir == 0.0, ( + "ScreenShakeController failed to reset properly [current_dir]" + ) + assert screen_shaker._last_vector == (0.0, 0.0, 0.0), ( + "ScreenShakeController failed to reset properly [last_vector]" + ) + assert screen_shaker._length_shaking == 0.0, ( + "ScreenShakeController failed to reset properly [length_shaking]" + ) + assert screen_shaker._last_update_time == 0.0, ( + "ScreenShakeController failed to reset properly [last_update_time]" + ) def test_update(window: Window): @@ -27,21 +35,25 @@ def test_update(window: Window): screen_shaker = ScreenShake2D(camera_view) # When - screen_shaker.update(1/60) + screen_shaker.update(1 / 60) # Then - assert screen_shaker._length_shaking == 0.0, "ScreenShakeController updated when it had not started" + assert screen_shaker._length_shaking == 0.0, ( + "ScreenShakeController updated when it had not started" + ) # When screen_shaker.start() - screen_shaker.update(1/60) + screen_shaker.update(1 / 60) # Then - assert screen_shaker._length_shaking == 1/60, "ScreenShakeController failed to update by the correct dt" + assert screen_shaker._length_shaking == 1 / 60, ( + "ScreenShakeController failed to update by the correct dt" + ) # When screen_shaker.stop() - screen_shaker.update(1/60) + screen_shaker.update(1 / 60) # Then assert screen_shaker._length_shaking == 0.0, "ScreenShakeController failed to stop updating" @@ -51,7 +63,9 @@ def test_update(window: Window): screen_shaker.update(2.0) # Then - assert not screen_shaker.shaking, "ScreenShakeController failed to stop when shaking for too long" + assert not screen_shaker.shaking, ( + "ScreenShakeController failed to stop when shaking for too long" + ) def test_update_camera(window: Window): @@ -63,12 +77,16 @@ def test_update_camera(window: Window): # When screen_shaker.start() - screen_shaker.update(1/60) + screen_shaker.update(1 / 60) screen_shaker.update_camera() # Then - assert camera_view.position != cam_pos, "ScreenShakeController failed to change the camera's position" - assert screen_shaker._last_vector != (0.0, 0.0, 0.0), "ScreenShakeController failed to store the last vector" + assert camera_view.position != cam_pos, ( + "ScreenShakeController failed to change the camera's position" + ) + assert screen_shaker._last_vector != (0.0, 0.0, 0.0), ( + "ScreenShakeController failed to store the last vector" + ) _adjust_test = ( camera_view.position[0] - screen_shaker._last_vector[0], camera_view.position[1] - screen_shaker._last_vector[1], @@ -90,5 +108,9 @@ def test_readjust_camera(window: Window): screen_shaker.readjust_camera() # Then - assert camera_view.position == cam_pos, "ScreenShakeController failed to readjust the camera position" - assert screen_shaker._last_vector == (0.0, 0.0, 0.0), "ScreenShakeController failed to reset the last vector" + assert camera_view.position == cam_pos, ( + "ScreenShakeController failed to readjust the camera position" + ) + assert screen_shaker._last_vector == (0.0, 0.0, 0.0), ( + "ScreenShakeController failed to reset the last vector" + ) diff --git a/tests/unit/camera/test_orthographic_projector.py b/tests/unit/camera/test_orthographic_projector.py index 3c2220d7f2..8834a71f2e 100644 --- a/tests/unit/camera/test_orthographic_projector.py +++ b/tests/unit/camera/test_orthographic_projector.py @@ -69,7 +69,7 @@ def test_orthographic_projector_map_coordinates_move(window: Window, width, heig ortho_camera = camera.OrthographicProjector() default_view = ortho_camera.view - half_width, half_height = window.width//2, window.height//2 + half_width, half_height = window.width // 2, window.height // 2 mouse_pos_a = (half_width, half_height) mouse_pos_b = (100.0, 100.0) @@ -79,10 +79,8 @@ def test_orthographic_projector_map_coordinates_move(window: Window, width, heig # Then assert tuple(ortho_camera.unproject(mouse_pos_a)) == pytest.approx((0.0, 0.0, 0.0)) - assert ( - tuple(ortho_camera.unproject(mouse_pos_b)) - == - pytest.approx((-half_width+100.0, -half_height+100, 0.0)) + assert tuple(ortho_camera.unproject(mouse_pos_b)) == pytest.approx( + (-half_width + 100.0, -half_height + 100, 0.0) ) # And @@ -92,10 +90,8 @@ def test_orthographic_projector_map_coordinates_move(window: Window, width, heig # Then assert tuple(ortho_camera.unproject(mouse_pos_a)) == pytest.approx((100.0, 100.0, 0.0)) - assert ( - tuple(ortho_camera.unproject(mouse_pos_b)) - == - pytest.approx((-half_width+200.0, -half_height+200.0, 0.0)) + assert tuple(ortho_camera.unproject(mouse_pos_b)) == pytest.approx( + (-half_width + 200.0, -half_height + 200.0, 0.0) ) @@ -106,7 +102,7 @@ def test_orthographic_projector_map_coordinates_rotate(window: Window, width, he ortho_camera = camera.OrthographicProjector() default_view = ortho_camera.view - half_width, half_height = window.width//2, window.height//2 + half_width, half_height = window.width // 2, window.height // 2 mouse_pos_a = (half_width, half_height) mouse_pos_b = (100.0, 100.0) @@ -117,10 +113,8 @@ def test_orthographic_projector_map_coordinates_rotate(window: Window, width, he # Then assert tuple(ortho_camera.unproject(mouse_pos_a)) == pytest.approx((0.0, 0.0, 0.0)) - assert ( - tuple(ortho_camera.unproject(mouse_pos_b)) - == - pytest.approx((-half_height+100.0, half_width-100.0, 0.0)) + assert tuple(ortho_camera.unproject(mouse_pos_b)) == pytest.approx( + (-half_height + 100.0, half_width - 100.0, 0.0) ) # And @@ -135,10 +129,8 @@ def test_orthographic_projector_map_coordinates_rotate(window: Window, width, he b_rotated_y = -b_shift_x / (2.0**0.5) + b_shift_y / (2.0**0.5) + 100 # Then assert tuple(ortho_camera.unproject(mouse_pos_a)) == pytest.approx((100.0, 100.0, 0.0)) - assert ( - tuple(ortho_camera.unproject(mouse_pos_b)) - == - pytest.approx((b_rotated_x, b_rotated_y, 0.0)) + assert tuple(ortho_camera.unproject(mouse_pos_b)) == pytest.approx( + (b_rotated_x, b_rotated_y, 0.0) ) @@ -149,7 +141,7 @@ def test_orthographic_projector_map_coordinates_zoom(window: Window, width, heig ortho_camera = camera.OrthographicProjector() default_view = ortho_camera.view - half_width, half_height = window.width//2, window.height//2 + half_width, half_height = window.width // 2, window.height // 2 mouse_pos_a = (window.width, window.height) mouse_pos_b = (100.0, 100.0) @@ -158,15 +150,11 @@ def test_orthographic_projector_map_coordinates_zoom(window: Window, width, heig default_view.zoom = 2.0 # Then - assert ( - tuple(ortho_camera.unproject(mouse_pos_a)) - == - pytest.approx(Vec3(window.width*0.75, window.height*0.75, 0.0)) + assert tuple(ortho_camera.unproject(mouse_pos_a)) == pytest.approx( + Vec3(window.width * 0.75, window.height * 0.75, 0.0) ) - assert ( - tuple(ortho_camera.unproject(mouse_pos_b)) - == - pytest.approx((half_width + (100 - half_width)*0.5, half_height + (100 - half_height)*0.5, 0.0)) + assert tuple(ortho_camera.unproject(mouse_pos_b)) == pytest.approx( + (half_width + (100 - half_width) * 0.5, half_height + (100 - half_height) * 0.5, 0.0) ) # And @@ -176,13 +164,9 @@ def test_orthographic_projector_map_coordinates_zoom(window: Window, width, heig default_view.zoom = 0.25 # Then - assert ( - tuple(ortho_camera.unproject(mouse_pos_a)) - == - pytest.approx((window.width*2.0, window.height*2.0, 0.0)) + assert tuple(ortho_camera.unproject(mouse_pos_a)) == pytest.approx( + (window.width * 2.0, window.height * 2.0, 0.0) ) - assert ( - tuple(ortho_camera.unproject(mouse_pos_b)) - == - pytest.approx(((100 - half_width)*4.0, (100 - half_height)*4.0, 0.0)) + assert tuple(ortho_camera.unproject(mouse_pos_b)) == pytest.approx( + ((100 - half_width) * 4.0, (100 - half_height) * 4.0, 0.0) ) diff --git a/tests/unit/camera/test_perspective_projector.py b/tests/unit/camera/test_perspective_projector.py index 8201e6ed3d..e4e0caa906 100644 --- a/tests/unit/camera/test_perspective_projector.py +++ b/tests/unit/camera/test_perspective_projector.py @@ -51,7 +51,7 @@ def test_perspective_projector_map_coordinates(window: Window, width, height): window.set_size(width, height) persp_camera = camera.PerspectiveProjector() - depth = (0.5 * persp_camera.viewport.height / tan(radians(0.5 * persp_camera._projection.fov))) + depth = 0.5 * persp_camera.viewport.height / tan(radians(0.5 * persp_camera._projection.fov)) # When mouse_pos_a = (100.0, 100.0) @@ -71,9 +71,9 @@ def test_perspective_projector_map_coordinates_move(window: Window, width, heigh persp_camera = camera.PerspectiveProjector() default_view = persp_camera.view - depth = (0.5 * persp_camera.viewport.height / tan(radians(0.5 * persp_camera._projection.fov))) + depth = 0.5 * persp_camera.viewport.height / tan(radians(0.5 * persp_camera._projection.fov)) - half_width, half_height = window.width//2, window.height//2 + half_width, half_height = window.width // 2, window.height // 2 mouse_pos_a = (half_width, half_height) mouse_pos_b = (100.0, 100.0) @@ -83,10 +83,8 @@ def test_perspective_projector_map_coordinates_move(window: Window, width, heigh # Then assert tuple(persp_camera.unproject(mouse_pos_a)) == pytest.approx((0.0, 0.0, depth)) - assert ( - tuple(persp_camera.unproject(mouse_pos_b)) - == - pytest.approx((-half_width+100.0, -half_height+100, depth)) + assert tuple(persp_camera.unproject(mouse_pos_b)) == pytest.approx( + (-half_width + 100.0, -half_height + 100, depth) ) # And @@ -96,10 +94,8 @@ def test_perspective_projector_map_coordinates_move(window: Window, width, heigh # Then assert tuple(persp_camera.unproject(mouse_pos_a)) == pytest.approx((100.0, 100.0, depth)) - assert ( - tuple(persp_camera.unproject(mouse_pos_b)) - == - pytest.approx((-half_width+200.0, -half_height+200.0, depth)) + assert tuple(persp_camera.unproject(mouse_pos_b)) == pytest.approx( + (-half_width + 200.0, -half_height + 200.0, depth) ) @@ -110,9 +106,9 @@ def test_perspective_projector_map_coordinates_rotate(window: Window, width, hei persp_camera = camera.PerspectiveProjector() default_view = persp_camera.view - depth = (0.5 * persp_camera.viewport.height / tan(radians(0.5 * persp_camera._projection.fov))) + depth = 0.5 * persp_camera.viewport.height / tan(radians(0.5 * persp_camera._projection.fov)) - half_width, half_height = window.width//2, window.height//2 + half_width, half_height = window.width // 2, window.height // 2 mouse_pos_a = (half_width, half_height) mouse_pos_b = (100.0, 100.0) @@ -123,10 +119,8 @@ def test_perspective_projector_map_coordinates_rotate(window: Window, width, hei # Then assert tuple(persp_camera.unproject(mouse_pos_a)) == pytest.approx((0.0, 0.0, depth)) - assert ( - tuple(persp_camera.unproject(mouse_pos_b)) - == - pytest.approx((-half_height+100.0, half_width-100.0, depth)) + assert tuple(persp_camera.unproject(mouse_pos_b)) == pytest.approx( + (-half_height + 100.0, half_width - 100.0, depth) ) # And @@ -141,9 +135,6 @@ def test_perspective_projector_map_coordinates_rotate(window: Window, width, hei b_rotated_y = -b_shift_x / (2.0**0.5) + b_shift_y / (2.0**0.5) + 100 # Then assert tuple(persp_camera.unproject(mouse_pos_a)) == pytest.approx((100.0, 100.0, depth)) - assert ( - tuple(persp_camera.unproject(mouse_pos_b)) - == - pytest.approx((b_rotated_x, b_rotated_y, depth)) + assert tuple(persp_camera.unproject(mouse_pos_b)) == pytest.approx( + (b_rotated_x, b_rotated_y, depth) ) - diff --git a/tests/unit/camera/test_viewport_projector.py b/tests/unit/camera/test_viewport_projector.py index ebd33d55e4..f99098ff1a 100644 --- a/tests/unit/camera/test_viewport_projector.py +++ b/tests/unit/camera/test_viewport_projector.py @@ -5,11 +5,13 @@ from arcade import camera, Window from arcade.types import Point, LBWH, Rect + @pytest.mark.parametrize("wrld_pos", [Vec2(100, 150), Vec2(1280, 720), Vec3(500, 500, -10)]) def test_viewport_projector_project(window: Window, wrld_pos: Point): cam = camera.default.ViewportProjector() assert cam.project(wrld_pos) == wrld_pos.xy + @pytest.mark.parametrize("wrld_pos", [Vec2(100, 150), Vec2(1280, 720), Vec3(500, 500, -10)]) def test_viewport_projector_unproject(window: Window, wrld_pos: Point): cam = camera.default.ViewportProjector() @@ -17,7 +19,10 @@ def test_viewport_projector_unproject(window: Window, wrld_pos: Point): assert cam.unproject(wrld_pos) == Vec3(x, y, 0.0 if not z else z[0]) -@pytest.mark.parametrize("viewport", [LBWH(0.0, 0.0, 100, 200), LBWH(100, 100, 20, 40), LBWH(300, 20, 20, 700)]) + +@pytest.mark.parametrize( + "viewport", [LBWH(0.0, 0.0, 100, 200), LBWH(100, 100, 20, 40), LBWH(300, 20, 20, 700)] +) def test_viewport_projector_viewport(window: Window, viewport: Rect): cam = camera.default.ViewportProjector() assert cam.viewport.lbwh_int == window.ctx.viewport diff --git a/tests/unit/color/test_color_type.py b/tests/unit/color/test_color_type.py index 7bf5dc11f7..c92f66fe7d 100644 --- a/tests/unit/color/test_color_type.py +++ b/tests/unit/color/test_color_type.py @@ -173,7 +173,7 @@ def test_color_from_hex_string(): assert Color.from_hex_string("#fff") == (255, 255, 255, 255) assert Color.from_hex_string("FFF") == (255, 255, 255, 255) - for bad_value in ("ppp", 'ff', "e"): + for bad_value in ("ppp", "ff", "e"): with pytest.raises(ValueError): Color.from_hex_string(bad_value) @@ -197,7 +197,7 @@ def test_color_rgb_property(): # Spot check unique colors assert colors.COBALT.rgb == (0, 71, 171) - assert Color(1,3,5,7).rgb == (1, 3, 5) + assert Color(1, 3, 5, 7).rgb == (1, 3, 5) def test_deepcopy_color_values(): @@ -246,11 +246,10 @@ def randint_is_constant(monkeypatch): repeated value (128, or 0x80 in hex) to represent a channel fetched from random rather than taken from user input. """ - monkeypatch.setattr('random.randint', Mock(return_value=0x80808080)) + monkeypatch.setattr("random.randint", Mock(return_value=0x80808080)) def test_color_random(randint_is_constant): - for combo in product((None, 0), repeat=4): color = Color.random(*combo) for channel_value, channel_arg in zip(color, combo): diff --git a/tests/unit/color/test_module_csscolor.py b/tests/unit/color/test_module_csscolor.py index f238c95ecb..dce43eba3e 100644 --- a/tests/unit/color/test_module_csscolor.py +++ b/tests/unit/color/test_module_csscolor.py @@ -1,6 +1,6 @@ - def test_csscolors(): from arcade import csscolor + names = csscolor.__dict__.keys() # number of colors + 1 import assert 156 + 1 == len(names) diff --git a/tests/unit/draw/test_drawing_primitives.py b/tests/unit/draw/test_drawing_primitives.py index 2d429670e4..8c3d81ced9 100644 --- a/tests/unit/draw/test_drawing_primitives.py +++ b/tests/unit/draw/test_drawing_primitives.py @@ -23,12 +23,7 @@ def test_draw_primitives(window): # Draw a set of points arcade.draw_text("draw_points", 123, 405, arcade.color.BLACK, 12) - point_list = ((165, 495), - (165, 480), - (165, 465), - (195, 495), - (195, 480), - (195, 465)) + point_list = ((165, 495), (165, 480), (165, 465), (195, 495), (195, 480), (195, 465)) arcade.draw_points(point_list, arcade.color.ZAFFRE, 10) # Draw a line @@ -37,45 +32,23 @@ def test_draw_primitives(window): # Draw a set of lines arcade.draw_text("draw_lines", 363, 405, arcade.color.BLACK, 12) - point_list = ((390, 450), - (450, 450), - (390, 480), - (450, 480), - (390, 510), - (450, 510) - ) + point_list = ((390, 450), (450, 450), (390, 480), (450, 480), (390, 510), (450, 510)) arcade.draw_lines(point_list, arcade.color.BLUE, 3) # Draw a line strip arcade.draw_text("draw_line_strip", 483, 405, arcade.color.BLACK, 12) - point_list = ((510, 450), - (570, 450), - (510, 480), - (570, 480), - (510, 510), - (570, 510) - ) + point_list = ((510, 450), (570, 450), (510, 480), (570, 480), (510, 510), (570, 510)) arcade.draw_line_strip(point_list, arcade.color.TROPICAL_RAIN_FOREST, 3) arcade.draw_line_strip(point_list, arcade.color.BEIGE) # Draw a polygon arcade.draw_text("draw_polygon_outline", 3, 207, arcade.color.BLACK, 9) - point_list = ((30, 240), - (45, 240), - (60, 255), - (60, 285), - (45, 300), - (30, 300)) + point_list = ((30, 240), (45, 240), (60, 255), (60, 285), (45, 300), (30, 300)) arcade.draw_polygon_outline(point_list, arcade.color.SPANISH_VIOLET, 3) # Draw a filled in polygon arcade.draw_text("draw_polygon_filled", 123, 207, arcade.color.BLACK, 9) - point_list = ((150, 240), - (165, 240), - (180, 255), - (180, 285), - (165, 300), - (150, 300)) + point_list = ((150, 240), (165, 240), (180, 255), (180, 285), (165, 300), (150, 300)) arcade.draw_polygon_filled(point_list, arcade.color.SPANISH_VIOLET) # Draw an outline of a circle @@ -90,28 +63,24 @@ def test_draw_primitives(window): # Draw an ellipse outline, and another one rotated arcade.draw_text("draw_ellipse_outline", 483, 207, arcade.color.BLACK, 10) arcade.draw_ellipse_outline(540, 273, 15, 36, arcade.color.AMBER, 3) - arcade.draw_ellipse_outline(540, 336, 15, 36, - arcade.color.BLACK_BEAN, 3, 45) + arcade.draw_ellipse_outline(540, 336, 15, 36, arcade.color.BLACK_BEAN, 3, 45) # Draw a filled ellipse, and another one rotated arcade.draw_text("draw_ellipse_filled", 3, 3, arcade.color.BLACK, 10) arcade.draw_ellipse_filled(60, 81, 15, 36, arcade.color.AMBER) - arcade.draw_ellipse_filled(60, 144, 15, 36, - arcade.color.BLACK_BEAN, 45) + arcade.draw_ellipse_filled(60, 144, 15, 36, arcade.color.BLACK_BEAN, 45) # Draw an arc, and another one rotated arcade.draw_text("draw_arc/filled_arc", 123, 3, arcade.color.BLACK, 10) - arcade.draw_arc_outline(150, 81, 15, 36, - arcade.color.BRIGHT_MAROON, 90, 360) - arcade.draw_arc_filled(150, 144, 15, 36, - arcade.color.BOTTLE_GREEN, 90, 360, 45) + arcade.draw_arc_outline(150, 81, 15, 36, arcade.color.BRIGHT_MAROON, 90, 360) + arcade.draw_arc_filled(150, 144, 15, 36, arcade.color.BOTTLE_GREEN, 90, 360, 45) # Draw an rectangle outline arcade.draw_text("draw_rect", 243, 3, arcade.color.BLACK, 10) - arcade.draw_rect_outline(arcade.rect.XYWH(295, 100, 45, 65), - arcade.color.BRITISH_RACING_GREEN) - arcade.draw_rect_outline(arcade.rect.XYWH(295, 160, 20, 45), - arcade.color.BRITISH_RACING_GREEN, 3, 45) + arcade.draw_rect_outline(arcade.rect.XYWH(295, 100, 45, 65), arcade.color.BRITISH_RACING_GREEN) + arcade.draw_rect_outline( + arcade.rect.XYWH(295, 160, 20, 45), arcade.color.BRITISH_RACING_GREEN, 3, 45 + ) # Draw a filled in rectangle arcade.draw_text("draw_filled_rect", 363, 3, arcade.color.BLACK, 10) @@ -122,7 +91,7 @@ def test_draw_primitives(window): # Image from kenney.nl asset pack #1 arcade.draw_text("draw_bitmap", 483, 3, arcade.color.BLACK, 12) texture = arcade.load_texture(":resources:images/space_shooter/playerShip1_orange.png") - scale = .6 + scale = 0.6 # arcade.draw_texture_rectangle(540, 120, scale * texture.width, # scale * texture.height, texture, 0) # arcade.draw_texture_rectangle(540, 60, scale * texture.width, diff --git a/tests/unit/draw/test_rect.py b/tests/unit/draw/test_rect.py index 767f78925d..caceb02f72 100644 --- a/tests/unit/draw/test_rect.py +++ b/tests/unit/draw/test_rect.py @@ -16,7 +16,7 @@ def test_draw_texture_rect(window, offscreen): """Draw a texture rect and compare it to the expected image.""" region = LBWH(0, 0, *TEXTURE.size) - arcade.draw_texture_rect(TEXTURE, region, blend=False, pixelated=True) + arcade.draw_texture_rect(TEXTURE, region, blend=False, pixelated=True) screen_image = offscreen.read_region_image(region, components=3) expected_image = TEXTURE.image.convert("RGB") diff --git a/tests/unit/geometry/test_is_point_in_box.py b/tests/unit/geometry/test_is_point_in_box.py index 8cbd408d22..631ed8d0c4 100644 --- a/tests/unit/geometry/test_is_point_in_box.py +++ b/tests/unit/geometry/test_is_point_in_box.py @@ -29,12 +29,12 @@ def test_point_outside_1px(): def test_zero_box(): """ A box selection with zero width or height - + The selection area should always be included as a hit. """ # 1 x 1 pixel box - assert is_point_in_box((0, 0), (0, 0), (0, 0)) is True + assert is_point_in_box((0, 0), (0, 0), (0, 0)) is True # 1 x 100 pixel box - assert is_point_in_box((0, 0), (50, 0), (100, 0)) is True + assert is_point_in_box((0, 0), (50, 0), (100, 0)) is True # 100 x 1 pixel box - assert is_point_in_box((0, 0), (0, 50), (0, 100)) is True + assert is_point_in_box((0, 0), (0, 50), (0, 100)) is True diff --git a/tests/unit/gl/backends/gl/test_gl_program.py b/tests/unit/gl/backends/gl/test_gl_program.py index 5ea19a789f..5a7971e2ce 100644 --- a/tests/unit/gl/backends/gl/test_gl_program.py +++ b/tests/unit/gl/backends/gl/test_gl_program.py @@ -9,6 +9,7 @@ pytestmark = pytest.mark.backendgl + def test_shader_source(ctx): """Test shader source parsing""" source_wrapper = ShaderSource( @@ -34,10 +35,10 @@ def test_shader_source(ctx): elif ctx.gl_api == "opengles": assert source_wrapper.version == 310 - assert source_wrapper.out_attributes == ['out_pos', 'out_velocity'] - source = source_wrapper.get_source(defines={'TEST': 1, 'TEST2': '2'}) - assert '#define TEST 1' in source - assert '#define TEST2 2' in source + assert source_wrapper.out_attributes == ["out_pos", "out_velocity"] + source = source_wrapper.get_source(defines={"TEST": 1, "TEST2": "2"}) + assert "#define TEST 1" in source + assert "#define TEST2 2" in source def test_shader_source_empty(ctx): @@ -50,12 +51,7 @@ def test_shader_source_missing_version(ctx): with pytest.raises(ShaderException): ShaderSource( ctx, - ( - "in vec3 in_vert\n" - "void main() {\n" - " gl_Position = vec3(in_vert, 1.0);\n" - "}\n" - ), + ("in vec3 in_vert\nvoid main() {\n gl_Position = vec3(in_vert, 1.0);\n}\n"), None, gl.GL_VERTEX_SHADER, ) @@ -66,25 +62,14 @@ def test_shader_source_malformed(ctx): with pytest.raises(ShaderException): ShaderSource( ctx, - ( - "in in_vert\n" - "void main() \n" - " gl_Position = vec3(in_vert, 1.0)\n" - "}\n" - ), + ("in in_vert\nvoid main() \n gl_Position = vec3(in_vert, 1.0)\n}\n"), None, gl.GL_VERTEX_SHADER, ) with pytest.raises(ShaderException): ShaderSource( ctx, - ( - "#version\n" - "in in_vert\n" - "void main() \n" - " gl_Position = vec3(in_vert, 1.0)\n" - "}\n" - ), + ("#version\nin in_vert\nvoid main() \n gl_Position = vec3(in_vert, 1.0)\n}\n"), None, gl.GL_VERTEX_SHADER, ) @@ -104,8 +89,8 @@ def test_shader_source_malformed(ctx): None, gl.GL_VERTEX_SHADER, ) - source = wrapper.get_source(defines={'TEST': 1}) - assert 'TEST 1' in source + source = wrapper.get_source(defines={"TEST": 1}) + assert "TEST 1" in source def test_shader_program_broken_out(ctx): @@ -122,7 +107,7 @@ def test_shader_program_broken_out(ctx): None, gl.GL_VERTEX_SHADER, ) - wrapper.out_attributes == ['out_vert'] + wrapper.out_attributes == ["out_vert"] def test_program_basic(ctx): @@ -158,25 +143,25 @@ def test_program_basic(ctx): assert program.glo > 0 program.use() # assert ctx.active_program == program - assert repr(program).startswith('= (4, 1): program = ctx.program( @@ -310,7 +296,7 @@ def test_varyings(ctx): } """, ) - assert program.varyings == ['out_pos', 'out_velocity'] + assert program.varyings == ["out_pos", "out_velocity"] # Illegal varying names with pytest.raises(ShaderException): @@ -318,9 +304,9 @@ def test_varyings(ctx): # Mapping one of two varyings program = ctx.program(vertex_shader=src, varyings=["out_pos"]) - assert program.varyings == ['out_pos'] + assert program.varyings == ["out_pos"] program = ctx.program(vertex_shader=src, varyings=["out_velocity"]) - assert program.varyings == ['out_velocity'] + assert program.varyings == ["out_velocity"] # Configure capture mode program = ctx.program(vertex_shader=src, varyings_capture_mode="interleaved") @@ -332,7 +318,8 @@ def test_varyings(ctx): def test_uniform_block(ctx): """Test uniform block""" # Simple tranform with a uniform block - program = ctx.program(vertex_shader=""" + program = ctx.program( + vertex_shader=""" #version 330 uniform Projection { uniform mat4 matrix; @@ -346,9 +333,9 @@ def test_uniform_block(ctx): """ ) # Obtain the ubo info and modify binding + test properties - ubo = program['Projection'] + ubo = program["Projection"] assert isinstance(ubo, UniformBlock) - program['Projection'] = 1 + program["Projection"] = 1 assert ubo.binding == 1 ubo.binding = 0 assert ubo.binding == 0 @@ -362,4 +349,4 @@ def test_uniform_block(ctx): vao = ctx.geometry() ubo_buffer.bind_to_uniform_block(0) vao.transform(program, buffer, vertices=1) - assert struct.unpack('2f', buffer.read()) == pytest.approx((1, 1), 0.01) + assert struct.unpack("2f", buffer.read()) == pytest.approx((1, 1), 0.01) diff --git a/tests/unit/gl/test_gl_buffer.py b/tests/unit/gl/test_gl_buffer.py index f8b43126b2..1a919a2e80 100644 --- a/tests/unit/gl/test_gl_buffer.py +++ b/tests/unit/gl/test_gl_buffer.py @@ -3,7 +3,7 @@ def test_properties(ctx): - buffer = ctx.buffer(data=b'Hello world') + buffer = ctx.buffer(data=b"Hello world") assert buffer.glo.value > 0 assert buffer.ctx == ctx @@ -14,10 +14,10 @@ def test_create_empty(ctx): def test_read(ctx): - buffer = ctx.buffer(data=b'Hello world') - assert buffer.read() == b'Hello world' - assert buffer.read(size=5) == b'Hello' - assert buffer.read(size=5, offset=6) == b'world' + buffer = ctx.buffer(data=b"Hello world") + assert buffer.read() == b"Hello world" + assert buffer.read(size=5) == b"Hello" + assert buffer.read(size=5, offset=6) == b"world" # Reading outside buffer by 1 byte with pytest.raises(ValueError): @@ -38,58 +38,58 @@ def test_read(ctx): def test_write(ctx): # Attempt to write too much data buffer = ctx.buffer(reserve=4) - buffer.write(b'Hello World') - assert buffer.read() == b'Hell' + buffer.write(b"Hello World") + assert buffer.read() == b"Hell" # Write too little data buffer = ctx.buffer(reserve=8) - buffer.write(b'Hello') - assert buffer.read() == b'Hello\x00\x00\x00' + buffer.write(b"Hello") + assert buffer.read() == b"Hello\x00\x00\x00" # Write with offset buffer = ctx.buffer(reserve=8) - buffer.write(b'test', offset=4) - assert buffer.read() == b'\x00\x00\x00\x00test' + buffer.write(b"test", offset=4) + assert buffer.read() == b"\x00\x00\x00\x00test" # Clipped data with offset buffer = ctx.buffer(reserve=8) - buffer.write(b'test', offset=6) - assert buffer.read() == b'\x00\x00\x00\x00\x00\x00te' + buffer.write(b"test", offset=6) + assert buffer.read() == b"\x00\x00\x00\x00\x00\x00te" # Write 0 bytes buffer = ctx.buffer(reserve=8) - buffer.write(b'test', offset=8) + buffer.write(b"test", offset=8) # Go past the buffer buffer = ctx.buffer(reserve=8) with pytest.raises(ValueError): - buffer.write(b'test', offset=9) + buffer.write(b"test", offset=9) def test_write_buffer_protocol(ctx): """Write data to buffer with buffer protocol""" - data = array('f', [1, 2, 3, 4]) + data = array("f", [1, 2, 3, 4]) buff = ctx.buffer(data=data) assert buff.read() == data.tobytes() def test_orphan(ctx): - buffer = ctx.buffer(data=b'Hello world') + buffer = ctx.buffer(data=b"Hello world") buffer.orphan(size=20) assert buffer.size == 20 assert len(buffer.read()) == 20 - buffer.write(b'Testing') - assert buffer.read(size=7) == b'Testing' - buffer.write(b'Testing', offset=10) - assert buffer.read(offset=10, size=7) == b'Testing' + buffer.write(b"Testing") + assert buffer.read(size=7) == b"Testing" + buffer.write(b"Testing", offset=10) + assert buffer.read(offset=10, size=7) == b"Testing" buffer.orphan(double=True) assert buffer.size == 40 def test_copy(ctx): - buffer = ctx.buffer(data=b'Hello world') + buffer = ctx.buffer(data=b"Hello world") source = ctx.buffer(reserve=20) buffer.copy_from_buffer(source, size=10, offset=0) # Copy out of bounds in the source buffer diff --git a/tests/unit/gl/test_gl_buffer_description.py b/tests/unit/gl/test_gl_buffer_description.py index 156a1d013b..14c3ca1d79 100644 --- a/tests/unit/gl/test_gl_buffer_description.py +++ b/tests/unit/gl/test_gl_buffer_description.py @@ -6,10 +6,10 @@ def test_buffer_description(ctx): # TODO: components > 4 # TODO: padding buffer = ctx.buffer(reserve=4 * 8) - attribute_names = ['in_vert', 'in_uv'] + attribute_names = ["in_vert", "in_uv"] descr = BufferDescription( buffer, - '2f 2f', + "2f 2f", attribute_names, ) assert descr.num_vertices == 2 diff --git a/tests/unit/gl/test_gl_context.py b/tests/unit/gl/test_gl_context.py index ebf1b21475..e413d8c9b7 100644 --- a/tests/unit/gl/test_gl_context.py +++ b/tests/unit/gl/test_gl_context.py @@ -1,6 +1,7 @@ """ Low level tests for OpenGL 3.3 wrappers. """ + import pytest from pyglet.math import Mat4 @@ -39,6 +40,7 @@ def test_view_matrix(window): with pytest.raises(ValueError): window.ctx.view_matrix = "moo" + def test_projection_matrix(window): """Test setting projection matrix directly""" window.ctx.projection_matrix = Mat4() @@ -81,7 +83,7 @@ def test_enable_disable(ctx): def test_enabled(ctx): - """Enabled only context manager""" + """Enabled only context manager""" assert ctx.is_enabled(ctx.BLEND) assert not ctx.is_enabled(ctx.DEPTH_TEST) @@ -94,7 +96,7 @@ def test_enabled(ctx): def test_enabled_only(ctx): - """Enabled only context manager""" + """Enabled only context manager""" assert ctx.is_enabled(ctx.BLEND) with ctx.enabled_only(ctx.DEPTH_TEST): @@ -107,12 +109,16 @@ def test_enabled_only(ctx): def test_load_texture(ctx): # Default flipped and read value of corner pixel - texture = ctx.load_texture(":resources:images/test_textures/test_texture.png", build_mipmaps=True) - assert texture.read()[:4] == b'\x00\x00\xff\xff' # Blue + texture = ctx.load_texture( + ":resources:images/test_textures/test_texture.png", build_mipmaps=True + ) + assert texture.read()[:4] == b"\x00\x00\xff\xff" # Blue # Don't flip the texture - texture = ctx.load_texture(":resources:images/test_textures/test_texture.png", flip=False, build_mipmaps=True) - assert texture.read()[:4] == b'\xff\x00\x00\xff' # Red + texture = ctx.load_texture( + ":resources:images/test_textures/test_texture.png", flip=False, build_mipmaps=True + ) + assert texture.read()[:4] == b"\xff\x00\x00\xff" # Red def test_shader_include(ctx): diff --git a/tests/unit/gl/test_gl_framebuffer.py b/tests/unit/gl/test_gl_framebuffer.py index a809945d58..18f29f01f8 100644 --- a/tests/unit/gl/test_gl_framebuffer.py +++ b/tests/unit/gl/test_gl_framebuffer.py @@ -2,8 +2,10 @@ import arcade -def create(ctx, width, height, components=4, layers=1, dtype='f1'): - layers = [ctx.texture((width, height), components=components, dtype=dtype) for _ in range(layers)] +def create(ctx, width, height, components=4, layers=1, dtype="f1"): + layers = [ + ctx.texture((width, height), components=components, dtype=dtype) for _ in range(layers) + ] return ctx.framebuffer(color_attachments=layers) @@ -18,7 +20,7 @@ def test_properties(ctx): assert fb.viewport == (0, 0, 10, 20) assert fb.depth_attachment is None assert fb.depth_mask is True - assert repr(fb).startswith('= (4, 3): created, freed = ctx.stats.compute_shader - compute_shader = ctx.compute_shader(source=COMPUTE_SHADER_SOURCE) + compute_shader = ctx.compute_shader(source=COMPUTE_SHADER_SOURCE) assert ctx.stats.compute_shader == (created + 1, freed) compute_shader = None gc.collect() if ctx.gc_mode == "context_gc": collected = ctx.gc() assert collected > 0 - assert ctx.stats.compute_shader == (created + 1, freed + 1) + assert ctx.stats.compute_shader == (created + 1, freed + 1) # query created, freed = ctx.stats.query diff --git a/tests/unit/gl/test_gl_geometry.py b/tests/unit/gl/test_gl_geometry.py index a76b0971d1..8b1b5d6e9f 100644 --- a/tests/unit/gl/test_gl_geometry.py +++ b/tests/unit/gl/test_gl_geometry.py @@ -1,6 +1,7 @@ """ Low level tests for OpenGL 3.3 wrappers. """ + from arcade.gl import geometry diff --git a/tests/unit/gl/test_gl_texture.py b/tests/unit/gl/test_gl_texture.py index a78a9b31d4..3ff6272bb5 100644 --- a/tests/unit/gl/test_gl_texture.py +++ b/tests/unit/gl/test_gl_texture.py @@ -14,7 +14,7 @@ def test_default_properties(ctx): assert texture.filter == (ctx.LINEAR, ctx.LINEAR) assert texture.wrap_x == ctx.REPEAT assert texture.wrap_y == ctx.REPEAT - assert repr(texture).startswith(' tuple[NinePatchTexture, Image.Image,]: +) -> tuple[ + NinePatchTexture, + Image.Image, +]: """Create a ninepatch texture with the given borders.""" # Manually create a ninepatch texture. # We make it white by default and draw a red rectangle in the middle. @@ -31,14 +34,19 @@ def create_ninepatch( # NOTE: Pillow's 0,0 is top left, Arcade's is bottom left. patch_image = Image.new("RGBA", texture_size, (255, 255, 255, 255)) draw = ImageDraw.Draw(patch_image) - draw.rectangle((left, top, texture_size[0] - right - 1, texture_size[1] - bottom - 1), fill=(255, 0, 0, 255)) + draw.rectangle( + (left, top, texture_size[0] - right - 1, texture_size[1] - bottom - 1), + fill=(255, 0, 0, 255), + ) texture = arcade.Texture(patch_image) # patch_image.show() # Create the expected image expected_image = Image.new("RGBA", patch_size, (255, 255, 255, 255)) draw = ImageDraw.Draw(expected_image) - draw.rectangle((left, top, patch_size[0] - right - 1, patch_size[1] - bottom - 1), fill=(255, 0, 0, 255)) + draw.rectangle( + (left, top, patch_size[0] - right - 1, patch_size[1] - bottom - 1), fill=(255, 0, 0, 255) + ) return NinePatchTexture( texture=texture, @@ -67,7 +75,9 @@ def test_draw(ctx, fbo, left, right, bottom, top): ) with fbo.activate(): fbo.clear() - ctx.projection_matrix = Mat4.orthogonal_projection(0, PATCH_SIZE[0], 0, PATCH_SIZE[1], -100, 100) + ctx.projection_matrix = Mat4.orthogonal_projection( + 0, PATCH_SIZE[0], 0, PATCH_SIZE[1], -100, 100 + ) patch.draw_rect( rect=LBWH(0, 0, PATCH_SIZE[0], PATCH_SIZE[1]), pixelated=True, diff --git a/tests/unit/hitbox/test_black_image.py b/tests/unit/hitbox/test_black_image.py index 78624322bd..9558bf6a17 100644 --- a/tests/unit/hitbox/test_black_image.py +++ b/tests/unit/hitbox/test_black_image.py @@ -1,6 +1,7 @@ """ Test fallback for hitbox creation with empty textures. """ + from PIL import Image import arcade diff --git a/tests/unit/hitbox/test_hitbox.py b/tests/unit/hitbox/test_hitbox.py index 0cdde55057..ba601bd109 100644 --- a/tests/unit/hitbox/test_hitbox.py +++ b/tests/unit/hitbox/test_hitbox.py @@ -49,4 +49,4 @@ def test_create_rotatable(): rot_p = rot.get_adjusted_points() for i, (a, b) in enumerate(zip(rot_90, rot_p)): - assert a == pytest.approx(b, abs = 1e-6), f"[{i}] {a} != {b}" + assert a == pytest.approx(b, abs=1e-6), f"[{i}] {a} != {b}" diff --git a/tests/unit/hitbox/test_hitbox_algo_legacy.py b/tests/unit/hitbox/test_hitbox_algo_legacy.py index 7b4ed49de3..92e4972655 100644 --- a/tests/unit/hitbox/test_hitbox_algo_legacy.py +++ b/tests/unit/hitbox/test_hitbox_algo_legacy.py @@ -7,7 +7,7 @@ def test_calculate_hit_box_points_simple(): # Completely filled RGBA image image = Image.new("RGBA", (100, 100), (255, 255, 255, 255)) expected_points = ((-50.0, -50.0), (50.0, -50.0), (50.0, 50.0), (-50.0, 50.0)) - points = hitbox.calculate_hit_box_points_simple(image) + points = hitbox.calculate_hit_box_points_simple(image) assert points == expected_points # Fail trying RGB @@ -20,7 +20,7 @@ def test_calculate_hit_box_points_detailed(): # Completely filled RGBA image image = Image.new("RGBA", (100, 100), (255, 255, 255, 255)) expected_points = ((-50.0, -50.0), (50.0, -50.0), (50.0, 50.0), (-50.0, 50.0)) - points = hitbox.calculate_hit_box_points_detailed(image) + points = hitbox.calculate_hit_box_points_detailed(image) assert points == expected_points # Fail trying RGB diff --git a/tests/unit/paths/test_astar.py b/tests/unit/paths/test_astar.py index d7994a6c7a..4f2772a03e 100644 --- a/tests/unit/paths/test_astar.py +++ b/tests/unit/paths/test_astar.py @@ -1,6 +1,7 @@ """ Test for A-Star path routing """ + import arcade SPRITE_IMAGE_SIZE = 128 @@ -17,14 +18,18 @@ def test_astar(window): enemy_list = arcade.SpriteList() # Set up the player - player = arcade.Sprite(":resources:images/animated_characters/female_person/femalePerson_idle.png", - scale=SPRITE_SCALING) + player = arcade.Sprite( + ":resources:images/animated_characters/female_person/femalePerson_idle.png", + scale=SPRITE_SCALING, + ) player.center_x = SPRITE_SIZE * 1 player.center_y = SPRITE_SIZE * 1 player_list.append(player) # Set enemies - enemy = arcade.Sprite(":resources:images/animated_characters/zombie/zombie_idle.png", scale=SPRITE_SCALING) + enemy = arcade.Sprite( + ":resources:images/animated_characters/zombie/zombie_idle.png", scale=SPRITE_SCALING + ) enemy.center_x = SPRITE_SIZE * 5 enemy.center_y = SPRITE_SIZE * 5 enemy_list.append(enemy) @@ -46,30 +51,40 @@ def test_astar(window): # Note: If the enemy sprites are the same size, we only need to calculate # one of these. We do NOT need a different one for each enemy. The sprite # is just used for a size calculation. - barrier_list = arcade.AStarBarrierList(enemy, - wall_list, - grid_size, - playing_field_left_boundary, - playing_field_right_boundary, - playing_field_bottom_boundary, - playing_field_top_boundary) + barrier_list = arcade.AStarBarrierList( + enemy, + wall_list, + grid_size, + playing_field_left_boundary, + playing_field_right_boundary, + playing_field_bottom_boundary, + playing_field_top_boundary, + ) # print() - path = arcade.astar_calculate_path(enemy.position, - player.position, - barrier_list, - diagonal_movement=False) + path = arcade.astar_calculate_path( + enemy.position, player.position, barrier_list, diagonal_movement=False + ) # barrier_list.recalculate() # print(f"barrier_list: {barrier_list.barrier_list}") # print("Path 1", path) - assert path == [(160, 160), (128, 160), (128, 128), (96, 128), (96, 96), (64, 96), (64, 64), (32, 64), (32, 32)] - - path = arcade.astar_calculate_path(enemy.position, - player.position, - barrier_list, - diagonal_movement=True) + assert path == [ + (160, 160), + (128, 160), + (128, 128), + (96, 128), + (96, 96), + (64, 96), + (64, 64), + (32, 64), + (32, 32), + ] + + path = arcade.astar_calculate_path( + enemy.position, player.position, barrier_list, diagonal_movement=True + ) assert path == [(160, 160), (128, 128), (96, 96), (64, 64), (32, 32)] # print("Path 2", path) @@ -100,9 +115,17 @@ def test_astar(window): barrier_list.recalculate() - path = arcade.astar_calculate_path(enemy.position, - player.position, - barrier_list, - diagonal_movement=True) - - assert path == [(160, 160), (128, 160), (96, 192), (64, 160), (64, 128), (64, 96), (64, 64), (32, 32)] + path = arcade.astar_calculate_path( + enemy.position, player.position, barrier_list, diagonal_movement=True + ) + + assert path == [ + (160, 160), + (128, 160), + (96, 192), + (64, 160), + (64, 128), + (64, 96), + (64, 64), + (32, 32), + ] diff --git a/tests/unit/paths/test_line_of_sight.py b/tests/unit/paths/test_line_of_sight.py index 944b62f305..76afeff28d 100644 --- a/tests/unit/paths/test_line_of_sight.py +++ b/tests/unit/paths/test_line_of_sight.py @@ -2,11 +2,15 @@ def test_line_of_sight(window): - player = arcade.Sprite(":resources:images/animated_characters/female_person/femalePerson_idle.png") + player = arcade.Sprite( + ":resources:images/animated_characters/female_person/femalePerson_idle.png" + ) player.center_x = 0 player.center_y = 350 - enemy = arcade.Sprite(":resources:images/animated_characters/female_person/femalePerson_idle.png") + enemy = arcade.Sprite( + ":resources:images/animated_characters/female_person/femalePerson_idle.png" + ) enemy.center_x = 250 enemy.center_y = 350 diff --git a/tests/unit/physics_engine/test_physics_engine2.py b/tests/unit/physics_engine/test_physics_engine2.py index 0b50a60281..8fdeca83ea 100644 --- a/tests/unit/physics_engine/test_physics_engine2.py +++ b/tests/unit/physics_engine/test_physics_engine2.py @@ -1,4 +1,5 @@ -""" Physics engine tests. """ +"""Physics engine tests.""" + import copy import pytest @@ -17,9 +18,10 @@ def check_spritelists_prop_clears_instead_of_overwrites(engine, prop_name: str): * extra allocations from copying lists (see arcade.utils.Chain) * Avoid GC thrash from creating & deleting items - """ + """ + def _get_current(): - return getattr(engine, f'_{prop_name}') + return getattr(engine, f"_{prop_name}") original_list = _get_current() @@ -258,7 +260,8 @@ def simple_engine_tests(moving_sprite, wall_list, physics_engine): else: assert len(collisions) == 1 - check_spritelists_prop_clears_instead_of_overwrites(physics_engine, 'walls') + check_spritelists_prop_clears_instead_of_overwrites(physics_engine, "walls") + def platformer_tests(moving_sprite, wall_list, physics_engine): wall_sprite_1 = wall_list[0] @@ -327,8 +330,8 @@ def platformer_tests(moving_sprite, wall_list, physics_engine): collisions = physics_engine.update() assert moving_sprite.position == (3, -6) - check_spritelists_prop_clears_instead_of_overwrites(physics_engine, 'platforms') - check_spritelists_prop_clears_instead_of_overwrites(physics_engine, 'ladders') + check_spritelists_prop_clears_instead_of_overwrites(physics_engine, "platforms") + check_spritelists_prop_clears_instead_of_overwrites(physics_engine, "ladders") # Temp fix for https://github.com/pythonarcade/arcade/issues/2074 @@ -357,9 +360,7 @@ def test_main(window: arcade.Window): simple_engine_tests(moving_sprite, wall_list, physics_engine) nocopy_tests(physics_engine) - physics_engine = arcade.PhysicsEnginePlatformer( - moving_sprite, wall_list, gravity_constant=0.0 - ) + physics_engine = arcade.PhysicsEnginePlatformer(moving_sprite, wall_list, gravity_constant=0.0) basic_tests(moving_sprite, wall_list, physics_engine) platformer_tests(moving_sprite, wall_list, physics_engine) nocopy_tests(physics_engine) diff --git a/tests/unit/physics_engine/test_physics_engine_platformer.py b/tests/unit/physics_engine/test_physics_engine_platformer.py index 9818c2857b..a3fffc80f8 100644 --- a/tests/unit/physics_engine/test_physics_engine_platformer.py +++ b/tests/unit/physics_engine/test_physics_engine_platformer.py @@ -33,7 +33,7 @@ def test_physics_engine(window): center_x=64, center_y=256, ) - platform.boundary_left = 0 # 0 in particular was problematic, see #2658 + platform.boundary_left = 0 # 0 in particular was problematic, see #2658 platform.boundary_right = 128 platform.change_x = 8 platform_list.append(platform) @@ -65,7 +65,7 @@ def update(td): window.test(frames=7) assert physics_engine.can_jump() is True - assert platform.center_x == 80 # it bounced against the boundary_right + assert platform.center_x == 80 # it bounced against the boundary_right assert platform.change_x == -8 character_sprite.change_y = 15 physics_engine.increment_jump_counter() @@ -73,11 +73,11 @@ def update(td): window.test(frames=6) assert physics_engine.can_jump() is False - assert platform.center_x == 32 # right at the boundary - assert platform.change_x == -8 # still going left + assert platform.center_x == 32 # right at the boundary + assert platform.change_x == -8 # still going left physics_engine.disable_multi_jump() window.test(frames=3) - assert platform.center_x == 32 + 24 # it bounced against the boundary_left + assert platform.center_x == 32 + 24 # it bounced against the boundary_left assert platform.change_x == +8 diff --git a/tests/unit/physics_engine/test_pymunk.py b/tests/unit/physics_engine/test_pymunk.py index 838051caf4..dfcc07780d 100644 --- a/tests/unit/physics_engine/test_pymunk.py +++ b/tests/unit/physics_engine/test_pymunk.py @@ -7,8 +7,7 @@ def test_pymunk(): - physics_engine = arcade.PymunkPhysicsEngine(damping=1.0, - gravity=(0, -100)) + physics_engine = arcade.PymunkPhysicsEngine(damping=1.0, gravity=(0, -100)) my_sprite = arcade.SpriteSolidColor(50, 50, color=arcade.color.WHITE) @@ -18,20 +17,20 @@ def test_pymunk(): physics_engine.add_sprite(my_sprite) physics_engine.step(1.0) - assert(my_sprite.center_y == 0) + assert my_sprite.center_y == 0 physics_engine.step(1.0) - assert(my_sprite.center_y == -100.0) + assert my_sprite.center_y == -100.0 physics_engine.step(1.0) - assert(my_sprite.center_y == -300.0) + assert my_sprite.center_y == -300.0 # Temp fix for https://github.com/pythonarcade/arcade/issues/2074 def test_pymunk_engine_nocopy(): import copy - physics_engine = arcade.PymunkPhysicsEngine( - damping=1.0, gravity=(0, -100)) + + physics_engine = arcade.PymunkPhysicsEngine(damping=1.0, gravity=(0, -100)) with pytest.raises(NotImplementedError): _ = copy.copy(physics_engine) @@ -39,15 +38,12 @@ def test_pymunk_engine_nocopy(): _ = copy.deepcopy(physics_engine) -@pytest.mark.parametrize("moment_of_inertia_arg_name", - ( - "moment_of_inertia", - )) +@pytest.mark.parametrize("moment_of_inertia_arg_name", ("moment_of_inertia",)) def test_pymunk_add_sprite_moment_backwards_compatibility(moment_of_inertia_arg_name): """ Ensure that all supported kwarg aliases for moment of inertia work """ - physics_engine = arcade.PymunkPhysicsEngine(damping=1.0, gravity=(0,0)) + physics_engine = arcade.PymunkPhysicsEngine(damping=1.0, gravity=(0, 0)) sprite = arcade.SpriteSolidColor(32, 32, color=arcade.color.RED) @@ -71,10 +67,13 @@ def test_pymunk_hitbox_algorithm_trace_image_only_takes_rgba(): """ algo = PymunkHitBoxAlgorithm() + def mode(m: str) -> Image.Image: return Image.new( - m, # type: ignore - (10, 10), 0) + m, # type: ignore + (10, 10), + 0, + ) with pytest.raises(ValueError): algo.trace_image(mode("1")) @@ -91,6 +90,4 @@ def mode(m: str) -> Image.Image: with pytest.raises(ValueError): algo.trace_image(mode("HSV")) - assert isinstance( - algo.trace_image(mode("RGBA")), pymunk.autogeometry.PolylineSet) - + assert isinstance(algo.trace_image(mode("RGBA")), pymunk.autogeometry.PolylineSet) diff --git a/tests/unit/rect/test_rect_creation_helpers.py b/tests/unit/rect/test_rect_creation_helpers.py index 928145762d..f78cb24027 100644 --- a/tests/unit/rect/test_rect_creation_helpers.py +++ b/tests/unit/rect/test_rect_creation_helpers.py @@ -97,7 +97,6 @@ def test_kwargtangle_missing_args(): def test_kwargtangle_none_args(): - # LRBT with pytest.raises(ValueError): _ = Rect.from_kwargs(left=0, right=0, bottom=0, top=None) @@ -109,7 +108,7 @@ def test_kwargtangle_none_args(): _ = Rect.from_kwargs(left=0, right=None, top=0, bottom=0) with pytest.raises(ValueError): - _ = Rect.from_kwargs(left = None, right=0, top=0, bottom=0) + _ = Rect.from_kwargs(left=None, right=0, top=0, bottom=0) # LBWH with pytest.raises(ValueError): diff --git a/tests/unit/rect/test_rect_instances.py b/tests/unit/rect/test_rect_instances.py index 267a6c5d36..faed78c0ec 100644 --- a/tests/unit/rect/test_rect_instances.py +++ b/tests/unit/rect/test_rect_instances.py @@ -21,15 +21,11 @@ def test_attributes(): def test_equivalency(): assert ( - LBWH(10, 10, 10, 10) - == - LRBT(10, 20, 10, 20) - == - XYWH(15, 15, 10, 10) - == - XYRR(15, 15, 5, 5) - == - A_RECT + LBWH(10, 10, 10, 10) + == LRBT(10, 20, 10, 20) + == XYWH(15, 15, 10, 10) + == XYRR(15, 15, 5, 5) + == A_RECT ) @@ -93,27 +89,21 @@ def test_at_position(): def test_views(): assert A_RECT.lrbt == (10, 20, 10, 20) assert A_RECT.lbwh == (10, 10, 10, 10) - assert A_RECT.xyrr == (15, 15, 5, 5) + assert A_RECT.xyrr == (15, 15, 5, 5) assert A_RECT.xywh == (15, 15, 10, 10) -class SubclassedRect(Rect): - ... +class SubclassedRect(Rect): ... ALL_ZEROES = tuple((0 for _ in Rect._fields)) -def _formats_correctly( - func: Callable[[Any], str], - starts_with_format: str, - instance: Any -) -> bool: +def _formats_correctly(func: Callable[[Any], str], starts_with_format: str, instance: Any) -> bool: """True if func(instance) starts w/ its class name as specified.""" class_name = instance.__class__.__name__ - return func(instance).startswith( - starts_with_format.format(class_name=class_name)) + return func(instance).startswith(starts_with_format.format(class_name=class_name)) def test_repr(): diff --git a/tests/unit/resources/test_handles.py b/tests/unit/resources/test_handles.py index d36bd53ccc..6fa242e328 100644 --- a/tests/unit/resources/test_handles.py +++ b/tests/unit/resources/test_handles.py @@ -38,4 +38,3 @@ def test_add_handles(monkeypatch): def test_misc(): path = resources.resolve(":resources:images/cards/cardBack_blue1.png") assert resources.resolve(path) == path - diff --git a/tests/unit/scene/test_scene_dunder_methods.py b/tests/unit/scene/test_scene_dunder_methods.py index 191bf48fb6..e10f1bde2f 100644 --- a/tests/unit/scene/test_scene_dunder_methods.py +++ b/tests/unit/scene/test_scene_dunder_methods.py @@ -47,7 +47,7 @@ def test_contains(): scene = arcade.Scene() assert "Walls" not in scene assert None not in scene - + walls_spriteList = arcade.SpriteList() scene.add_sprite_list("Walls", use_spatial_hash=True, sprite_list=walls_spriteList) assert "Walls" in scene diff --git a/tests/unit/scene/test_scene_remove_sprite_lists.py b/tests/unit/scene/test_scene_remove_sprite_lists.py index 2a8f2901a6..4dcd35571b 100644 --- a/tests/unit/scene/test_scene_remove_sprite_lists.py +++ b/tests/unit/scene/test_scene_remove_sprite_lists.py @@ -1,6 +1,7 @@ import arcade import pytest + def test_remove_sprite_list_by_index(): scene = arcade.Scene() scene.add_sprite_list("Player") @@ -10,6 +11,7 @@ def test_remove_sprite_list_by_index(): with pytest.raises(KeyError): scene["Player"] + def test_remove_sprite_list_by_name(): scene = arcade.Scene() scene.add_sprite_list("Walls") @@ -19,6 +21,7 @@ def test_remove_sprite_list_by_name(): with pytest.raises(KeyError): scene["Walls"] + def test_remove_sprite_list_by_object(): scene = arcade.Scene() scene.add_sprite_list("Coins") diff --git a/tests/unit/shape_list/test_buffered_drawing.py b/tests/unit/shape_list/test_buffered_drawing.py index 990ae670d8..715b95f258 100644 --- a/tests/unit/shape_list/test_buffered_drawing.py +++ b/tests/unit/shape_list/test_buffered_drawing.py @@ -23,7 +23,6 @@ @pytest.fixture def shape_list_instance() -> ShapeElementList: - shape_list = ShapeElementList() center_x = 0 @@ -34,11 +33,15 @@ def shape_list_instance() -> ShapeElementList: shape_list.append(shape) center_x += 40 - shape = create_ellipse_outline(center_x, center_y, width, height, arcade.color.RED, border_width=1) + shape = create_ellipse_outline( + center_x, center_y, width, height, arcade.color.RED, border_width=1 + ) shape_list.append(shape) center_x += 40 - shape = create_ellipse_outline(center_x, center_y, width, height, arcade.color.DARK_RED, border_width=1) + shape = create_ellipse_outline( + center_x, center_y, width, height, arcade.color.DARK_RED, border_width=1 + ) shape_list.append(shape) shape = create_line(0, 0, 80, 0, arcade.color.BLUE, line_width=1) @@ -54,24 +57,24 @@ def shape_list_instance() -> ShapeElementList: outside_color = arcade.color.AERO_BLUE inside_color = arcade.color.AFRICAN_VIOLET tilt_angle = 45 - shape = create_ellipse_filled_with_colors(center_x, center_y, - width, height, - outside_color, inside_color, - tilt_angle) + shape = create_ellipse_filled_with_colors( + center_x, center_y, width, height, outside_color, inside_color, tilt_angle + ) shape_list.append(shape) center_x = 0 center_y = -50 width = 20 height = 20 - shape = create_rectangle_filled(center_x, center_y, width, height, - arcade.color.WHITE) + shape = create_rectangle_filled(center_x, center_y, width, height, arcade.color.WHITE) shape_list.append(shape) - shape = create_rectangle_outline(center_x, center_y, width, height, - arcade.color.BLACK, border_width=1) + shape = create_rectangle_outline( + center_x, center_y, width, height, arcade.color.BLACK, border_width=1 + ) shape_list.append(shape) - shape = create_rectangle_outline(center_x, center_y, width, height, - arcade.color.AMERICAN_ROSE, border_width=1) + shape = create_rectangle_outline( + center_x, center_y, width, height, arcade.color.AMERICAN_ROSE, border_width=1 + ) shape_list.append(shape) color1 = (215, 214, 165) @@ -93,7 +96,6 @@ def shape_list_instance() -> ShapeElementList: def test_shape_copy_dunders_raise_notimplemented_error(window, shape_list_instance): - for shape in shape_list_instance: with pytest.raises(NotImplementedError): _ = copy.copy(shape) @@ -103,7 +105,6 @@ def test_shape_copy_dunders_raise_notimplemented_error(window, shape_list_instan # Temp fix for https://github.com/pythonarcade/arcade/issues/2074 def test_shapeelementlist_copy_dunders_raise_notimplemented_error(window, shape_list_instance): - with pytest.raises(NotImplementedError): _ = copy.copy(shape_list_instance) @@ -112,7 +113,6 @@ def test_shapeelementlist_copy_dunders_raise_notimplemented_error(window, shape_ def test_buffered_drawing(window, shape_list_instance): - shape_list_instance.center_x = 200 shape_list_instance.center_y = 200 diff --git a/tests/unit/shape_list/test_buffered_line_strip.py b/tests/unit/shape_list/test_buffered_line_strip.py index caa3caa4df..4b58c59699 100644 --- a/tests/unit/shape_list/test_buffered_line_strip.py +++ b/tests/unit/shape_list/test_buffered_line_strip.py @@ -6,10 +6,7 @@ def test_buffered_lines(window): window.background_color = arcade.color.WHITE window.clear() - point_list = ([0, 100], - [100, 100], - [100, 300], - [300, 300]) + point_list = ([0, 100], [100, 100], [100, 300], [300, 300]) line_strip = shape_list.create_line_strip(point_list, arcade.csscolor.BLACK, 10) line_strip.draw() diff --git a/tests/unit/sprite/test_copy_dunders.py b/tests/unit/sprite/test_copy_dunders.py index 02f6fbfd7e..6975b1e76e 100644 --- a/tests/unit/sprite/test_copy_dunders.py +++ b/tests/unit/sprite/test_copy_dunders.py @@ -12,7 +12,9 @@ def test_copy_dunders_raise_notimplementederror(): """ # Make sure BasicSprite raises NotImplementedError - texture = arcade.load_texture(":resources:images/animated_characters/female_person/femalePerson_idle.png") + texture = arcade.load_texture( + ":resources:images/animated_characters/female_person/femalePerson_idle.png" + ) basic_sprite = arcade.BasicSprite(texture) with pytest.raises(NotImplementedError): diff --git a/tests/unit/sprite/test_sprite.py b/tests/unit/sprite/test_sprite.py index b7d7bee261..2201a15629 100644 --- a/tests/unit/sprite/test_sprite.py +++ b/tests/unit/sprite/test_sprite.py @@ -1,13 +1,16 @@ """ Strictly unit tests for the sprite class. """ + import pytest as pytest import arcade from pyglet.math import Vec2 frame_counter = 0 -SPRITE_TEXTURE_FEMALE_PERSON_IDLE = arcade.load_texture(":resources:images/animated_characters/female_person/femalePerson_idle.png") +SPRITE_TEXTURE_FEMALE_PERSON_IDLE = arcade.load_texture( + ":resources:images/animated_characters/female_person/femalePerson_idle.png" +) SPRITE_TEXTURE_GOLD_COIN = arcade.load_texture(":resources:images/items/coinGold.png") @@ -69,9 +72,7 @@ def test_set_size(): sprite.size = 1 -@pytest.mark.parametrize('not_a_texture', [ - 1, "not_a_texture", (1, 2, 3) -]) +@pytest.mark.parametrize("not_a_texture", [1, "not_a_texture", (1, 2, 3)]) def test_sprite_texture_setter_raises_type_error_when_given_non_texture(not_a_texture): sprite = arcade.Sprite(SPRITE_TEXTURE_GOLD_COIN, scale=1.0) with pytest.raises(TypeError): @@ -125,6 +126,7 @@ def test_sprite_rgb_property_basics(): assert sprite.color.a == 15 assert sprite.alpha == 15 + def test_sprite_scale_constructor(window): sprite = arcade.BasicSprite(SPRITE_TEXTURE_GOLD_COIN, scale=2.0) assert sprite.scale == (2.0, 2.0) @@ -137,7 +139,7 @@ def test_sprite_scale_constructor(window): sprite = arcade.Sprite(SPRITE_TEXTURE_GOLD_COIN, scale=(1.0, 2.0, 10.0, 100.0)) assert sprite.scale == (1.0, 2.0) with pytest.raises(TypeError): - sprite = arcade.sprite(SPRITE_TEXTURE_GOLD_COIN, scale = test_sprite_scale_constructor) + sprite = arcade.sprite(SPRITE_TEXTURE_GOLD_COIN, scale=test_sprite_scale_constructor) sprite = arcade.Sprite(SPRITE_TEXTURE_GOLD_COIN, scale=1.0) assert isinstance(sprite.scale, tuple) @@ -258,6 +260,7 @@ def test_sprite_scale_resets_mismatched_xy_settings(window): assert sprite.width == 40 assert sprite.height == 40 + def test_sprite_scale_invalid(window): sprite = arcade.Sprite(SPRITE_TEXTURE_FEMALE_PERSON_IDLE) @@ -266,6 +269,7 @@ def test_sprite_scale_invalid(window): with pytest.raises(TypeError): sprite.scale = test_sprite_scale_invalid + # TODO: Possibly separate into a movement module def test_strafe(window): """Test if strafe moves the sprite in the correct direction.""" @@ -310,10 +314,7 @@ def sprite_64x64_at_position(x, y): # expected: # 1. sprite is 3.31 times further away from origin to upper right # 2. sprite is now 3.31 times larger - sprite_1 = sprite_64x64_at_position( - window_center_x + 50, - window_center_y - 50 - ) + sprite_1 = sprite_64x64_at_position(window_center_x + 50, window_center_y - 50) sprite_1.rescale_relative_to_point((0, 0), 3.31) assert sprite_1.scale == (3.31, 3.31) assert sprite_1.center_x == (window_center_x + 50) * 3.31 @@ -328,10 +329,7 @@ def sprite_64x64_at_position(x, y): # result: # 1. sprite distance doubled # 2. sprite scale doubled - sprite_2 = sprite_64x64_at_position( - window_center_x + 10, - window_center_y + 10 - ) + sprite_2 = sprite_64x64_at_position(window_center_x + 10, window_center_y + 10) sprite_2.scale = (2.0, 1.0) sprite_2.rescale_relative_to_point(window_center, 2.0) assert sprite_2.scale == (4.0, 2.0) @@ -347,10 +345,7 @@ def sprite_64x64_at_position(x, y): # result: # 1. sprite distance tripled # 2. sprite scale tripled - sprite_3 = sprite_64x64_at_position( - window_center_x - 10, - window_center_y - 10 - ) + sprite_3 = sprite_64x64_at_position(window_center_x - 10, window_center_y - 10) sprite_3.scale = (0.5, 1.5) sprite_3.rescale_relative_to_point(window_center, 3.0) assert sprite_3.scale == (1.5, 4.5) @@ -381,10 +376,7 @@ def sprite_64x64_at_position(x, y): # edge case: point != sprite center, factor == 1.0 # expected : no movement or size change occurs - sprite_6 = sprite_64x64_at_position( - window_center_x - 81, - window_center_y + 81 - ) + sprite_6 = sprite_64x64_at_position(window_center_x - 81, window_center_y + 81) sprite_6.rescale_relative_to_point((50, 40), 1.0) assert sprite_6.scale == (1.0, 1.0) assert sprite_6.center_x == window_center_x - 81 @@ -394,10 +386,7 @@ def sprite_64x64_at_position(x, y): # edge case: point != sprite center, factor == 1.0 # expected : no movement or size change occurs - sprite_7 = sprite_64x64_at_position( - window_center_x - 81, - window_center_y + 81 - ) + sprite_7 = sprite_64x64_at_position(window_center_x - 81, window_center_y + 81) sprite_7.rescale_relative_to_point((50, 40), 1.0) assert sprite_7.scale == (1.0, 1.0) assert sprite_7.center_x == window_center_x - 81 @@ -409,10 +398,7 @@ def sprite_64x64_at_position(x, y): # expected : # 1. sprite teleports to opposite side of point # 2. sprite has negative versions of scale data - sprite_8 = sprite_64x64_at_position( - window_center_x - 81, - window_center_y + 81 - ) + sprite_8 = sprite_64x64_at_position(window_center_x - 81, window_center_y + 81) sprite_8.rescale_relative_to_point(window_center, -1.0) assert sprite_8.scale == (-1.0, -1.0) assert sprite_8.center_x == window_center_x + 81 @@ -426,16 +412,10 @@ def test_rescale_relative_to_point_with_vec_quants(window): window_center_x, window_center_y = window_center def sprite_64x64_at_position(x, y): - return arcade.Sprite( - ":resources:images/items/gold_1.png", - center_x=x, center_y=y - ) + return arcade.Sprite(":resources:images/items/gold_1.png", center_x=x, center_y=y) # sprite with initial _scale[0] == _scale[1] works with identical scale - sprite_1 = sprite_64x64_at_position( - window_center_x + 50, - window_center_y - 50 - ) + sprite_1 = sprite_64x64_at_position(window_center_x + 50, window_center_y - 50) sprite_1.rescale_relative_to_point((0, 0), (3.31, 3.31)) assert sprite_1.scale == (3.31, 3.31) assert sprite_1.center_x == (window_center_x + 50) * 3.31 @@ -444,10 +424,7 @@ def sprite_64x64_at_position(x, y): assert sprite_1.height == 64 * 3.31 # sprite with x scale > y scale works correctly - sprite_2 = sprite_64x64_at_position( - window_center_x + 10, - window_center_y + 10 - ) + sprite_2 = sprite_64x64_at_position(window_center_x + 10, window_center_y + 10) sprite_2.scale = (2.0, 1.0) sprite_2.rescale_relative_to_point(window_center, (2.0, 2.0)) assert sprite_2.scale == (4.0, 2.0) @@ -457,10 +434,7 @@ def sprite_64x64_at_position(x, y): assert sprite_2.height == 128 # sprite with y scale > x scale works correctly - sprite_3 = sprite_64x64_at_position( - window_center_x - 10, - window_center_y - 10 - ) + sprite_3 = sprite_64x64_at_position(window_center_x - 10, window_center_y - 10) sprite_3.scale = (0.5, 1.5) sprite_3.rescale_relative_to_point(window_center, (3.0, 3.0)) assert sprite_3.scale == (1.5, 4.5) @@ -481,10 +455,7 @@ def sprite_64x64_at_position(x, y): # edge case: point != sprite center, factor == 1.0 # expected : no movement or size change occurs - sprite_5 = sprite_64x64_at_position( - window_center_x - 81, - window_center_y + 81 - ) + sprite_5 = sprite_64x64_at_position(window_center_x - 81, window_center_y + 81) sprite_5.rescale_relative_to_point((50, 40), (1.0, 1.0)) assert sprite_5.scale == (1.0, 1.0) assert sprite_5.center_x == window_center_x - 81 @@ -504,10 +475,7 @@ def sprite_64x64_at_position(x, y): # edge case: point != sprite center, factor == 1.0 # expected : no movement or size change occurs - sprite_7 = sprite_64x64_at_position( - window_center_x - 81, - window_center_y + 81 - ) + sprite_7 = sprite_64x64_at_position(window_center_x - 81, window_center_y + 81) sprite_7.rescale_relative_to_point((50, 40), (1.0, 1.0)) assert sprite_7.scale == (1.0, 1.0) assert sprite_7.center_x == window_center_x - 81 diff --git a/tests/unit/sprite/test_sprite_animated_walking.py b/tests/unit/sprite/test_sprite_animated_walking.py index fb2bfee07f..46cf3ca92c 100644 --- a/tests/unit/sprite/test_sprite_animated_walking.py +++ b/tests/unit/sprite/test_sprite_animated_walking.py @@ -19,19 +19,34 @@ def test_sprite_animated_old(window: arcade.Window): player.scale = 1.0 player.stand_right_textures = [] player.stand_right_textures.append( - arcade.load_texture(":resources:images/animated_characters/female_person/femalePerson_idle.png")) + arcade.load_texture( + ":resources:images/animated_characters/female_person/femalePerson_idle.png" + ) + ) player.stand_left_textures = [tex.flip_left_right() for tex in player.stand_right_textures] player.walk_right_textures = [] player.walk_right_textures.append( - arcade.load_texture(":resources:images/animated_characters/female_person/femalePerson_walk0.png")) + arcade.load_texture( + ":resources:images/animated_characters/female_person/femalePerson_walk0.png" + ) + ) player.walk_right_textures.append( - arcade.load_texture(":resources:images/animated_characters/female_person/femalePerson_walk1.png")) + arcade.load_texture( + ":resources:images/animated_characters/female_person/femalePerson_walk1.png" + ) + ) player.walk_right_textures.append( - arcade.load_texture(":resources:images/animated_characters/female_person/femalePerson_walk2.png")) + arcade.load_texture( + ":resources:images/animated_characters/female_person/femalePerson_walk2.png" + ) + ) player.walk_right_textures.append( - arcade.load_texture(":resources:images/animated_characters/female_person/femalePerson_walk3.png")) + arcade.load_texture( + ":resources:images/animated_characters/female_person/femalePerson_walk3.png" + ) + ) player.walk_left_textures = [tex.flip_left_right() for tex in player.walk_right_textures] diff --git a/tests/unit/sprite/test_sprite_collision.py b/tests/unit/sprite/test_sprite_collision.py index 33d6803e28..dce9fd284b 100644 --- a/tests/unit/sprite/test_sprite_collision.py +++ b/tests/unit/sprite/test_sprite_collision.py @@ -4,12 +4,11 @@ def test_sprites_at_point(): - coin_list = arcade.SpriteList() sprite = arcade.SpriteSolidColor(50, 50, color=arcade.csscolor.RED) # an adjacent sprite with the same level horizontal bottom edge sprite2 = arcade.SpriteSolidColor(50, 50, center_x=50, center_y=0, color=arcade.csscolor.RED) - + coin_list.append(sprite) coin_list.append(sprite2) @@ -97,7 +96,6 @@ def test_sprite_collides_with_sprite(): sprite_two.center_x = 10 assert sprite_one.collides_with_sprite(sprite_two) is False - # Borders, opposite side sprite_two.center_x = -10 assert sprite_one.collides_with_sprite(sprite_two) is False diff --git a/tests/unit/sprite/test_sprite_colored.py b/tests/unit/sprite/test_sprite_colored.py index 1cad4df8a9..0470683118 100644 --- a/tests/unit/sprite/test_sprite_colored.py +++ b/tests/unit/sprite/test_sprite_colored.py @@ -1,6 +1,7 @@ """ SpriteCircle and SpriteSolidColor """ + import arcade diff --git a/tests/unit/sprite/test_sprite_hitbox.py b/tests/unit/sprite/test_sprite_hitbox.py index 5a44ba8b80..13bbf1f407 100644 --- a/tests/unit/sprite/test_sprite_hitbox.py +++ b/tests/unit/sprite/test_sprite_hitbox.py @@ -4,9 +4,7 @@ def test_1(): # setup - my_sprite = arcade.Sprite( - arcade.make_soft_square_texture(20, arcade.color.RED, 0, 255) - ) + my_sprite = arcade.Sprite(arcade.make_soft_square_texture(20, arcade.color.RED, 0, 255)) hit_box = arcade.hitbox.HitBox(((-10, -10), (-10, 10), (10, 10), (10, -10))) my_sprite.hit_box = hit_box my_sprite.scale = 1.0 diff --git a/tests/unit/spritelist/test_spatial_hash.py b/tests/unit/spritelist/test_spatial_hash.py index 4e02ea448a..91a316f24d 100644 --- a/tests/unit/spritelist/test_spatial_hash.py +++ b/tests/unit/spritelist/test_spatial_hash.py @@ -10,14 +10,17 @@ def test_create(): assert sh.buckets_for_sprite == {} assert sh.count == 0 + def test_incorrect_str_input(): with pytest.raises(TypeError): sh = SpatialHash(cell_size="10") - + + def test_incorrect_inf_input(): with pytest.raises(TypeError): sh = SpatialHash(cell_size=float("inf")) + def test_reset(): sh = SpatialHash(cell_size=10) sh.add(arcade.SpriteSolidColor(10, 10, color=arcade.color.RED)) @@ -85,16 +88,12 @@ def get_nearby_sprites(): sh.add(sprite_1) sh.add(sprite_2) - nearby_sprites = sh.get_sprites_near_sprite( - arcade.SpriteSolidColor(10, 10, center_x=-5) - ) + nearby_sprites = sh.get_sprites_near_sprite(arcade.SpriteSolidColor(10, 10, center_x=-5)) assert isinstance(nearby_sprites, set) assert len(nearby_sprites) == 1 assert nearby_sprites[0] == sprite_1 - nearby_sprites = sh.get_sprites_near_sprite( - arcade.SpriteSolidColor(10, 10, center_x=0) - ) + nearby_sprites = sh.get_sprites_near_sprite(arcade.SpriteSolidColor(10, 10, center_x=0)) assert isinstance(nearby_sprites, set) assert len(nearby_sprites) == 2 assert nearby_sprites == set([sprite_1, sprite_2]) diff --git a/tests/unit/spritelist/test_spritelist.py b/tests/unit/spritelist/test_spritelist.py index be20383c37..53187f2ee5 100644 --- a/tests/unit/spritelist/test_spritelist.py +++ b/tests/unit/spritelist/test_spritelist.py @@ -47,10 +47,10 @@ def test_copy_dunder_stubs_raise_notimplementederror(): import copy with pytest.raises(NotImplementedError): - _ = copy.copy(spritelist) + _ = copy.copy(spritelist) with pytest.raises(NotImplementedError): - _ = copy.deepcopy(spritelist) + _ = copy.deepcopy(spritelist) def test_it_can_extend_a_spritelist_from_a_list(): @@ -93,7 +93,7 @@ def sprite_grid_generator(cols: int, rows: int, cell_size: float): height=32, color=arcade.color.RED, center_x=col * cell_size, - center_y=row * cell_size + center_y=row * cell_size, ) sprite_list.extend(sprite_grid_generator(3, 5, 1.0)) @@ -183,7 +183,9 @@ def test_can_shuffle(ctx): spritelist.draw() # Ensure the index buffer is referring to the correct slots # Raw buffer from OpenGL - index_data = struct.unpack(f"{num_sprites}i", spritelist._sprite_index_buf.read()[:num_sprites * 4]) + index_data = struct.unpack( + f"{num_sprites}i", spritelist._sprite_index_buf.read()[: num_sprites * 4] + ) for i, sprite in enumerate(spritelist): # Check if slots are updated slot = spritelist.sprite_slot[sprite] @@ -219,7 +221,7 @@ def test_sort(ctx): assert spritelist._sprite_index_data[0:3] == array("f", [0, 1, 2]) -@pytest.mark.parametrize('capacity', (128, 512, 1024)) +@pytest.mark.parametrize("capacity", (128, 512, 1024)) def test_clear(ctx, capacity): sp = arcade.SpriteList(capacity=capacity) sp.clear(capacity=None) @@ -259,7 +261,7 @@ def test_color(): # Alpha sp.alpha = 172 assert sp.alpha == 172 - assert sp.alpha_normalized == pytest.approx(172/255, rel=0.01) + assert sp.alpha_normalized == pytest.approx(172 / 255, rel=0.01) # Setting float RGBA works sp.color_normalized = 0.1, 0.2, 0.3, 0.4 @@ -295,7 +297,7 @@ def test_swap(window): sprites = [ arcade.SpriteSolidColor(10, 10, color=arcade.color.RED), - arcade.SpriteSolidColor(10, 10, color=arcade.color.GREEN) + arcade.SpriteSolidColor(10, 10, color=arcade.color.GREEN), ] sl = arcade.SpriteList() sl.extend(sprites) diff --git a/tests/unit/spritelist/test_spritelist_buffers.py b/tests/unit/spritelist/test_spritelist_buffers.py index 10648fe40c..5b8aa89a3c 100644 --- a/tests/unit/spritelist/test_spritelist_buffers.py +++ b/tests/unit/spritelist/test_spritelist_buffers.py @@ -2,6 +2,7 @@ Ensure internal buffers are sized correctly. Incorrectly sized buffers can lead to segfaults. """ + import struct import arcade @@ -100,12 +101,12 @@ def test_buffer_sizes(ctx: arcade.ArcadeContext): # Test the contents of the arrays and buffers. # Prepare expected data - expected_pos_data = struct.pack('12f', *[v for p in positions for v in p]) - expected_color_data = struct.pack('16B', *[v for c in colors for v in c]) - expected_size_data = struct.pack('8f', *[v for s in sizes for v in s]) - expected_angle_data = struct.pack('4f', *angles) + expected_pos_data = struct.pack("12f", *[v for p in positions for v in p]) + expected_color_data = struct.pack("16B", *[v for c in colors for v in c]) + expected_size_data = struct.pack("8f", *[v for s in sizes for v in s]) + expected_angle_data = struct.pack("4f", *angles) expected_texture_data = struct.pack( - '4f', + "4f", *[ctx.default_atlas.get_texture_id(sprite.texture) for sprite in sprites], ) @@ -124,4 +125,4 @@ def test_buffer_sizes(ctx: arcade.ArcadeContext): assert sp._sprite_texture_data.tobytes() == expected_texture_data # Index buffer - assert sp._sprite_index_buf.read() == struct.pack('4i', 0, 1, 2, 3) + assert sp._sprite_index_buf.read() == struct.pack("4i", 0, 1, 2, 3) diff --git a/tests/unit/spritelist/test_spritelist_draw.py b/tests/unit/spritelist/test_spritelist_draw.py index c19cbcd191..eea6a3a5c8 100644 --- a/tests/unit/spritelist/test_spritelist_draw.py +++ b/tests/unit/spritelist/test_spritelist_draw.py @@ -6,9 +6,11 @@ def test_visible(window, monkeypatch): """Ensure invisible spritelists are not drawn""" sp = arcade.SpriteList() + # Monkeypatch Geometry.render to raise an error if called def mock_draw(*args, **kwargs): raise AssertionError("Should not be called") + monkeypatch.setattr(Geometry, "render", mock_draw) # Empty spritelist should not be rendered diff --git a/tests/unit/spritelist/test_spritelist_lazy.py b/tests/unit/spritelist/test_spritelist_lazy.py index 4d4781e8e9..014600d186 100644 --- a/tests/unit/spritelist/test_spritelist_lazy.py +++ b/tests/unit/spritelist/test_spritelist_lazy.py @@ -14,9 +14,7 @@ def test_create_lazy_equals_true(): # Make sure CPU-only behavior still works correctly for x in range(100): - spritelist.append( - arcade.Sprite(":resources:images/items/coinGold.png", center_x=x * 64) - ) + spritelist.append(arcade.Sprite(":resources:images/items/coinGold.png", center_x=x * 64)) assert len(spritelist) == 100 assert spritelist.spatial_hash is not None assert spritelist._initialized is False @@ -37,7 +35,7 @@ def test_manual_initialization_after_lazy_equals_true(window): spritelist.remove(sprite) # Make sure initialization still worked correctly. - spritelist.initialize() + spritelist.initialize() assert spritelist._initialized assert spritelist._sprite_pos_buf assert spritelist._geometry diff --git a/tests/unit/spritelist/test_spritesequence.py b/tests/unit/spritelist/test_spritesequence.py index 454ba7a7cb..2212c241e0 100644 --- a/tests/unit/spritelist/test_spritesequence.py +++ b/tests/unit/spritelist/test_spritesequence.py @@ -1,8 +1,10 @@ import arcade + class _CustomSpriteSolidColor(arcade.SpriteSolidColor): pass + def test_collective_draw(window: arcade.Window) -> None: sprite_list1: arcade.SpriteList[arcade.Sprite] = arcade.SpriteList() sprite_list1.append(arcade.SpriteSolidColor(16, 16, color=(255, 0, 0, 1))) @@ -11,7 +13,7 @@ def test_collective_draw(window: arcade.Window) -> None: sprite_list2.append(_CustomSpriteSolidColor(16, 16, color=(255, 0, 0, 1))) # It really is a SpriteList with a good type; this would not typecheck otherwise - custom_sprite: _CustomSpriteSolidColor = sprite_list2[0] # assert_type + custom_sprite: _CustomSpriteSolidColor = sprite_list2[0] # assert_type # Assert that SpriteSequence is truly covariant: # It can be used as a common type for different types of SpriteLists. @@ -19,7 +21,7 @@ def test_collective_draw(window: arcade.Window) -> None: sprite_list1, sprite_list2, ] - sprite: arcade.Sprite = scene[0][0] # assert_type + sprite: arcade.Sprite = scene[0][0] # assert_type # We can collectively draw all the SpriteSequences. for sprite_list in scene: diff --git a/tests/unit/test_arcade.py b/tests/unit/test_arcade.py index 56e05ac4a0..243afe5cad 100644 --- a/tests/unit/test_arcade.py +++ b/tests/unit/test_arcade.py @@ -12,8 +12,9 @@ def test_import(): """Compare arcade.__all__ to the actual module contents""" import arcade - global_names = set(k for k in globals() if not k.startswith('_')) - arcade_names = set(k for k in arcade.__dict__ if not k.startswith('_')) + + global_names = set(k for k in globals() if not k.startswith("_")) + arcade_names = set(k for k in arcade.__dict__ if not k.startswith("_")) # Get the common members common = global_names.intersection(arcade_names) @@ -23,7 +24,7 @@ def test_import(): attr_type = type(attr) if attr_type in builtin_types: remaining.remove(name) - elif not attr.__module__.startswith('arcade.'): + elif not attr.__module__.startswith("arcade."): remaining.remove(name) assert len(remaining) == 0 @@ -31,5 +32,5 @@ def test_import(): def test_logging(): arcade.configure_logging(logging.WARNING) - logger = logging.getLogger('arcade') + logger = logging.getLogger("arcade") assert logger.level == logging.WARNING diff --git a/tests/unit/test_clock.py b/tests/unit/test_clock.py index 7b6f75c71a..abed4d9a1e 100644 --- a/tests/unit/test_clock.py +++ b/tests/unit/test_clock.py @@ -2,22 +2,23 @@ from arcade.clock import Clock, FixedClock, GLOBAL_CLOCK, GLOBAL_FIXED_CLOCK + def test_clock(): # GLOBAL_CLOCK.set_tick_speed(1.0) time = GLOBAL_CLOCK.time ticks = GLOBAL_CLOCK.ticks - GLOBAL_CLOCK.tick(1.0/60.0) - assert GLOBAL_CLOCK.time == time + 1.0/60.0 + GLOBAL_CLOCK.tick(1.0 / 60.0) + assert GLOBAL_CLOCK.time == time + 1.0 / 60.0 assert GLOBAL_CLOCK.ticks == ticks + 1 - assert GLOBAL_CLOCK.delta_time == 1.0/60.0 + assert GLOBAL_CLOCK.delta_time == 1.0 / 60.0 - GLOBAL_CLOCK.set_max_deltatime(1.0/100.0) + GLOBAL_CLOCK.set_max_deltatime(1.0 / 100.0) GLOBAL_CLOCK.tick(1.0 / 60.0) - assert GLOBAL_CLOCK.time == time + 1.0/60.0 + 1.0 / 100.0 + assert GLOBAL_CLOCK.time == time + 1.0 / 60.0 + 1.0 / 100.0 assert GLOBAL_CLOCK.ticks == ticks + 2 - assert GLOBAL_CLOCK.delta_time == 1.0/100.0 + assert GLOBAL_CLOCK.delta_time == 1.0 / 100.0 GLOBAL_CLOCK.set_max_deltatime() with pytest.raises(ValueError): - GLOBAL_FIXED_CLOCK.tick(1.0) \ No newline at end of file + GLOBAL_FIXED_CLOCK.tick(1.0) diff --git a/tests/unit/test_example_docstrings.py b/tests/unit/test_example_docstrings.py index 9bda1cd8f2..f70bb76c1e 100644 --- a/tests/unit/test_example_docstrings.py +++ b/tests/unit/test_example_docstrings.py @@ -62,7 +62,6 @@ def check_submodules(parent_module_absolute_name: str) -> None: # Check all modules nested immediately inside it on the file system for finder, child_module_name, is_pkg in pkgutil.iter_modules(parent_module_file_path): - child_module_file_path = Path(finder.path) / f"{child_module_name}.py" child_module_absolute_name = f"{parent_module_absolute_name}.{child_module_name}" @@ -80,7 +79,6 @@ def test_docstrings(): # For each immediate child folder module in arcade.examples, # check the immediate child python files for correct docstrings. for folder_submodule_path in Path(arcade.examples.__path__[0]).iterdir(): - # Skip file modules we already covered above outside the loop if not folder_submodule_path.is_dir(): continue diff --git a/tests/unit/test_isometric.py b/tests/unit/test_isometric.py index 1df2d1ec4b..07cdc3b775 100644 --- a/tests/unit/test_isometric.py +++ b/tests/unit/test_isometric.py @@ -13,9 +13,7 @@ def test_isometric_grid_to_screen(window): height = 10 tile_width = 64 tile_height = 64 - x, y = isometric_grid_to_screen(tile_x, tile_y, - width, height, - tile_width, tile_height) + x, y = isometric_grid_to_screen(tile_x, tile_y, width, height, tile_width, tile_height) assert x == 320 assert y == 608 @@ -25,9 +23,7 @@ def test_isometric_grid_to_screen(window): height = 10 tile_width = 64 tile_height = 64 - x, y = isometric_grid_to_screen(tile_x, tile_y, - width, height, - tile_width, tile_height) + x, y = isometric_grid_to_screen(tile_x, tile_y, width, height, tile_width, tile_height) assert x == 320 assert y == 480 @@ -39,20 +35,19 @@ def test_screen_to_isometric_grid(window): height = 10 tile_width = 64 tile_height = 64 - x, y = screen_to_isometric_grid(screen_x, screen_y, - width, height, - tile_width, tile_height) + x, y = screen_to_isometric_grid(screen_x, screen_y, width, height, tile_width, tile_height) print(x, y) assert x == 4 assert y == 14 + def test_create_isometric_grid_lines(window): width = 10 height = 10 tile_width = 64 tile_height = 64 - lines = create_isometric_grid_lines(width, height, - tile_width, tile_height, - arcade.color.BLACK, 2) + lines = create_isometric_grid_lines( + width, height, tile_width, tile_height, arcade.color.BLACK, 2 + ) assert lines diff --git a/tests/unit/test_key.py b/tests/unit/test_key.py index 2712eddf4b..b039c5cdb4 100644 --- a/tests/unit/test_key.py +++ b/tests/unit/test_key.py @@ -1,8 +1,5 @@ - def test_key(): from arcade import key - names = [ - k for k in key.__dict__.keys() - if not k.startswith("__") and k.isupper() - ] + + names = [k for k in key.__dict__.keys() if not k.startswith("__") and k.isupper()] assert 205 == len(names) diff --git a/tests/unit/test_screenshot.py b/tests/unit/test_screenshot.py index e15f44d6d6..b210eb29a0 100644 --- a/tests/unit/test_screenshot.py +++ b/tests/unit/test_screenshot.py @@ -14,7 +14,7 @@ def test_get_image(window): """Get image from active framebuffer.""" window.clear(color=arcade.color.WHITE) image = arcade.get_image() - assert image.tobytes()[0:16] == b'\xff' * 16 + assert image.tobytes()[0:16] == b"\xff" * 16 image = arcade.get_image(components=3) - assert image.tobytes()[0:16] == b'\xff' * 16 + assert image.tobytes()[0:16] == b"\xff" * 16 diff --git a/tests/unit/test_shadertoy.py b/tests/unit/test_shadertoy.py index 827bccfdb8..1813e890ce 100644 --- a/tests/unit/test_shadertoy.py +++ b/tests/unit/test_shadertoy.py @@ -2,26 +2,26 @@ from arcade.experimental import Shadertoy, ShadertoyBuffer from arcade.gl import Program, Texture2D + def glsl(inner: str): - return ( - "void mainImage(out vec4 fragColor, in vec2 fragCoord)\n" - "{\n" - f"{inner}\n" - "}\n" - ) + return f"void mainImage(out vec4 fragColor, in vec2 fragCoord)\n{{\n{inner}\n}}\n" def test_create_from_file(ctx): - st = Shadertoy.create_from_file((100, 200), ":resources:shaders/shadertoy/crt_monitor_filter.glsl") + st = Shadertoy.create_from_file( + (100, 200), ":resources:shaders/shadertoy/crt_monitor_filter.glsl" + ) check_internals(st) with pytest.raises(FileNotFoundError): st = Shadertoy.create_from_file((100, 200), "something.glsl") + def test_create(ctx): st = Shadertoy((120, 130), glsl("fragColor = vec4(1.0, 1.0, 1.0, 1.0);")) check_internals(st) + def test_buffers(ctx): st = Shadertoy((120, 130), glsl("fragColor = vec4(1.0, 1.0, 1.0, 1.0);")) buffer_a = st.create_buffer(glsl("fragColor = vec4(1.0, 0.0, 0.0, 1.0);")) @@ -50,6 +50,7 @@ def test_buffers(ctx): assert st.buffer_c == buffer_c assert st.buffer_d == buffer_d + def test_getters_setters(ctx): st = Shadertoy((120, 130), glsl("fragColor = vec4(1.0, 1.0, 1.0, 1.0);")) assert st.size == (120, 130) @@ -83,10 +84,18 @@ def test_getters_setters(ctx): st.channel_2 = tx3 st.channel_3 = tx4 assert st._channel_resolution == [ - 10, 11, 1, - 12, 13, 1, - 14, 15, 1, - 16, 17, 1, + 10, + 11, + 1, + 12, + 13, + 1, + 14, + 15, + 1, + 16, + 17, + 1, ] diff --git a/tests/unit/test_utils.py b/tests/unit/test_utils.py index 9cd77a1d6c..6474fdd7f5 100644 --- a/tests/unit/test_utils.py +++ b/tests/unit/test_utils.py @@ -4,13 +4,13 @@ Can run these tests individually with: python -m pytest tests/unit/test_utils.py """ + from typing import Callable, Any from arcade import utils -class _Dummy: - ... +class _Dummy: ... def fn_returns_expect_for_nonstr_iterables(fn: Callable[[Any], bool], expect: bool): @@ -27,7 +27,7 @@ def fn_returns_expect_for_nonstr_iterables(fn: Callable[[Any], bool], expect: bo def fn_returns_expect_for_noniterables(fn: Callable[[Any], bool], expect: bool): assert fn(1) == expect # Numbers - assert fn(complex(1,2)) == expect # Numbers part 2: complex is not iterable like pyglet vecs + assert fn(complex(1, 2)) == expect # Numbers part 2: complex is not iterable like pyglet vecs assert fn(type) == expect # types assert fn(_Dummy()) == expect # Instances assert fn(print) == expect # Functions diff --git a/tests/unit/test_version.py b/tests/unit/test_version.py index 01f05ae703..617ce28040 100644 --- a/tests/unit/test_version.py +++ b/tests/unit/test_version.py @@ -3,42 +3,36 @@ from unittest import mock import pytest -from arcade.version import ( - _parse_python_friendly_version, - _parse_py_version_from_file -) +from arcade.version import _parse_python_friendly_version, _parse_py_version_from_file -@pytest.mark.parametrize("value, expected", [ - ("3.0.0.dev1", "3.0.0.dev1"), - ("3.0.0", "3.0.0"), - # Edge cases - ("11.22.333.dev4444", "11.22.333.dev4444"), - ("11.22.333", "11.22.333"), - ("111.2222.3333rc0", "111.2222.3333rc0") -]) +@pytest.mark.parametrize( + "value, expected", + [ + ("3.0.0.dev1", "3.0.0.dev1"), + ("3.0.0", "3.0.0"), + # Edge cases + ("11.22.333.dev4444", "11.22.333.dev4444"), + ("11.22.333", "11.22.333"), + ("111.2222.3333rc0", "111.2222.3333rc0"), + ], +) class TestParsingWellFormedData: - def test_parse_python_friendly_version( - self, value, expected - ): + def test_parse_python_friendly_version(self, value, expected): assert _parse_python_friendly_version(value) == expected - def test_parse_py_version_from_file( - self, value, expected - ): - + def test_parse_py_version_from_file(self, value, expected): with tempfile.NamedTemporaryFile("w", delete=False) as f: f.write(value) f.close() - assert _parse_py_version_from_file( - f.name - ) == expected + assert _parse_py_version_from_file(f.name) == expected @pytest.mark.parametrize( - "bad_value", ( - '', + "bad_value", + ( + "", "This string is not a version number at all!" # Malformed version numbers "3", @@ -56,21 +50,15 @@ def test_parse_py_version_from_file( "3.1.0.A", "3.1.0-dev.A", # Can't be both a release candidate and a dev preview - "3.1.0.dev4rc1" - ) + "3.1.0.dev4rc1", + ), ) def test_parse_python_friendly_version_raises_value_errors(bad_value): with pytest.raises(ValueError): _parse_python_friendly_version(bad_value) -@pytest.mark.parametrize('bad_type', ( - None, - 0xBAD, - 0.1234, - (3, 1, 0), - ('3', '1' '0') -)) +@pytest.mark.parametrize("bad_type", (None, 0xBAD, 0.1234, (3, 1, 0), ("3", "10"))) def test_parse_python_friendly_version_raises_typeerror_on_bad_values(bad_type): with pytest.raises(TypeError): _parse_python_friendly_version(bad_type) # type: ignore # Type mistmatch is the point @@ -78,6 +66,4 @@ def test_parse_python_friendly_version_raises_typeerror_on_bad_values(bad_type): def test_parse_py_version_from_file_returns_zeroes_on_errors(): fake_stderr = mock.MagicMock(sys.stderr) - assert _parse_py_version_from_file( - "FILEDOESNOTEXIST", write_errors_to=fake_stderr - ) == "0.0.0" + assert _parse_py_version_from_file("FILEDOESNOTEXIST", write_errors_to=fake_stderr) == "0.0.0" diff --git a/tests/unit/text/test_text.py b/tests/unit/text/test_text.py index d7b0692e01..993fe75a94 100644 --- a/tests/unit/text/test_text.py +++ b/tests/unit/text/test_text.py @@ -23,47 +23,95 @@ def test_text(window): arcade.draw_text("Test Text", current_x, current_y, arcade.color.BLACK, 12) current_y -= LINE_HEIGHT - arcade.draw_text("Test Text Anchor Left", SCREEN_WIDTH // 2, current_y, - arcade.color.BLACK, 12, anchor_x="left") + arcade.draw_text( + "Test Text Anchor Left", + SCREEN_WIDTH // 2, + current_y, + arcade.color.BLACK, + 12, + anchor_x="left", + ) arcade.draw_point(SCREEN_WIDTH // 2, current_y, arcade.color.RED, 5) current_y -= LINE_HEIGHT - arcade.draw_text("Test Text Anchor Center", SCREEN_WIDTH // 2, current_y, - arcade.color.BLACK, 12, anchor_x="center") + arcade.draw_text( + "Test Text Anchor Center", + SCREEN_WIDTH // 2, + current_y, + arcade.color.BLACK, + 12, + anchor_x="center", + ) arcade.draw_point(SCREEN_WIDTH // 2, current_y, arcade.color.RED, 5) current_y -= LINE_HEIGHT - arcade.draw_text("Test Text Anchor Right", SCREEN_WIDTH // 2, current_y, - arcade.color.BLACK, 12, anchor_x="right") + arcade.draw_text( + "Test Text Anchor Right", + SCREEN_WIDTH // 2, + current_y, + arcade.color.BLACK, + 12, + anchor_x="right", + ) arcade.draw_point(SCREEN_WIDTH // 2, current_y, arcade.color.RED, 5) current_y -= LINE_HEIGHT - arcade.draw_text("Test Text Anchor Top", SCREEN_WIDTH // 2, current_y, - arcade.color.BLACK, 12, anchor_y="top") + arcade.draw_text( + "Test Text Anchor Top", SCREEN_WIDTH // 2, current_y, arcade.color.BLACK, 12, anchor_y="top" + ) arcade.draw_point(SCREEN_WIDTH // 2, current_y, arcade.color.RED, 5) current_y -= LINE_HEIGHT - arcade.draw_text("Test Text Anchor Center", SCREEN_WIDTH // 2, current_y, - arcade.color.BLACK, 12, anchor_y="center") + arcade.draw_text( + "Test Text Anchor Center", + SCREEN_WIDTH // 2, + current_y, + arcade.color.BLACK, + 12, + anchor_y="center", + ) arcade.draw_point(SCREEN_WIDTH // 2, current_y, arcade.color.RED, 5) current_y -= LINE_HEIGHT - arcade.draw_text("Test Text Anchor Bottom", SCREEN_WIDTH // 2, current_y, - arcade.color.BLACK, 12, anchor_y="bottom") + arcade.draw_text( + "Test Text Anchor Bottom", + SCREEN_WIDTH // 2, + current_y, + arcade.color.BLACK, + 12, + anchor_y="bottom", + ) arcade.draw_point(SCREEN_WIDTH // 2, current_y, arcade.color.RED, 5) field_width = SCREEN_WIDTH current_y -= LINE_HEIGHT - arcade.draw_text(f"Test Text Field Width {field_width}", current_x, current_y, - arcade.color.BLACK, 12, font_name="arial", width=field_width) - - current_y -= LINE_HEIGHT - arcade.draw_text(f"Centered Test Text Field Width {field_width}", current_x, current_y, - arcade.color.BLACK, 12, font_name="arial", width=field_width, align="center") + arcade.draw_text( + f"Test Text Field Width {field_width}", + current_x, + current_y, + arcade.color.BLACK, + 12, + font_name="arial", + width=field_width, + ) + + current_y -= LINE_HEIGHT + arcade.draw_text( + f"Centered Test Text Field Width {field_width}", + current_x, + current_y, + arcade.color.BLACK, + 12, + font_name="arial", + width=field_width, + align="center", + ) current_y -= LINE_HEIGHT font_name = ("comic", "arial") - arcade.draw_text("Different font", current_x, current_y, arcade.color.BLACK, 12, font_name=font_name) + arcade.draw_text( + "Different font", current_x, current_y, arcade.color.BLACK, 12, font_name=font_name + ) current_y -= LINE_HEIGHT @@ -104,43 +152,89 @@ def new_text(*args, **kwargs) -> None: new_text("Test Text", current_x, current_y, arcade.color.BLACK, 12) current_y -= LINE_HEIGHT - new_text("Test Text Anchor Left", SCREEN_WIDTH // 2, current_y, - arcade.color.BLACK, 12, anchor_x="left") + new_text( + "Test Text Anchor Left", + SCREEN_WIDTH // 2, + current_y, + arcade.color.BLACK, + 12, + anchor_x="left", + ) arcade.draw_point(SCREEN_WIDTH // 2, current_y, arcade.color.RED, 5) current_y -= LINE_HEIGHT - new_text("Test Text Anchor Center", SCREEN_WIDTH // 2, current_y, - arcade.color.BLACK, 12, anchor_x="center") + new_text( + "Test Text Anchor Center", + SCREEN_WIDTH // 2, + current_y, + arcade.color.BLACK, + 12, + anchor_x="center", + ) arcade.draw_point(SCREEN_WIDTH // 2, current_y, arcade.color.RED, 5) current_y -= LINE_HEIGHT - new_text("Test Text Anchor Right", SCREEN_WIDTH // 2, current_y, - arcade.color.BLACK, 12, anchor_x="right") + new_text( + "Test Text Anchor Right", + SCREEN_WIDTH // 2, + current_y, + arcade.color.BLACK, + 12, + anchor_x="right", + ) arcade.draw_point(SCREEN_WIDTH // 2, current_y, arcade.color.RED, 5) current_y -= LINE_HEIGHT - new_text("Test Text Anchor Top", SCREEN_WIDTH // 2, current_y, - arcade.color.BLACK, 12, anchor_y="top") + new_text( + "Test Text Anchor Top", SCREEN_WIDTH // 2, current_y, arcade.color.BLACK, 12, anchor_y="top" + ) arcade.draw_point(SCREEN_WIDTH // 2, current_y, arcade.color.RED, 5) current_y -= LINE_HEIGHT - new_text("Test Text Anchor Center", SCREEN_WIDTH // 2, current_y, - arcade.color.BLACK, 12, anchor_y="center") + new_text( + "Test Text Anchor Center", + SCREEN_WIDTH // 2, + current_y, + arcade.color.BLACK, + 12, + anchor_y="center", + ) arcade.draw_point(SCREEN_WIDTH // 2, current_y, arcade.color.RED, 5) current_y -= LINE_HEIGHT - new_text("Test Text Anchor Bottom", SCREEN_WIDTH // 2, current_y, - arcade.color.BLACK, 12, anchor_y="bottom") + new_text( + "Test Text Anchor Bottom", + SCREEN_WIDTH // 2, + current_y, + arcade.color.BLACK, + 12, + anchor_y="bottom", + ) arcade.draw_point(SCREEN_WIDTH // 2, current_y, arcade.color.RED, 5) field_width = SCREEN_WIDTH current_y -= LINE_HEIGHT - new_text(f"Test Text Field Width {field_width}", current_x, current_y, - arcade.color.BLACK, 12, font_name="arial", width=field_width) - - current_y -= LINE_HEIGHT - new_text(f"Centered Test Text Field Width {field_width}", current_x, current_y, - arcade.color.BLACK, 12, font_name="arial", width=field_width, align="center") + new_text( + f"Test Text Field Width {field_width}", + current_x, + current_y, + arcade.color.BLACK, + 12, + font_name="arial", + width=field_width, + ) + + current_y -= LINE_HEIGHT + new_text( + f"Centered Test Text Field Width {field_width}", + current_x, + current_y, + arcade.color.BLACK, + 12, + font_name="arial", + width=field_width, + align="center", + ) current_y -= LINE_HEIGHT font_name = ("comic", "arial") diff --git a/tests/unit/text/test_text_error_handling.py b/tests/unit/text/test_text_error_handling.py index 4a46dd29e5..7e756ed757 100644 --- a/tests/unit/text/test_text_error_handling.py +++ b/tests/unit/text/test_text_error_handling.py @@ -7,21 +7,33 @@ def test_text_instance_raise_multiline_error(window): with pytest.raises(ValueError) as e: _ = arcade.Text("Initial text", 0, 0, width=0, multiline=True) - assert e.value.args[0] == "The 'width' parameter must be set to a non-zero value when 'multiline' is True, but got 0." + assert ( + e.value.args[0] + == "The 'width' parameter must be set to a non-zero value when 'multiline' is True, but got 0." + ) with pytest.raises(ValueError) as e: _ = arcade.Text("Initial text", 0, 0, width=None, multiline=True) - assert e.value.args[0] == "The 'width' parameter must be set to a non-zero value when 'multiline' is True, but got None." + assert ( + e.value.args[0] + == "The 'width' parameter must be set to a non-zero value when 'multiline' is True, but got None." + ) def test_text_function_raise_multiline_error(window): with pytest.raises(ValueError) as e: _ = arcade.draw_text("Initial text", 0, 0, width=0, multiline=True) - assert e.value.args[0] == "The 'width' parameter must be set to a non-zero value when 'multiline' is True, but got 0." + assert ( + e.value.args[0] + == "The 'width' parameter must be set to a non-zero value when 'multiline' is True, but got 0." + ) with pytest.raises(ValueError) as e: _ = arcade.draw_text("Initial text", 0, 0, width=None, multiline=True) - assert e.value.args[0] == "The 'width' parameter must be set to a non-zero value when 'multiline' is True, but got None." + assert ( + e.value.args[0] + == "The 'width' parameter must be set to a non-zero value when 'multiline' is True, but got None." + ) diff --git a/tests/unit/text/test_text_instance_properties.py b/tests/unit/text/test_text_instance_properties.py index 837347a75b..a7e129ad6b 100644 --- a/tests/unit/text/test_text_instance_properties.py +++ b/tests/unit/text/test_text_instance_properties.py @@ -18,11 +18,10 @@ def instance() -> arcade.Text: ("width", 600), ("bold", True), ("italic", True), - ("rotation", 45.0) - ) + ("rotation", 45.0), + ), ) def test_text_instance_simple_property(ctx, instance, prop_name, prop_new_value): - assert getattr(instance, prop_name) != prop_new_value setattr(instance, prop_name, prop_new_value) assert getattr(instance, prop_name) == prop_new_value @@ -33,11 +32,10 @@ def test_text_instance_simple_property(ctx, instance, prop_name, prop_new_value) ( ("anchor_x", ("left", "center", "right")), ("anchor_y", ("top", "center", "baseline", "bottom")), - ("bold", (True, False)) - ) + ("bold", (True, False)), + ), ) def test_text_instance_discrete_prop_valid_values(ctx, prop_name, valid_values): - for value in valid_values: i = arcade.Text("Initial text", 0.0, 0.0) @@ -46,7 +44,6 @@ def test_text_instance_discrete_prop_valid_values(ctx, prop_name, valid_values): def test_text_instance_multiline_setter(ctx): - # this requires width to be set or pyglet.label will throw errors instance = arcade.Text("Initial text", 0.0, 0.0, width=400) @@ -57,7 +54,6 @@ def test_text_instance_multiline_setter(ctx): @pytest.mark.parametrize("align", ("center", "right")) def test_text_instance_align_not_left(ctx, align): - # width must be set instance = arcade.Text("Initial text", 0, 0, width=500) @@ -71,13 +67,11 @@ def test_text_instance_align_not_left(ctx, align): def test_text_instance_position_setter(instance): - instance.position = (20.0, 40.0) assert instance.x == 20.0 assert instance.y == 40.0 def test_text_instance_position_getter(): - instance = arcade.Text("Initial text", 20.0, 40.0) assert instance.position == (20.0, 40.0) diff --git a/tests/unit/text/test_text_sprite.py b/tests/unit/text/test_text_sprite.py index 53d403721f..01b93f05ec 100644 --- a/tests/unit/text/test_text_sprite.py +++ b/tests/unit/text/test_text_sprite.py @@ -2,9 +2,7 @@ import arcade -@pytest.mark.parametrize( - 'color', (arcade.color.WHITE, (255, 255, 255), (255, 255, 255, 255)) -) +@pytest.mark.parametrize("color", (arcade.color.WHITE, (255, 255, 255), (255, 255, 255, 255))) def test_create(window, color): sprite = arcade.create_text_sprite("Hello World", color) assert isinstance(sprite, arcade.Sprite) diff --git a/tests/unit/texture/test_manager.py b/tests/unit/texture/test_manager.py index 4b88499b64..8626d84a99 100644 --- a/tests/unit/texture/test_manager.py +++ b/tests/unit/texture/test_manager.py @@ -1,10 +1,12 @@ """Test the TextureCacheManager""" + import arcade from arcade.types.rect import LBWH SPRITESHEET_PATH = ":assets:images/spritesheets/codepage_437.png" TEST_TEXTURE = ":assets:images/test_textures/test_texture.png" + def test_create(): arcade.texture.TextureCacheManager() @@ -34,7 +36,10 @@ def test_load_spritesheet_texture(): # Load a few more textures for i in range(10): texture = manager.load_or_get_spritesheet_texture(SPRITESHEET_PATH, LBWH(i * 9, 0, 8, 16)) - assert manager.load_or_get_spritesheet_texture(SPRITESHEET_PATH, LBWH(i * 9, 0, 8, 16)) == texture + assert ( + manager.load_or_get_spritesheet_texture(SPRITESHEET_PATH, LBWH(i * 9, 0, 8, 16)) + == texture + ) # We should still have 1 spritesheet assert len(manager._sprite_sheets) == 1 @@ -47,7 +52,7 @@ def test_load_spritesheet_texture(): manager.flush() assert len(manager._sprite_sheets) == 0 assert len(manager.texture_cache._file_entries) == 0 - assert len(manager.texture_cache._entries) == 0 + assert len(manager.texture_cache._entries) == 0 assert len(manager.image_data_cache) == 0 diff --git a/tests/unit/texture/test_sprite_sheet.py b/tests/unit/texture/test_sprite_sheet.py index 0fc39e07e9..feb2c37a53 100644 --- a/tests/unit/texture/test_sprite_sheet.py +++ b/tests/unit/texture/test_sprite_sheet.py @@ -13,12 +13,14 @@ def get_dollar_sign(sprite_sheet: arcade.SpriteSheet): Crop out the dollar sign from the sprite sheet. """ # left, upper, right, and lower - return sprite_sheet.image.crop(( - 9 * 4, # left: 4th column - 16, # upper: second row - 9 * 4 + 8, # right: 8 pixels wide - 16 + 16 # lower: 16 pixels tall - )) + return sprite_sheet.image.crop( + ( + 9 * 4, # left: 4th column + 16, # upper: second row + 9 * 4 + 8, # right: 8 pixels wide + 16 + 16, # lower: 16 pixels tall + ) + ) @pytest.fixture(scope="module") @@ -75,18 +77,27 @@ def test_get_image(sprite_sheet): # Crop out the dollar sign using upper left origin im = sprite_sheet.get_image( - LBWH(9 * 4, # 4th column - 16, # second row - 8, 16)) + LBWH( + 9 * 4, # 4th column + 16, # second row + 8, + 16, + ) + ) assert isinstance(im, Image.Image) assert im.size == (8, 16) assert im.tobytes() == dollar_sign.tobytes() # Crop out the dollar sign using lower left origin im = sprite_sheet.get_image( - LBWH(9 * 4, # 4th column - 16 * 6, # 6th row - 8,16), True) + LBWH( + 9 * 4, # 4th column + 16 * 6, # 6th row + 8, + 16, + ), + True, + ) assert isinstance(im, Image.Image) assert im.size == (8, 16) assert im.tobytes() == dollar_sign.tobytes() @@ -125,5 +136,5 @@ def test_get_texture_grid(sprite_sheet): assert len(textures) == 255 for texture in textures: assert texture.image.size == (8, 16) - + assert textures[36].image.tobytes() == get_dollar_sign(sprite_sheet).tobytes() diff --git a/tests/unit/texture/test_texture.py b/tests/unit/texture/test_texture.py index 59f6ff129c..5d535516f5 100644 --- a/tests/unit/texture/test_texture.py +++ b/tests/unit/texture/test_texture.py @@ -10,8 +10,14 @@ def test_create(): assert texture.height == 10 assert texture.file_path is None assert texture.crop_values is None - assert texture.image_data.hash == "7a12e561363385e9dfeeab326368731c030ed4b374e7f5897ac819159d2884c5" - assert texture.cache_name == f"{texture.image_data.hash}|{texture._vertex_order}|{texture.hit_box_algorithm.cache_name}|" + assert ( + texture.image_data.hash + == "7a12e561363385e9dfeeab326368731c030ed4b374e7f5897ac819159d2884c5" + ) + assert ( + texture.cache_name + == f"{texture.image_data.hash}|{texture._vertex_order}|{texture.hit_box_algorithm.cache_name}|" + ) with pytest.raises(TypeError): _ = arcade.Texture("not valid image data") @@ -19,7 +25,10 @@ def test_create(): def test_create_override_name(): texture = arcade.Texture(Image.new("RGBA", (10, 10)), hash="test") - assert texture.cache_name == f"test|{texture._vertex_order}|{texture.hit_box_algorithm.cache_name}|" + assert ( + texture.cache_name + == f"test|{texture._vertex_order}|{texture.hit_box_algorithm.cache_name}|" + ) def test_hitbox_algo_selection(): diff --git a/tests/unit/texture/test_texture_tools.py b/tests/unit/texture/test_texture_tools.py index fea7ab7144..bee7b94403 100644 --- a/tests/unit/texture/test_texture_tools.py +++ b/tests/unit/texture/test_texture_tools.py @@ -3,7 +3,7 @@ ImageData, get_default_texture, get_default_image, - default_texture_cache + default_texture_cache, ) diff --git a/tests/unit/texture/test_texture_transform_render.py b/tests/unit/texture/test_texture_transform_render.py index 45f685efc0..bb5b6baf9b 100644 --- a/tests/unit/texture/test_texture_transform_render.py +++ b/tests/unit/texture/test_texture_transform_render.py @@ -1,6 +1,7 @@ """ Ensure we are emulating PIL's transforms correctly. """ + import arcade import pytest from pyglet.math import Mat4 @@ -15,6 +16,7 @@ TransposeTransform, TransverseTransform, ) + # Arcade transform, PIL transform TRANSFORMS = [ (Rotate90Transform, Image.Transpose.ROTATE_270, 1), @@ -23,9 +25,10 @@ (FlipLeftRightTransform, Image.FLIP_LEFT_RIGHT, 4), (FlipTopBottomTransform, Image.FLIP_TOP_BOTTOM, 5), (TransposeTransform, Image.TRANSPOSE, 6), - (TransverseTransform, Image.TRANSVERSE, 7) + (TransverseTransform, Image.TRANSVERSE, 7), ] + @pytest.fixture(scope="module") def image(): im = Image.new("RGBA", (8, 8)) @@ -48,7 +51,9 @@ def test_rotate90_transform(ctx: arcade.ArcadeContext, image, transform, pil_tra sprite = arcade.Sprite(texture, center_x=image.width // 2, center_y=image.height // 2) with fbo.activate(): fbo.clear() - ctx.projection_matrix = Mat4.orthogonal_projection(0, image.width, 0, image.height, -100, 100) + ctx.projection_matrix = Mat4.orthogonal_projection( + 0, image.width, 0, image.height, -100, 100 + ) arcade.draw_sprite(sprite, pixelated=True) expected_image = image.transpose(pil_transform) diff --git a/tests/unit/texture/test_texture_transform_values.py b/tests/unit/texture/test_texture_transform_values.py index 82f3b98180..9667b75993 100644 --- a/tests/unit/texture/test_texture_transform_values.py +++ b/tests/unit/texture/test_texture_transform_values.py @@ -8,12 +8,9 @@ TransverseTransform, VertexOrder, ) + # Hit box points to test for transformations -HIT_BOX_POINTS = ( - (1.0, 1.0), - (2.0, 2.0), - (2.0, 1.0) -) +HIT_BOX_POINTS = ((1.0, 1.0), (2.0, 2.0), (2.0, 1.0)) ORDER = ( VertexOrder.UPPER_LEFT.value, VertexOrder.UPPER_RIGHT.value, diff --git a/tests/unit/texture/test_textures.py b/tests/unit/texture/test_textures.py index 75c2f53959..3153b5bfbb 100644 --- a/tests/unit/texture/test_textures.py +++ b/tests/unit/texture/test_textures.py @@ -27,7 +27,7 @@ def test_texture_constructor_hit_box_algo(): def test_load_texture(): - """Create texture with different """ + """Create texture with different""" path = ":resources:images/test_textures/test_texture.png" # Basic loading tex = arcade.load_texture(path) @@ -65,5 +65,5 @@ def test_crate_empty(): (-128.0, -128.0), (128.0, -128.0), (128.0, 128.0), - (-128.0, 128.0) + (-128.0, 128.0), ) diff --git a/tests/unit/tilemap/test_img_layer.py b/tests/unit/tilemap/test_img_layer.py index 7c6896ee5a..74ccd2cfd0 100644 --- a/tests/unit/tilemap/test_img_layer.py +++ b/tests/unit/tilemap/test_img_layer.py @@ -19,7 +19,7 @@ def test_image_layer(): assert "img-offset" in tile_map.sprite_lists assert len(tile_map.sprite_lists["img-offset"]) == 1 image = tile_map.sprite_lists["img-offset"][0] - + assert image.width == 1024 assert image.height == 600 assert image.left == 1280 @@ -43,8 +43,8 @@ def test_image_layer_with_scaling(): assert "img-offset" in tile_map.sprite_lists assert len(tile_map.sprite_lists["img-offset"]) == 1 image = tile_map.sprite_lists["img-offset"][0] - + assert image.width == 512 assert image.height == 300 assert image.left == 640 - assert image.top == 704 \ No newline at end of file + assert image.top == 704 diff --git a/tests/unit/tilemap/test_rotation_flip.py b/tests/unit/tilemap/test_rotation_flip.py index 4ffe96859e..3c8b76b344 100644 --- a/tests/unit/tilemap/test_rotation_flip.py +++ b/tests/unit/tilemap/test_rotation_flip.py @@ -20,7 +20,6 @@ def test_rotation_mirror(): assert my_map.width == 11 assert my_map.height == 10 - # --- Platforms --- assert "Blocking Sprites" in my_map.sprite_lists wall_list = my_map.sprite_lists["Blocking Sprites"] @@ -39,17 +38,23 @@ def test_rotation_mirror(): # Transpose and flipped horizontally wall = wall_list[2] assert wall.position == (448, 64) - assert wall.texture._vertex_order == tt.FlipLeftRightTransform.transform_vertex_order(tt.TransposeTransform.order) + assert wall.texture._vertex_order == tt.FlipLeftRightTransform.transform_vertex_order( + tt.TransposeTransform.order + ) # Transposed, flipped vertically and horizontally wall = wall_list[3] assert wall.position == (576, 64) - assert wall.texture._vertex_order == _transform(tt.TransposeTransform, tt.FlipLeftRightTransform, tt.FlipTopBottomTransform) + assert wall.texture._vertex_order == _transform( + tt.TransposeTransform, tt.FlipLeftRightTransform, tt.FlipTopBottomTransform + ) # Horizontal flip and flipped vertically wall = wall_list[4] assert wall.position == (832, 64) - assert wall.texture._vertex_order == _transform(tt.FlipLeftRightTransform, tt.FlipTopBottomTransform) + assert wall.texture._vertex_order == _transform( + tt.FlipLeftRightTransform, tt.FlipTopBottomTransform + ) # Vertical flip wall = wall_list[5] @@ -59,7 +64,9 @@ def test_rotation_mirror(): # Transposed and flipped vertically wall = wall_list[6] assert wall.position == (1216, 64) - assert wall.texture._vertex_order == _transform(tt.TransposeTransform, tt.FlipTopBottomTransform) + assert wall.texture._vertex_order == _transform( + tt.TransposeTransform, tt.FlipTopBottomTransform + ) # Transposed wall = wall_list[7] @@ -78,7 +85,7 @@ def test_object_rotation_orientation(): # --- Object --- assert "Objects Sprites" in my_map.sprite_lists wall_list = my_map.sprite_lists["Objects Sprites"] - + # Check for the direction of rotation # not rotated the top is aligned with the grid wall = wall_list[16] @@ -96,7 +103,7 @@ def test_object_rotation_orientation(): assert (wall.left / 128).is_integer() assert not (wall.right / 128).is_integer() - # Turned 180 + # Turned 180 wall = wall_list[18] assert wall.properties["name"] == "r2" assert not (wall.top / 128).is_integer() @@ -104,7 +111,7 @@ def test_object_rotation_orientation(): assert (wall.left / 128).is_integer() assert (wall.right / 128).is_integer() - # Turned 270 to the left (90 to the right) + # Turned 270 to the left (90 to the right) wall = wall_list[19] assert wall.properties["name"] == "r3" assert (wall.top / 128).is_integer() @@ -121,68 +128,68 @@ def test_object_rotation_placement(): assert "Objects Sprites" in my_map.sprite_lists wall_list = my_map.sprite_lists["Objects Sprites"] - line = 64+128*2 + line = 64 + 128 * 2 wall = wall_list[0] assert wall.properties["name"] == "not" assert wall.position == (64, line) wall = wall_list[1] assert wall.properties["name"] == "h" - assert wall.position == (64+128*1, line) + assert wall.position == (64 + 128 * 1, line) wall = wall_list[2] assert wall.properties["name"] == "90" - assert wall.position == (64+128*3, line) + assert wall.position == (64 + 128 * 3, line) wall = wall_list[3] assert wall.properties["name"] == "h90" - assert wall.position == (64+128*4, line) + assert wall.position == (64 + 128 * 4, line) wall = wall_list[4] assert wall.properties["name"] == "180" - assert wall.position == (64+128*6, line) - + assert wall.position == (64 + 128 * 6, line) + wall = wall_list[5] assert wall.properties["name"] == "h180" - assert wall.position == (64+128*7, line) + assert wall.position == (64 + 128 * 7, line) wall = wall_list[6] assert wall.properties["name"] == "-90" - assert wall.position == (64+128*9, line) + assert wall.position == (64 + 128 * 9, line) wall = wall_list[7] assert wall.properties["name"] == "h-90" - assert wall.position == (64+128*10, line) + assert wall.position == (64 + 128 * 10, line) - line = 64+128*4 + line = 64 + 128 * 4 wall = wall_list[8] assert wall.properties["name"] == "v" assert wall.position == (64, line) wall = wall_list[9] assert wall.properties["name"] == "hv" - assert wall.position == (64+128*1, line) + assert wall.position == (64 + 128 * 1, line) wall = wall_list[10] assert wall.properties["name"] == "v90" - assert wall.position == (64+128*3, line) + assert wall.position == (64 + 128 * 3, line) wall = wall_list[11] assert wall.properties["name"] == "hv90" - assert wall.position == (64+128*4, line) + assert wall.position == (64 + 128 * 4, line) wall = wall_list[12] assert wall.properties["name"] == "v180" - assert wall.position == (64+128*6, line) + assert wall.position == (64 + 128 * 6, line) wall = wall_list[13] assert wall.properties["name"] == "hv180" - assert wall.position == (64+128*7, line) + assert wall.position == (64 + 128 * 7, line) wall = wall_list[14] assert wall.properties["name"] == "v-90" - assert wall.position == (64+128*9, line) + assert wall.position == (64 + 128 * 9, line) wall = wall_list[15] assert wall.properties["name"] == "hv-90" - assert wall.position == (64+128*10, line) \ No newline at end of file + assert wall.position == (64 + 128 * 10, line) diff --git a/tests/unit/tilemap/test_tilemap_objects.py b/tests/unit/tilemap/test_tilemap_objects.py index 1b93fb7ea1..648a08c343 100644 --- a/tests/unit/tilemap/test_tilemap_objects.py +++ b/tests/unit/tilemap/test_tilemap_objects.py @@ -39,7 +39,12 @@ def test_one(): rectangle = tile_map.object_lists["Shapes"][0] assert isclose(rectangle.shape[2][0] - rectangle.shape[0][0], 573.60, abs_tol=0.02) assert isclose(rectangle.shape[0][1] - rectangle.shape[2][1], 469.04, abs_tol=0.02) - assert isclose(tile_map.tiled_map.map_size.height * tile_map.tiled_map.tile_size[1] - rectangle.shape[0][1], 630.37, abs_tol=0.02) + assert isclose( + tile_map.tiled_map.map_size.height * tile_map.tiled_map.tile_size[1] + - rectangle.shape[0][1], + 630.37, + abs_tol=0.02, + ) # # # # Test getting layer in group diff --git a/tests/unit/window/test_view.py b/tests/unit/window/test_view.py index 35147fe4c0..ac5ab72726 100644 --- a/tests/unit/window/test_view.py +++ b/tests/unit/window/test_view.py @@ -24,7 +24,8 @@ def test_on_hide_view_called(window): window.show_view(view2) hide_mock.assert_called_once() - + + def test_view_background_color(window): view = View(window, color.ARCADE_GREEN) assert view.background_color == color.ARCADE_GREEN diff --git a/tests/unit/window/test_window.py b/tests/unit/window/test_window.py index 4635e51632..1ba75f4dc6 100644 --- a/tests/unit/window/test_window.py +++ b/tests/unit/window/test_window.py @@ -47,11 +47,12 @@ def test_window(window: arcade.Window): def f(): pass - arcade.schedule(f, 1/60) + arcade.schedule(f, 1 / 60) time.sleep(0.01) arcade.unschedule(f) window.test() + def test_window_with_view_arg(window: arcade.Window): class TestView(arcade.View): def __init__(self): @@ -60,12 +61,14 @@ def __init__(self): def on_show_view(self): self.on_show_called = True + v = TestView() window.run(view=v) assert v.on_show_called assert window.current_view is v + def test_start_finish_render(window): """Test start and finish render""" # start_render must be called first diff --git a/util/create_resources_listing.py b/util/create_resources_listing.py index 150b9cb072..8b08654738 100644 --- a/util/create_resources_listing.py +++ b/util/create_resources_listing.py @@ -3,6 +3,7 @@ Generate quick API indexes in Restructured Text Format for Sphinx documentation. """ + # fmt: off # ruff: noqa import copy diff --git a/util/doc_helpers/__init__.py b/util/doc_helpers/__init__.py index 3426f7e4db..069dcfbcc6 100644 --- a/util/doc_helpers/__init__.py +++ b/util/doc_helpers/__init__.py @@ -15,6 +15,7 @@ class NotExcludedBy: This is here because we may eventually define excludes at per-module level in our config below instead of a single list. """ + def __init__(self, collection: Iterable): self.items = set(collection) @@ -24,6 +25,7 @@ def __call__(self, item) -> bool: class SharedPaths: """These are often used to set up a Vfs and open files.""" + REPO_UTILS_DIR = Path(__file__).parent.parent.resolve() REPO_ROOT = REPO_UTILS_DIR.parent ARCADE_ROOT = REPO_ROOT / "arcade" @@ -31,8 +33,7 @@ class SharedPaths: API_DOC_ROOT = DOC_ROOT / "api_docs" - -def get_module_path(module: str, root = SharedPaths.REPO_ROOT) -> Path: +def get_module_path(module: str, root=SharedPaths.REPO_ROOT) -> Path: """Quick-n-dirty module path estimation relative to the repo root. Args: @@ -44,10 +45,9 @@ def get_module_path(module: str, root = SharedPaths.REPO_ROOT) -> Path: """ # Convert module.name.here to module/name/here current = root - for index, part in enumerate(module.split('.')): + for index, part in enumerate(module.split(".")): if not _VALID_MODULE_SEGMENT.fullmatch(part): - raise ValueError( - f'Invalid module segment at index {index}: {part!r}') + raise ValueError(f"Invalid module segment at index {index}: {part!r}") # else: # print(current, part) current /= part @@ -57,25 +57,25 @@ def get_module_path(module: str, root = SharedPaths.REPO_ROOT) -> Path: # 2. arcade/module/__init__.py as_package = current / "__init__.py" have_package = as_package.is_file() - as_file = current.with_suffix('.py') + as_file = current.with_suffix(".py") have_file = as_file.is_file() # TODO: When 3.10 becomes our min Python, make this a match-case? if have_package and have_file: - raise ValueError( - f"Module conflict between {as_package} and {as_file}") + raise ValueError(f"Module conflict between {as_package} and {as_file}") elif have_package: current = as_package elif have_file: current = as_file else: - raise ValueError( - f"No folder package or file module detected for " - f"{module}") + raise ValueError(f"No folder package or file module detected for {module}") return current + + class SharedPaths: """These are often used to set up a Vfs and open files.""" + REPO_UTILS_DIR = Path(__file__).parent.parent.resolve() REPO_ROOT = REPO_UTILS_DIR.parent ARCADE_ROOT = REPO_ROOT / "arcade" @@ -83,8 +83,7 @@ class SharedPaths: API_DOC_ROOT = DOC_ROOT / "api_docs" - -def get_module_path(module: str, root = SharedPaths.REPO_ROOT) -> Path: +def get_module_path(module: str, root=SharedPaths.REPO_ROOT) -> Path: """Quick-n-dirty module path estimation relative to the repo root. Args: @@ -96,10 +95,9 @@ def get_module_path(module: str, root = SharedPaths.REPO_ROOT) -> Path: """ # Convert module.name.here to module/name/here current = root - for index, part in enumerate(module.split('.')): + for index, part in enumerate(module.split(".")): if not _VALID_MODULE_SEGMENT.fullmatch(part): - raise ValueError( - f'Invalid module segment at index {index}: {part!r}') + raise ValueError(f"Invalid module segment at index {index}: {part!r}") # else: # print(current, part) current /= part @@ -109,33 +107,29 @@ def get_module_path(module: str, root = SharedPaths.REPO_ROOT) -> Path: # 2. arcade/module/__init__.py as_package = current / "__init__.py" have_package = as_package.is_file() - as_file = current.with_suffix('.py') + as_file = current.with_suffix(".py") have_file = as_file.is_file() # TODO: When 3.10 becomes our min Python, make this a match-case? if have_package and have_file: - raise ValueError( - f"Module conflict between {as_package} and {as_file}") + raise ValueError(f"Module conflict between {as_package} and {as_file}") elif have_package: current = as_package elif have_file: current = as_file else: - raise ValueError( - f"No folder package or file module detected for " - f"{module}") + raise ValueError(f"No folder package or file module detected for {module}") return current - __all__ = ( - 'get_module_path', - 'SharedPaths', - 'EMPTY_TUPLE', - 'F', - 'NotExcludedBy', - 'VirtualFile', - 'Vfs', - 'build_import_tree', + "get_module_path", + "SharedPaths", + "EMPTY_TUPLE", + "F", + "NotExcludedBy", + "VirtualFile", + "Vfs", + "build_import_tree", ) diff --git a/util/doc_helpers/real_filesystem.py b/util/doc_helpers/real_filesystem.py index 0cfc635be2..f7efa1962a 100644 --- a/util/doc_helpers/real_filesystem.py +++ b/util/doc_helpers/real_filesystem.py @@ -2,12 +2,13 @@ Helpers for dealing with the real-world file system. """ + import shutil from pathlib import Path from typing import Generator, TypeVar, Hashable, Iterable, Mapping, Sequence, Callable import logging -H = TypeVar('H', bound=Hashable) +H = TypeVar("H", bound=Hashable) FILE = Path(__file__) REPO_ROOT = Path(__file__).parent.parent.resolve() @@ -28,9 +29,7 @@ def dest_older(src: Path | str, dest: Path | str) -> bool: def multi_glob( - p: str | Path, - *globs: str, - predicate: Callable[[Path], bool] | None = None + p: str | Path, *globs: str, predicate: Callable[[Path], bool] | None = None ) -> Generator[Path, None, None]: """Chain multiple :py:class:`pathlib.Path.glob` results into one. @@ -84,17 +83,18 @@ def sync_dir(src_dir: Path, dest_dir: Path, *globs: str, done: set | None = None if not dest_file.exists() or dest_older(src_file, dest_file): dest_file.parent.mkdir(parents=True, exist_ok=True) - log.info(f' Copying media file {src_file} to {dest_file}') + log.info(f" Copying media file {src_file} to {dest_file}") shutil.copyfile(src_file, dest_file) else: log.info(f" Skipping media file {src_file} to {dest_file}") + def copy_media( - src_root: Path | str, - dest_root: Path | str, - items: Mapping[str | Path, Sequence[str]], - done: set | None = None + src_root: Path | str, + dest_root: Path | str, + items: Mapping[str | Path, Sequence[str]], + done: set | None = None, ) -> None: """A more configurable version of the file syncing scripts we use. diff --git a/util/doc_helpers/vfs.py b/util/doc_helpers/vfs.py index c88baafce1..3f0b1f438f 100644 --- a/util/doc_helpers/vfs.py +++ b/util/doc_helpers/vfs.py @@ -27,6 +27,7 @@ by reading each file before write and aborting if its contents would be unchanged. """ + from contextlib import suppress, contextmanager from io import StringIO from pathlib import Path @@ -73,7 +74,7 @@ def _write_to_disk(self): f.write(content) -F = TypeVar('F', bound=VirtualFile) +F = TypeVar("F", bound=VirtualFile) class Vfs(Generic[F]): diff --git a/util/generate_example_thumbnails.py b/util/generate_example_thumbnails.py index 83d572d4be..3f1db775a7 100644 --- a/util/generate_example_thumbnails.py +++ b/util/generate_example_thumbnails.py @@ -5,11 +5,11 @@ def main(): - input_path = Path('example_code/images') - output_path = Path('example_code/images/thumbs/') + input_path = Path("example_code/images") + output_path = Path("example_code/images/thumbs/") - png_input_files = input_path.glob('*.png') - gif_input_files = input_path.glob('*.gif') + png_input_files = input_path.glob("*.png") + gif_input_files = input_path.glob("*.gif") modified_files = [] @@ -40,12 +40,12 @@ def generate_thumbnails(input_files, output_path): output_path.mkdir(exist_ok=True) for input_file in input_files: - print('Generating thumbnail: ' + input_file.name) + print("Generating thumbnail: " + input_file.name) im = Image.open(input_file) im.thumbnail(size) im.save(output_path / input_file.name) print("Done generating thumbnails.") -if __name__ == '__main__': +if __name__ == "__main__": main() diff --git a/util/generate_hit_box_cache.py b/util/generate_hit_box_cache.py index 7391af350f..f61d76f23d 100644 --- a/util/generate_hit_box_cache.py +++ b/util/generate_hit_box_cache.py @@ -1,6 +1,7 @@ """ Generates a cache of hit boxes for all the built in resources. """ + import sys import time from pathlib import Path @@ -42,7 +43,7 @@ algorithm = "simple" textures.append(arcade.load_texture(path, hit_box_algorithm=algorithm)) algorithm = "detailed" - textures.append(arcade.load_texture(path, hit_box_algorithm=algorithm)) + textures.append(arcade.load_texture(path, hit_box_algorithm=algorithm)) except Exception as e: print() print(f"Error loading ({algorithm}): {path.relative_to(RESOURCE_DIR)}") diff --git a/util/sphinx_static_file_temp_fix.py b/util/sphinx_static_file_temp_fix.py index 80d8107508..b728b9b485 100644 --- a/util/sphinx_static_file_temp_fix.py +++ b/util/sphinx_static_file_temp_fix.py @@ -42,6 +42,7 @@ 4. Our customizations to be tested with all of the above """ + import shutil import sys import logging @@ -76,23 +77,13 @@ # You can add per-dir config the lazy way: # 1. copy & paste this block # 2. modifying it with filtering - **{ - source_file: BUILD_CSS_DIR / source_file.name - for source_file in SOURCE_CSS_DIR.glob("*.*") - }, - **{ - source_file: BUILD_JS_DIR / source_file.name - for source_file in SOURCE_JS_DIR.glob("*.*") - }, + **{source_file: BUILD_CSS_DIR / source_file.name for source_file in SOURCE_CSS_DIR.glob("*.*")}, + **{source_file: BUILD_JS_DIR / source_file.name for source_file in SOURCE_JS_DIR.glob("*.*")}, } # pending: some clever use of util/doc_helpers/vfs.py -def force_sync( - src: Path, - dest: Path, - dry: bool = False -) -> None: +def force_sync(src: Path, dest: Path, dry: bool = False) -> None: """Sync a single file from ``src`` to ``dest``. Caveats: @@ -120,7 +111,9 @@ def main(): skip_reason = None if not ENABLE_DEVMACHINE_SPHINX_STATIC_FIX.exists(): - skip_reason = f"SKIP: Force sync not enabled by a {ENABLE_DEVMACHINE_SPHINX_STATIC_FIX} file!" + skip_reason = ( + f"SKIP: Force sync not enabled by a {ENABLE_DEVMACHINE_SPHINX_STATIC_FIX} file!" + ) elif not BUILD_HTML_DIR.exists(): skip_reason = f"SKIP: {BUILD_HTML_DIR} does not exist yet." @@ -129,11 +122,13 @@ def main(): else: # indented so we can grep for Done force-syncing in the logs from sphinx import __version__ as sphinx_version + log.info(f" SYNC: Force-sync enable file found and build-dir exists") - if sphinx_version >= '8.1.4': + if sphinx_version >= "8.1.4": log.warning( - ' Sphinx >= 8.1.4 may patch broken _static copy\n' - ' (see https://github.com/sphinx-doc/sphinx/issues/1810)') + " Sphinx >= 8.1.4 may patch broken _static copy\n" + " (see https://github.com/sphinx-doc/sphinx/issues/1810)" + ) for src, dest in force_copy_on_change.items(): force_sync(src, dest) diff --git a/util/sync_example_code_with_rst.py b/util/sync_example_code_with_rst.py index 7f01a980b6..648a3c7ed3 100644 --- a/util/sync_example_code_with_rst.py +++ b/util/sync_example_code_with_rst.py @@ -3,6 +3,7 @@ # .. literalinclude:: ../../arcade/examples/array_backed_grid_buffered.py # :ref:`platformer_tutorial` import re + literal_include_pattern = re.compile(r"literalinclude:: .*/(.*\.py)$") ref_pattern = re.compile(":ref:`(.*)`") @@ -30,7 +31,6 @@ def check_directory_for_python_files(self, my_path: Path): def check_rst_file(self, cur_node: Path): if cur_node.name.endswith(".rst"): - i = 0 try: for i, line in enumerate(open(cur_node, encoding="utf-8")): @@ -42,7 +42,6 @@ def check_rst_file(self, cur_node: Path): def check_for_rst_ref(self, cur_node: Path): if cur_node.name.endswith(".rst"): - i = 0 try: for i, line in enumerate(open(cur_node, encoding="utf-8")): diff --git a/util/update_quick_index.py b/util/update_quick_index.py index c9a0731d8a..e6729b1af1 100644 --- a/util/update_quick_index.py +++ b/util/update_quick_index.py @@ -11,6 +11,7 @@ a # --- so you can skip between them in diffs or your favorite editor via hotkeys. """ + import re import sys from collections.abc import Mapping @@ -41,12 +42,10 @@ # --- 1. Special rules & excludes --- -RULE_SHOW_INHERITANCE = (':show-inheritance:',) -RULE_INHERITED_MEMBERS = (':inherited-members:',) +RULE_SHOW_INHERITANCE = (":show-inheritance:",) +RULE_INHERITED_MEMBERS = (":inherited-members:",) -MEMBER_SPECIAL_RULES = { - "arcade.ArcadeContext" : RULE_SHOW_INHERITANCE + RULE_INHERITED_MEMBERS -} +MEMBER_SPECIAL_RULES = {"arcade.ArcadeContext": RULE_SHOW_INHERITANCE + RULE_INHERITED_MEMBERS} # Module and class members to exclude @@ -69,8 +68,8 @@ "arcade.types.vector_like", "arcade.types.color", "arcade.types.rect", - "arcade.types.box" - ] + "arcade.types.box", + ], }, "resources.rst": { "title": "Resources", @@ -90,7 +89,7 @@ "arcade.draw.polygon", "arcade.draw.rect", "arcade.draw.triangle", - ] + ], }, "sprites.rst": { "title": "Sprites", @@ -101,8 +100,8 @@ "arcade.sprite.colored", "arcade.sprite.mixins", "arcade.sprite.animated", - "arcade.sprite.enums" - ] + "arcade.sprite.enums", + ], }, "sprite_list.rst": { "title": "Sprite Lists", @@ -110,8 +109,8 @@ "arcade.sprite_list", "arcade.sprite_list.sprite_list", "arcade.sprite_list.spatial_hash", - "arcade.sprite_list.collision" - ] + "arcade.sprite_list.collision", + ], }, "clock.rst": { "title": "Clock", @@ -119,30 +118,10 @@ "arcade.clock", ], }, - "text.rst": { - "title": "Text", - "use_declarations_in": [ - "arcade.text" - ] - }, - "camera_2d.rst": { - "title": "Camera 2D", - "use_declarations_in": [ - "arcade.camera.camera_2d" - ] - }, - "sprite_scenes.rst": { - "title": "Sprite Scenes", - "use_declarations_in": [ - "arcade.scene" - ] - }, - "tilemap.rst": { - "title": "Tiled Map Reader", - "use_declarations_in": [ - "arcade.tilemap.tilemap" - ] - }, + "text.rst": {"title": "Text", "use_declarations_in": ["arcade.text"]}, + "camera_2d.rst": {"title": "Camera 2D", "use_declarations_in": ["arcade.camera.camera_2d"]}, + "sprite_scenes.rst": {"title": "Sprite Scenes", "use_declarations_in": ["arcade.scene"]}, + "tilemap.rst": {"title": "Tiled Map Reader", "use_declarations_in": ["arcade.tilemap.tilemap"]}, "texture.rst": { "title": "Texture Management", "use_declarations_in": [ @@ -152,8 +131,8 @@ "arcade.texture.generate", "arcade.texture.manager", "arcade.texture.spritesheet", - "arcade.texture.tools" - ] + "arcade.texture.tools", + ], }, "hitbox.rst": { "title": "Hitbox", @@ -167,9 +146,7 @@ }, "texture_transforms.rst": { "title": "Texture Transforms", - "use_declarations_in": [ - "arcade.texture.transforms" - ] + "use_declarations_in": ["arcade.texture.transforms"], }, "texture_atlas.rst": { "title": "Texture Atlas", @@ -180,40 +157,22 @@ "arcade.texture_atlas.region", "arcade.texture_atlas.uv_data", "arcade.texture_atlas.ref_counters", - ] + ], }, "perf_info.rst": { "title": "Performance Information", - "use_declarations_in": [ - "arcade.perf_info", - "arcade.perf_graph" - ] + "use_declarations_in": ["arcade.perf_info", "arcade.perf_graph"], }, "physics_engines.rst": { "title": "Physics Engines", - "use_declarations_in": [ - "arcade.physics_engines", - "arcade.pymunk_physics_engine" - ] - }, - "geometry.rst": { - "title": "Geometry Support", - "use_declarations_in": [ - "arcade.geometry" - ] + "use_declarations_in": ["arcade.physics_engines", "arcade.pymunk_physics_engine"], }, + "geometry.rst": {"title": "Geometry Support", "use_declarations_in": ["arcade.geometry"]}, "game_controller.rst": { "title": "Game Controller", - "use_declarations_in": [ - "arcade.controller" - ] - }, - "joysticks.rst": { - "title": "Joystick", - "use_declarations_in": [ - "arcade.joysticks" - ] + "use_declarations_in": ["arcade.controller"], }, + "joysticks.rst": {"title": "Joystick", "use_declarations_in": ["arcade.joysticks"]}, "window.rst": { "title": "Window and View", "use_declarations_in": [ @@ -221,64 +180,23 @@ "arcade.window_commands", "arcade.sections", "arcade.screenshot", - ] - }, - "sound.rst": { - "title": "Sound", - "use_declarations_in": [ - "arcade.sound" - ] - }, - "path_finding.rst": { - "title": "Pathfinding", - "use_declarations_in": [ - "arcade.paths" - ] + ], }, + "sound.rst": {"title": "Sound", "use_declarations_in": ["arcade.sound"]}, + "path_finding.rst": {"title": "Pathfinding", "use_declarations_in": ["arcade.paths"]}, "isometric.rst": { "title": "Isometric Map (incomplete)", - "use_declarations_in": [ - "arcade.isometric" - ] - }, - "easing.rst": { - "title": "Easing", - "use_declarations_in": [ - "arcade.easing" - ] + "use_declarations_in": ["arcade.isometric"], }, + "easing.rst": {"title": "Easing", "use_declarations_in": ["arcade.easing"]}, "utility.rst": { "title": "Misc Utility Functions", - "use_declarations_in": [ - "arcade", - "arcade.__main__", - "arcade.utils" - ] - }, - "drawing_batch.rst": { - "title": "Shape Lists", - "use_declarations_in": [ - "arcade.shape_list" - ] - }, - "open_gl.rst": { - "title": "OpenGL Context", - "use_declarations_in": [ - "arcade.context" - ] - }, - "math.rst": { - "title": "Math", - "use_declarations_in": [ - "arcade.math" - ] - }, - "earclip.rst": { - "title": "Earclip", - "use_declarations_in": [ - "arcade.earclip" - ] + "use_declarations_in": ["arcade", "arcade.__main__", "arcade.utils"], }, + "drawing_batch.rst": {"title": "Shape Lists", "use_declarations_in": ["arcade.shape_list"]}, + "open_gl.rst": {"title": "OpenGL Context", "use_declarations_in": ["arcade.context"]}, + "math.rst": {"title": "Math", "use_declarations_in": ["arcade.math"]}, + "earclip.rst": {"title": "Earclip", "use_declarations_in": ["arcade.earclip"]}, "gui.rst": { "title": "GUI", "use_declarations_in": [ @@ -288,8 +206,8 @@ "arcade.gui.surface", "arcade.gui.ui_manager", "arcade.gui.nine_patch", - "arcade.gui.view" - ] + "arcade.gui.view", + ], }, "gui_widgets.rst": { "title": "GUI Widgets", @@ -301,51 +219,37 @@ "arcade.gui.widgets.slider", "arcade.gui.widgets.text", "arcade.gui.widgets.toggle", - "arcade.gui.widgets.image" - ] - }, - "gui_events.rst": { - "title": "GUI Events", - "use_declarations_in": [ - "arcade.gui.events" - ] + "arcade.gui.widgets.image", + ], }, + "gui_events.rst": {"title": "GUI Events", "use_declarations_in": ["arcade.gui.events"]}, "gui_properties.rst": { "title": "GUI Properties", - "use_declarations_in": [ - "arcade.gui.property" - ] - }, - "gui_style.rst": { - "title": "GUI Style", - "use_declarations_in": [ - "arcade.gui.style" - ] + "use_declarations_in": ["arcade.gui.property"], }, + "gui_style.rst": {"title": "GUI Style", "use_declarations_in": ["arcade.gui.style"]}, "gui_experimental.rst": { "title": "GUI Experimental Features", "use_declarations_in": [ "arcade.gui.experimental.password_input", "arcade.gui.experimental.scroll_area", - "arcade.gui.experimental.typed_text_input" - ] + "arcade.gui.experimental.typed_text_input", + ], }, "advanced_cameras.rst": { - "title": "Advanced Camera Features", - "use_declarations_in": [ - "arcade.camera.data_types", - "arcade.camera.projection_functions", - "arcade.camera.orthographic", - "arcade.camera.perspective", - "arcade.camera.default", - "arcade.camera.static" - ] + "title": "Advanced Camera Features", + "use_declarations_in": [ + "arcade.camera.data_types", + "arcade.camera.projection_functions", + "arcade.camera.orthographic", + "arcade.camera.perspective", + "arcade.camera.default", + "arcade.camera.static", + ], }, "exceptions.rst": { - "title": "Exceptions", - "use_declarations_in": [ - "arcade.exceptions" - ], + "title": "Exceptions", + "use_declarations_in": ["arcade.exceptions"], }, "start_finish_render.rst": { "title": "Start/Finish Render", @@ -363,19 +267,19 @@ ], }, "future.rst": { - "title": "Future Features", - "use_declarations_in": [ - "arcade.future.texture_render_target", - "arcade.future.input.inputs", - "arcade.future.input.manager", - "arcade.future.input.input_mapping", - "arcade.future.input.raw_dicts", - "arcade.future.background.background_texture", - "arcade.future.background.background", - "arcade.future.background.groups", - "arcade.future.light.lights", - "arcade.future.video.video_player" - ] + "title": "Future Features", + "use_declarations_in": [ + "arcade.future.texture_render_target", + "arcade.future.input.inputs", + "arcade.future.input.manager", + "arcade.future.input.input_mapping", + "arcade.future.input.raw_dicts", + "arcade.future.background.background_texture", + "arcade.future.background.background", + "arcade.future.background.groups", + "arcade.future.light.lights", + "arcade.future.video.video_player", + ], }, } @@ -385,7 +289,7 @@ # Return structure of parsing looks like this DeclarationsDict = dict[ str, # "kind" name or "*" - list[str] # A list of member names + list[str], # A list of member names ] # Patterns + default config dict @@ -395,16 +299,15 @@ # in the rect, box, and other modules. FUNCTION_RE = re.compile("^def ([a-zA-Z][a-zA-Z0-9_]*)") TYPE_RE = re.compile("^(?!LOG =)([A-Za-z][A-Za-z0-9_]*) =") -DEFAULT_EXPRESSIONS = { - 'class': CLASS_RE, - 'function': FUNCTION_RE, +DEFAULT_EXPRESSIONS = { + "class": CLASS_RE, + "function": FUNCTION_RE, # 'type': TYPE_RE } def get_file_declarations( - filepath: Path, - kind_to_regex: Mapping[str, re.Pattern] = DEFAULT_EXPRESSIONS + filepath: Path, kind_to_regex: Mapping[str, re.Pattern] = DEFAULT_EXPRESSIONS ) -> DeclarationsDict: """Use a mapping of kind names to regex to get declarations. @@ -434,7 +337,7 @@ def get_file_declarations( filename = filepath.name # Set up our return value dict - parsed_values = {'*':[]} + parsed_values = {"*": []} for kind_name, exp in kind_to_regex.items(): # print(f" ...with {group_name} expression {e.pattern!r}") parsed_values[kind_name] = [] @@ -446,7 +349,7 @@ def get_file_declarations( for kind, exp in kind_to_regex.items(): parsed_raw = exp.findall(line) parsed_values[kind].extend(parsed_raw) - parsed_values['*'].extend(parsed_raw) + parsed_values["*"].extend(parsed_raw) except Exception as e: print(f"Exception processing {filename} on line {line_no}: {e}") @@ -457,7 +360,6 @@ def get_file_declarations( return parsed_values - # --- 4. API file generation --- def generate_api_file(api_file_name: str, vfs: Vfs): """ @@ -481,8 +383,8 @@ def generate_api_file(api_file_name: str, vfs: Vfs): try: full_api_file_name = API_DOC_GENERATION_DIR / api_file_name - title = page_config.get('title') - use_declarations_in = page_config.get('use_declarations_in', EMPTY_TUPLE) + title = page_config.get("title") + use_declarations_in = page_config.get("use_declarations_in", EMPTY_TUPLE) # print(f"API filename {api_file_name} gets {title=} with {use_declarations_in=}") except Exception as e: @@ -527,7 +429,8 @@ def generate_api_file(api_file_name: str, vfs: Vfs): if "test" in module_name: print( f"WARNING: {module_name!r} appears to contain tests." - f"Those belong in the 'tests/' directory!") + f"Those belong in the 'tests/' directory!" + ) continue # TODO: Figure out how to reliably parse & render types? @@ -535,16 +438,15 @@ def generate_api_file(api_file_name: str, vfs: Vfs): member_lists = get_file_declarations(module_path) # Skip a file if we got no imports - if not len(member_lists['*']): + if not len(member_lists["*"]): print( f"WARNING: No members parsed for {module_name!r} with" f" inferred path {module_path!r}. Check & update your" - f"config?") + f"config?" + ) continue - def iter_declarations( - kind: str - ) -> Generator[tuple[str, str], None, None]: + def iter_declarations(kind: str) -> Generator[tuple[str, str], None, None]: kind_list = member_lists[kind] for name in filter(member_not_excluded, kind_list): yield name, IMPORT_TREE.resolve(f"{module_name}.{name}") @@ -558,7 +460,7 @@ def iter_declarations( # api_file.write("\n") # Classes - for name, full_name in iter_declarations('class'): + for name, full_name in iter_declarations("class"): quick_index_file.write(f" * - :py:class:`{full_name}`\n") quick_index_file.write(f" - {title}\n") @@ -578,7 +480,7 @@ def iter_declarations( # text_file.write(f" - {path_name}\n") # Functions - for name, full_name in iter_declarations('function'): + for name, full_name in iter_declarations("function"): quick_index_file.write(f" * - :py:func:`{full_name}`\n") quick_index_file.write(f" - {title}\n") @@ -595,18 +497,18 @@ def main(): vfs = Vfs() # Delete the API directory files - vfs.request_culling_unwritten(API_DOC_GENERATION_DIR, '*.rst') + vfs.request_culling_unwritten(API_DOC_GENERATION_DIR, "*.rst") # Open in "w" mode to clear with vfs.open_ctx(QUICK_INDEX_FILE_PATH, "w") as text_file: - text_file.include_file( - REPO_ROOT / 'util' / 'template_quick_index.rst') + text_file.include_file(REPO_ROOT / "util" / "template_quick_index.rst") # text_file.write("The Arcade module\n") # text_file.write("-----------------\n\n") - text_file.write(dedent( - """ + text_file.write( + dedent( + """ .. list-table:: :widths: 50 50 :header-rows: 1 @@ -616,7 +518,8 @@ def main(): * - Name - Group """ - )) + ) + ) for filename in API_FILE_TO_TITLE_AND_MODULES.keys(): generate_api_file(filename, vfs) From 380bd05196fae122678327aa79cc2bb4af5e39fb Mon Sep 17 00:00:00 2001 From: Benjamin Kirkbride Date: Tue, 20 May 2025 13:33:50 -0400 Subject: [PATCH 2/2] fix example --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index e67436c235..b840af03f0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -95,7 +95,7 @@ lint.exclude = [ ".pytest_cache", "temp", "bugs", - "arcade/examples/platform_tutorial", + "arcade/examples/*", ] lint.ignore = [ "E731", # E731 do not assign a lambda expression, use a def