From d669f0b7390054c57c04f49f9b6309b63992bcf9 Mon Sep 17 00:00:00 2001 From: Evan Kiefl Date: Sun, 2 Aug 2026 12:20:15 -0700 Subject: [PATCH 01/11] Bump ruff to 0.16.1 and apply safe auto-fixes --- pooltool/__init__.py | 35 ++-- pooltool/ai/aim/core.py | 2 +- pooltool/ani/animate.py | 4 +- pooltool/ani/camera/__init__.py | 2 +- pooltool/ani/camera/_camera.py | 6 +- pooltool/ani/collision.py | 5 +- pooltool/ani/hud.py | 8 +- pooltool/ani/image/__init__.py | 14 +- pooltool/ani/menu/__init__.py | 2 +- pooltool/ani/menu/_datatypes.py | 2 +- pooltool/ani/modes/__init__.py | 4 +- pooltool/ani/modes/aim.py | 8 +- pooltool/ani/modes/ball_in_hand.py | 4 +- pooltool/ani/modes/calculate.py | 2 +- pooltool/ani/modes/call_shot.py | 4 +- pooltool/ani/modes/cam_load.py | 2 +- pooltool/ani/modes/cam_save.py | 2 +- pooltool/ani/modes/datatypes.py | 2 +- pooltool/ani/modes/menu.py | 2 +- pooltool/ani/modes/pick_ball.py | 4 +- pooltool/ani/modes/purgatory.py | 2 +- pooltool/ani/modes/shot.py | 2 +- pooltool/ani/modes/stroke.py | 2 +- pooltool/ani/modes/view.py | 8 +- pooltool/ani/utils.py | 2 +- pooltool/events/__init__.py | 32 ++-- pooltool/events/filter.py | 4 +- pooltool/evolution/__init__.py | 2 +- pooltool/evolution/continuous.py | 2 +- .../evolution/event_based/detect/ball_ball.py | 14 +- .../event_based/detect/ball_cushion.py | 7 +- .../event_based/detect/ball_pocket.py | 2 +- .../detect/ball_position_polynomial.py | 2 +- .../evolution/event_based/detect/detector.py | 2 +- pooltool/evolution/event_based/simulate.py | 2 +- pooltool/layouts.py | 6 +- pooltool/objects/__init__.py | 28 ++-- pooltool/objects/ball/datatypes.py | 2 +- pooltool/objects/ball/render.py | 2 +- pooltool/objects/cue/render.py | 2 +- pooltool/objects/table/components.py | 2 +- pooltool/objects/table/datatypes.py | 2 +- pooltool/objects/table/specs.py | 4 +- pooltool/physics/evolve/__init__.py | 2 +- pooltool/physics/resolve/__init__.py | 2 +- pooltool/physics/resolve/ball_ball/core.py | 2 +- .../physics/resolve/ball_ball/friction.py | 2 +- .../frictional_inelastic/__init__.py | 2 +- .../frictionless_elastic/__init__.py | 2 +- pooltool/physics/resolve/ball_cushion/core.py | 2 +- .../resolve/ball_cushion/han_2005/model.py | 2 +- .../ball_cushion/han_2005/properties.py | 2 +- .../ball_cushion/mathavan_2010/__init__.py | 2 +- .../ball_cushion/mathavan_2010/model.py | 2 +- .../ball_cushion/stronge_compliant/model.py | 2 +- .../ball_cushion/unrealistic/__init__.py | 2 +- .../frictional_inelastic/__init__.py | 3 +- .../resolve/sphere_half_space_collision.py | 2 +- .../instantaneous_point/__init__.py | 2 +- pooltool/physics/resolve/stronge_compliant.py | 18 +- pooltool/ptmath/__init__.py | 22 +-- pooltool/ptmath/roots/__init__.py | 9 +- pooltool/ptmath/roots/_quartic_numba.py | 3 +- pooltool/ruleset/__init__.py | 22 +-- pooltool/ruleset/datatypes.py | 5 +- pooltool/serialize/__init__.py | 10 +- pooltool/system/__init__.py | 4 +- pooltool/system/datatypes.py | 2 +- pooltool/utils/strenum.py | 6 +- sandbox/arena.py | 2 +- sandbox/ball_ball_collisions.py | 2 +- sandbox/ball_cushion_collisions.py | 2 +- tests/evolution/event_based/test_ball_ball.py | 2 +- tests/evolution/event_based/test_simulate.py | 4 +- tests/ptmath/test_ptmath.py | 6 +- tests/test_layouts.py | 2 +- uv.lock | 154 +++++++++--------- 77 files changed, 271 insertions(+), 284 deletions(-) diff --git a/pooltool/__init__.py b/pooltool/__init__.py index c55b02d1..c207e634 100755 --- a/pooltool/__init__.py +++ b/pooltool/__init__.py @@ -21,23 +21,24 @@ __version__ = version("pooltool-billiards") -import pooltool.ai as ai -import pooltool.ai.aim as aim -import pooltool.ai.pot as pot -import pooltool.ani.image as image -import pooltool.constants as constants -import pooltool.events as events -import pooltool.evolution as evolution -import pooltool.game as game -import pooltool.interact as interact -import pooltool.layouts as layouts -import pooltool.objects as objects -import pooltool.physics as physics -import pooltool.ptmath as ptmath -import pooltool.ruleset as ruleset -import pooltool.serialize as serialize -import pooltool.system as system -import pooltool.utils as utils +from pooltool import ( + ai, + constants, + events, + evolution, + game, + interact, + layouts, + objects, + physics, + ptmath, + ruleset, + serialize, + system, + utils, +) +from pooltool.ai import aim, pot +from pooltool.ani import image from pooltool.events import EventType from pooltool.evolution import continuize, interpolate_ball_states, simulate from pooltool.game.datatypes import GameType diff --git a/pooltool/ai/aim/core.py b/pooltool/ai/aim/core.py index eff32603..f28f2e7f 100644 --- a/pooltool/ai/aim/core.py +++ b/pooltool/ai/aim/core.py @@ -4,7 +4,7 @@ import numpy as np from numpy.typing import NDArray -import pooltool.ptmath as ptmath +from pooltool import ptmath from pooltool.objects.ball.datatypes import Ball from pooltool.system.datatypes import System diff --git a/pooltool/ani/animate.py b/pooltool/ani/animate.py index dd973291..d1a0c769 100755 --- a/pooltool/ani/animate.py +++ b/pooltool/ani/animate.py @@ -15,8 +15,8 @@ WindowProperties, ) -import pooltool.ani.tasks as tasks import pooltool.ani.utils as autils +from pooltool.ani import tasks from pooltool.ani.camera import CameraState, cam from pooltool.ani.collision import cue_avoid from pooltool.ani.constants import menu_text_scale @@ -541,7 +541,7 @@ def start(self): __all__ = [ + "FrameStepper", "Game", "ShotViewer", - "FrameStepper", ] diff --git a/pooltool/ani/camera/__init__.py b/pooltool/ani/camera/__init__.py index a18f415b..e722a2c8 100644 --- a/pooltool/ani/camera/__init__.py +++ b/pooltool/ani/camera/__init__.py @@ -4,8 +4,8 @@ cam = Camera() __all__ = [ - "cam", "Camera", "CameraState", + "cam", "camera_states", ] diff --git a/pooltool/ani/camera/_camera.py b/pooltool/ani/camera/_camera.py index 4ab443c9..6f20968b 100644 --- a/pooltool/ani/camera/_camera.py +++ b/pooltool/ani/camera/_camera.py @@ -90,10 +90,8 @@ def rotate_via_mouse(self, fine_control: bool = False, theta_only: bool = False) theta = self.theta + dtheta phi = self.phi + dphi - if theta > 90: - theta = 90 - if theta < 0: - theta = 0 + theta = min(theta, 90) + theta = max(theta, 0) if theta_only: self.rotate(theta=theta) diff --git a/pooltool/ani/collision.py b/pooltool/ani/collision.py index a4aeb470..28461e02 100644 --- a/pooltool/ani/collision.py +++ b/pooltool/ani/collision.py @@ -1,7 +1,7 @@ import numpy as np from panda3d.core import CollisionHandlerQueue, CollisionTraverser -import pooltool.ptmath as ptmath +from pooltool import ptmath from pooltool.ani.globals import Global from pooltool.ani.scene import visual from pooltool.config import settings @@ -77,8 +77,7 @@ def collision_task(self, task): for entry in self.collision_handler.entries: min_theta = self.process_collision(entry) - if min_theta > max_min_theta: - max_min_theta = min_theta + max_min_theta = max(max_min_theta, min_theta) self.min_theta = max_min_theta return task.cont diff --git a/pooltool/ani/hud.py b/pooltool/ani/hud.py index 8d4777c1..b394e95e 100644 --- a/pooltool/ani/hud.py +++ b/pooltool/ani/hud.py @@ -8,8 +8,8 @@ from direct.interval.LerpInterval import LerpFunc from panda3d.core import CardMaker, NodePath, TextNode, TransparencyAttrib -import pooltool.ani.tasks as tasks import pooltool.ani.utils as autils +from pooltool.ani import tasks from pooltool.ani.constants import ( logo_paths, max_stroke_speed, @@ -475,10 +475,8 @@ def set(self, V0): self.text.setText(f"{V0:.2f} m/s") value = (V0 - min_stroke_speed) / (max_stroke_speed - min_stroke_speed) - if value < 0: - value = 0 - if value > 1: - value = 1 + value = max(value, 0) + value = min(value, 1) self.fg.setScale(value, 1, 1) self.bg.setScale(1.0 - value, 1, 1) diff --git a/pooltool/ani/image/__init__.py b/pooltool/ani/image/__init__.py index 6849464b..cf1fdd4f 100644 --- a/pooltool/ani/image/__init__.py +++ b/pooltool/ani/image/__init__.py @@ -14,16 +14,16 @@ from pooltool.ani.image.utils import ImageExt, gif, rgb2gray __all__ = [ - "save_images", - "image_stack", + "GzipArrayImages", + "HDF5Images", "ImageExt", + "ImageStorageMethod", "ImageZip", - "HDF5Images", - "GzipArrayImages", "NpyImages", + "get_graphics_texture", "gif", - "rgb2gray", "image_array_from_texture", - "get_graphics_texture", - "ImageStorageMethod", + "image_stack", + "rgb2gray", + "save_images", ] diff --git a/pooltool/ani/menu/__init__.py b/pooltool/ani/menu/__init__.py index 87a4611a..f5443c66 100644 --- a/pooltool/ani/menu/__init__.py +++ b/pooltool/ani/menu/__init__.py @@ -8,6 +8,6 @@ MenuRegistry.register(SettingsMenu) __all__ = [ - "MenuRegistry", "MenuNavigator", + "MenuRegistry", ] diff --git a/pooltool/ani/menu/_datatypes.py b/pooltool/ani/menu/_datatypes.py index b1d8da69..a4fccb4a 100644 --- a/pooltool/ani/menu/_datatypes.py +++ b/pooltool/ani/menu/_datatypes.py @@ -28,8 +28,8 @@ Vec4, ) -import pooltool.ani.tasks as tasks import pooltool.ani.utils as autils +from pooltool.ani import tasks from pooltool.ani.constants import logo_paths, model_dir from pooltool.ani.fonts import load_font from pooltool.ani.globals import Global diff --git a/pooltool/ani/modes/__init__.py b/pooltool/ani/modes/__init__.py index 6e43e1cf..1a95e70a 100644 --- a/pooltool/ani/modes/__init__.py +++ b/pooltool/ani/modes/__init__.py @@ -19,8 +19,6 @@ __all__ = [ - "Mode", - "ModeManager", "AimMode", "BallInHandMode", "CalculateMode", @@ -29,6 +27,8 @@ "CamSaveMode", "GameOverMode", "MenuMode", + "Mode", + "ModeManager", "PickBallMode", "PurgatoryMode", "ShotMode", diff --git a/pooltool/ani/modes/aim.py b/pooltool/ani/modes/aim.py index 477f4fc1..a75234c3 100644 --- a/pooltool/ani/modes/aim.py +++ b/pooltool/ani/modes/aim.py @@ -2,7 +2,7 @@ import numpy as np -import pooltool.ani.tasks as tasks +from pooltool.ani import tasks from pooltool.ani.action import Action from pooltool.ani.camera import cam from pooltool.ani.collision import cue_avoid @@ -203,10 +203,8 @@ def aim_apply_power(self): dy = mouse.get_dy() V0 = multisystem.active.cue.V0 + dy * power_sensitivity - if V0 < min_stroke_speed: - V0 = min_stroke_speed - if V0 > max_stroke_speed: - V0 = max_stroke_speed + V0 = max(V0, min_stroke_speed) + V0 = min(V0, max_stroke_speed) multisystem.active.cue.set_state(V0=V0) self._update_hud() diff --git a/pooltool/ani/modes/ball_in_hand.py b/pooltool/ani/modes/ball_in_hand.py index 6a4bdc7f..2952a0fd 100644 --- a/pooltool/ani/modes/ball_in_hand.py +++ b/pooltool/ani/modes/ball_in_hand.py @@ -4,10 +4,10 @@ from direct.interval.IntervalGlobal import Parallel from panda3d.core import TransparencyAttrib -import pooltool.ani.tasks as tasks import pooltool.ani.utils as autils import pooltool.constants as c -import pooltool.ptmath as ptmath +from pooltool import ptmath +from pooltool.ani import tasks from pooltool.ani.action import Action from pooltool.ani.camera import cam from pooltool.ani.constants import ball_highlight diff --git a/pooltool/ani/modes/calculate.py b/pooltool/ani/modes/calculate.py index cc56b8f8..eb73dab0 100644 --- a/pooltool/ani/modes/calculate.py +++ b/pooltool/ani/modes/calculate.py @@ -1,7 +1,7 @@ #! /usr/bin/env python -import pooltool.ani.tasks as tasks import pooltool.ani.utils as autils +from pooltool.ani import tasks from pooltool.ani.action import Action from pooltool.ani.camera import cam from pooltool.ani.constants import rotate_downtime diff --git a/pooltool/ani/modes/call_shot.py b/pooltool/ani/modes/call_shot.py index 281d168a..65c34e1e 100755 --- a/pooltool/ani/modes/call_shot.py +++ b/pooltool/ani/modes/call_shot.py @@ -5,10 +5,10 @@ from direct.interval.IntervalGlobal import LerpFunc, Parallel from panda3d.core import TransparencyAttrib -import pooltool.ani.tasks as tasks import pooltool.ani.utils as autils import pooltool.constants as c -import pooltool.ptmath as ptmath +from pooltool import ptmath +from pooltool.ani import tasks from pooltool.ani.action import Action from pooltool.ani.camera import cam from pooltool.ani.constants import ball_highlight diff --git a/pooltool/ani/modes/cam_load.py b/pooltool/ani/modes/cam_load.py index bb853843..c41fa7ee 100644 --- a/pooltool/ani/modes/cam_load.py +++ b/pooltool/ani/modes/cam_load.py @@ -2,8 +2,8 @@ from direct.gui.DirectGui import DGG -import pooltool.ani.tasks as tasks import pooltool.ani.utils as autils +from pooltool.ani import tasks from pooltool.ani.action import Action from pooltool.ani.camera import cam from pooltool.ani.globals import Global diff --git a/pooltool/ani/modes/cam_save.py b/pooltool/ani/modes/cam_save.py index 0ac7db3d..425f990d 100644 --- a/pooltool/ani/modes/cam_save.py +++ b/pooltool/ani/modes/cam_save.py @@ -2,8 +2,8 @@ from direct.gui.DirectGui import DGG -import pooltool.ani.tasks as tasks import pooltool.ani.utils as autils +from pooltool.ani import tasks from pooltool.ani.action import Action from pooltool.ani.camera import cam from pooltool.ani.globals import Global diff --git a/pooltool/ani/modes/datatypes.py b/pooltool/ani/modes/datatypes.py index c97408b4..2ed64413 100644 --- a/pooltool/ani/modes/datatypes.py +++ b/pooltool/ani/modes/datatypes.py @@ -2,7 +2,7 @@ import pdb from abc import ABC, abstractmethod -import pooltool.ani.tasks as tasks +from pooltool.ani import tasks from pooltool.ani.action import Action from pooltool.ani.globals import Global, require_showbase from pooltool.system.datatypes import multisystem diff --git a/pooltool/ani/modes/menu.py b/pooltool/ani/modes/menu.py index 92465418..672adef0 100644 --- a/pooltool/ani/modes/menu.py +++ b/pooltool/ani/modes/menu.py @@ -2,7 +2,7 @@ import sys -import pooltool.ani.tasks as tasks +from pooltool.ani import tasks from pooltool.ani.action import Action from pooltool.ani.globals import Global from pooltool.ani.menu import MenuRegistry diff --git a/pooltool/ani/modes/pick_ball.py b/pooltool/ani/modes/pick_ball.py index ed1eb294..e5cf70bb 100644 --- a/pooltool/ani/modes/pick_ball.py +++ b/pooltool/ani/modes/pick_ball.py @@ -3,9 +3,9 @@ import numpy as np -import pooltool.ani.tasks as tasks import pooltool.constants as c -import pooltool.ptmath as ptmath +from pooltool import ptmath +from pooltool.ani import tasks from pooltool.ani.action import Action from pooltool.ani.camera import cam from pooltool.ani.constants import ball_highlight diff --git a/pooltool/ani/modes/purgatory.py b/pooltool/ani/modes/purgatory.py index 63defb1b..7c7d3659 100644 --- a/pooltool/ani/modes/purgatory.py +++ b/pooltool/ani/modes/purgatory.py @@ -1,7 +1,7 @@ #! /usr/bin/env python -import pooltool.ani.tasks as tasks import pooltool.ani.utils as autils +from pooltool.ani import tasks from pooltool.ani.action import Action from pooltool.ani.globals import Global from pooltool.ani.modes.datatypes import BaseMode, Mode diff --git a/pooltool/ani/modes/shot.py b/pooltool/ani/modes/shot.py index 85f5802e..29ec5239 100755 --- a/pooltool/ani/modes/shot.py +++ b/pooltool/ani/modes/shot.py @@ -1,7 +1,7 @@ #! /usr/bin/env python -import pooltool.ani.tasks as tasks +from pooltool.ani import tasks from pooltool.ani.action import Action from pooltool.ani.camera import cam from pooltool.ani.collision import cue_avoid diff --git a/pooltool/ani/modes/stroke.py b/pooltool/ani/modes/stroke.py index 5e391449..3ba35072 100644 --- a/pooltool/ani/modes/stroke.py +++ b/pooltool/ani/modes/stroke.py @@ -1,7 +1,7 @@ #! /usr/bin/env python -import pooltool.ani.tasks as tasks import pooltool.ani.utils as autils +from pooltool.ani import tasks from pooltool.ani.action import Action from pooltool.ani.camera import cam from pooltool.ani.constants import ( diff --git a/pooltool/ani/modes/view.py b/pooltool/ani/modes/view.py index 31411a0f..d3dd5240 100755 --- a/pooltool/ani/modes/view.py +++ b/pooltool/ani/modes/view.py @@ -2,7 +2,7 @@ import numpy as np -import pooltool.ani.tasks as tasks +from pooltool.ani import tasks from pooltool.ani.action import Action from pooltool.ani.camera import cam from pooltool.ani.collision import cue_avoid @@ -165,10 +165,8 @@ def view_apply_power(self): dy = mouse.get_dy() V0 = multisystem.active.cue.V0 + dy * power_sensitivity - if V0 < min_stroke_speed: - V0 = min_stroke_speed - if V0 > max_stroke_speed: - V0 = max_stroke_speed + V0 = max(V0, min_stroke_speed) + V0 = min(V0, max_stroke_speed) multisystem.active.cue.set_state(V0=V0) self._update_hud() diff --git a/pooltool/ani/utils.py b/pooltool/ani/utils.py index 2005386b..ac9d6d86 100644 --- a/pooltool/ani/utils.py +++ b/pooltool/ani/utils.py @@ -17,7 +17,7 @@ Vec4, ) -import pooltool.ptmath as ptmath +from pooltool import ptmath from pooltool.ani.fonts import load_font from pooltool.ani.globals import Global diff --git a/pooltool/events/__init__.py b/pooltool/events/__init__.py index 1405b0b4..5232da4a 100644 --- a/pooltool/events/__init__.py +++ b/pooltool/events/__init__.py @@ -29,26 +29,26 @@ ) __all__ = [ - "filter_ball", - "filter_time", - "filter_type", - "filter_events", - "by_type", - "by_ball", - "by_time", - "null_event", + "Agent", + "AgentType", + "Event", + "EventType", "ball_ball_collision", - "ball_linear_cushion_collision", "ball_circular_cushion_collision", + "ball_linear_cushion_collision", "ball_pocket_collision", - "stick_ball_collision", "ball_table_collision", - "spinning_stationary_transition", - "rolling_stationary_transition", + "by_ball", + "by_time", + "by_type", + "filter_ball", + "filter_events", + "filter_time", + "filter_type", + "null_event", "rolling_spinning_transition", + "rolling_stationary_transition", "sliding_rolling_transition", - "Event", - "EventType", - "AgentType", - "Agent", + "spinning_stationary_transition", + "stick_ball_collision", ] diff --git a/pooltool/events/filter.py b/pooltool/events/filter.py index 93a8b8e5..e3ba200e 100644 --- a/pooltool/events/filter.py +++ b/pooltool/events/filter.py @@ -96,9 +96,7 @@ def func(events: list[Event]) -> list[Event]: new: list[Event] = [] for event in events: - if after and event.time > t: - new.append(event) - elif not after and event.time < t: + if after and event.time > t or not after and event.time < t: new.append(event) return new diff --git a/pooltool/evolution/__init__.py b/pooltool/evolution/__init__.py index 3a98993b..ae7f2c16 100644 --- a/pooltool/evolution/__init__.py +++ b/pooltool/evolution/__init__.py @@ -7,6 +7,6 @@ __all__ = [ "SimulationEngine", "continuize", - "simulate", "interpolate_ball_states", + "simulate", ] diff --git a/pooltool/evolution/continuous.py b/pooltool/evolution/continuous.py index 07f7e8f3..c704a2db 100644 --- a/pooltool/evolution/continuous.py +++ b/pooltool/evolution/continuous.py @@ -8,9 +8,9 @@ import numpy as np from numpy.typing import NDArray -import pooltool.physics.evolve as evolve from pooltool.events import filter_ball from pooltool.objects.ball.datatypes import Ball, BallHistory, BallState +from pooltool.physics import evolve from pooltool.system.datatypes import System diff --git a/pooltool/evolution/event_based/detect/ball_ball.py b/pooltool/evolution/event_based/detect/ball_ball.py index df782764..ec967ef2 100644 --- a/pooltool/evolution/event_based/detect/ball_ball.py +++ b/pooltool/evolution/event_based/detect/ball_ball.py @@ -7,7 +7,7 @@ from numpy.typing import NDArray import pooltool.constants as const -import pooltool.ptmath as ptmath +from pooltool import ptmath from pooltool.events import Event, EventType, ball_ball_collision, null_event from pooltool.evolution.event_based.cache import CollisionCache from pooltool.evolution.event_based.detect.ball_position_polynomial import ( @@ -149,11 +149,13 @@ def get_next_ball_ball_event( ball2_state = ball2.state ball2_params = ball2.params - if ball1_state.s == const.pocketed or ball2_state.s == const.pocketed: - cache[ball_pair] = np.inf - elif ( - ball1_state.s in const.nontranslating - and ball2_state.s in const.nontranslating + if ( + ball1_state.s == const.pocketed + or ball2_state.s == const.pocketed + or ( + ball1_state.s in const.nontranslating + and ball2_state.s in const.nontranslating + ) ): cache[ball_pair] = np.inf elif ptmath.is_overlapping( diff --git a/pooltool/evolution/event_based/detect/ball_cushion.py b/pooltool/evolution/event_based/detect/ball_cushion.py index 713db1b9..8b76b96d 100644 --- a/pooltool/evolution/event_based/detect/ball_cushion.py +++ b/pooltool/evolution/event_based/detect/ball_cushion.py @@ -6,8 +6,7 @@ from numpy.typing import NDArray import pooltool.constants as const -import pooltool.physics.evolve as evolve -import pooltool.ptmath as ptmath +from pooltool import ptmath from pooltool.events import ( Event, EventType, @@ -24,6 +23,7 @@ ) from pooltool.objects.ball.datatypes import Ball from pooltool.objects.table.components import LinearCushionSegment +from pooltool.physics import evolve from pooltool.physics.utils import get_u_vec from pooltool.ptmath import quaternion_from_vector_to_vector from pooltool.ptmath.roots import ( @@ -205,8 +205,7 @@ def ball_vertical_plane_collision_time( if not (0 <= s_score <= 1): continue - if root.real < min_time: - min_time = root.real + min_time = min(min_time, root.real) return min_time diff --git a/pooltool/evolution/event_based/detect/ball_pocket.py b/pooltool/evolution/event_based/detect/ball_pocket.py index cf70444a..5cf61543 100644 --- a/pooltool/evolution/event_based/detect/ball_pocket.py +++ b/pooltool/evolution/event_based/detect/ball_pocket.py @@ -5,7 +5,7 @@ from numpy.typing import NDArray import pooltool.constants as const -import pooltool.ptmath as ptmath +from pooltool import ptmath from pooltool.events import Event, EventType, ball_pocket_collision, null_event from pooltool.evolution.event_based.cache import CollisionCache from pooltool.physics.utils import get_airborne_time, get_u_vec diff --git a/pooltool/evolution/event_based/detect/ball_position_polynomial.py b/pooltool/evolution/event_based/detect/ball_position_polynomial.py index 6efb9839..4f092cb5 100644 --- a/pooltool/evolution/event_based/detect/ball_position_polynomial.py +++ b/pooltool/evolution/event_based/detect/ball_position_polynomial.py @@ -3,7 +3,7 @@ from numpy.typing import NDArray import pooltool.constants as const -import pooltool.ptmath as ptmath +from pooltool import ptmath from pooltool.physics.utils import tangent_surface_velocity diff --git a/pooltool/evolution/event_based/detect/detector.py b/pooltool/evolution/event_based/detect/detector.py index 914f19e2..ce0257f3 100644 --- a/pooltool/evolution/event_based/detect/detector.py +++ b/pooltool/evolution/event_based/detect/detector.py @@ -3,7 +3,7 @@ import attrs import numpy as np -import pooltool.ptmath as ptmath +from pooltool import ptmath from pooltool.events import Event, EventType, null_event from pooltool.evolution.event_based.cache import CollisionCache, TransitionCache from pooltool.evolution.event_based.detect.ball_ball import ( diff --git a/pooltool/evolution/event_based/simulate.py b/pooltool/evolution/event_based/simulate.py index f82996e8..75ed10a7 100755 --- a/pooltool/evolution/event_based/simulate.py +++ b/pooltool/evolution/event_based/simulate.py @@ -5,13 +5,13 @@ import attrs import numpy as np -import pooltool.physics.evolve as evolve from pooltool.events import Event, EventType, null_event from pooltool.evolution.continuous import continuize from pooltool.evolution.engine import SimulationEngine from pooltool.evolution.event_based.cache import CollisionCache, TransitionCache from pooltool.evolution.event_based.config import INCLUDED_EVENTS from pooltool.objects.ball.datatypes import BallState +from pooltool.physics import evolve from pooltool.system.datatypes import System DEFAULT_ENGINE = SimulationEngine() diff --git a/pooltool/layouts.py b/pooltool/layouts.py index c0437579..428155a3 100755 --- a/pooltool/layouts.py +++ b/pooltool/layouts.py @@ -548,14 +548,14 @@ def get_rack( __all__ = [ - "DEFAULT_STANDARD_BALLSET", "DEFAULT_SNOOKER_BALLSET", - "DEFAULT_THREECUSH_BALLSET", + "DEFAULT_STANDARD_BALLSET", "DEFAULT_SUMTOTHREE_BALLSET", + "DEFAULT_THREECUSH_BALLSET", + "BallPos", "Dir", "Jump", "Pos", - "BallPos", "Translation", "ball_cluster_blueprint", "generate_layout", diff --git a/pooltool/objects/__init__.py b/pooltool/objects/__init__.py index 8526ddae..4458f074 100644 --- a/pooltool/objects/__init__.py +++ b/pooltool/objects/__init__.py @@ -34,28 +34,28 @@ ) __all__ = [ - "BallSet", "Ball", - "BallState", - "BallParams", - "PrebuiltBallParams", "BallHistory", "BallOrientation", - "CueSpecs", - "PrebuiltCueSpecs", - "Cue", - "Pocket", - "LinearCushionSegment", + "BallParams", + "BallSet", + "BallState", + "BilliardTableSpecs", "CircularCushionSegment", - "CushionSegments", + "Cue", + "CueSpecs", "CushionDirection", + "CushionSegments", + "LinearCushionSegment", + "Pocket", + "PocketTableSpecs", + "PrebuiltBallParams", + "PrebuiltCueSpecs", + "SnookerTableSpecs", "Table", "TableModelDescr", - "TableType", "TableName", - "PocketTableSpecs", - "BilliardTableSpecs", - "SnookerTableSpecs", + "TableType", "get_ballset", "get_ballset_names", ] diff --git a/pooltool/objects/ball/datatypes.py b/pooltool/objects/ball/datatypes.py index 43f2e01c..bec5caa0 100644 --- a/pooltool/objects/ball/datatypes.py +++ b/pooltool/objects/ball/datatypes.py @@ -9,7 +9,7 @@ from numpy.typing import NDArray import pooltool.constants as c -import pooltool.ptmath as ptmath +from pooltool import ptmath from pooltool.objects.ball.params import BallParams from pooltool.objects.ball.sets import BallSet from pooltool.serialize import SerializeFormat, conversion diff --git a/pooltool/objects/ball/render.py b/pooltool/objects/ball/render.py index 78ba44e0..2cc4a64a 100644 --- a/pooltool/objects/ball/render.py +++ b/pooltool/objects/ball/render.py @@ -15,9 +15,9 @@ TransparencyAttrib, ) -import pooltool.ani.tasks as tasks import pooltool.ani.utils as autils import pooltool.constants as c +from pooltool.ani import tasks from pooltool.ani.globals import Global from pooltool.config import settings from pooltool.objects.ball.datatypes import Ball, BallHistory, BallOrientation diff --git a/pooltool/objects/cue/render.py b/pooltool/objects/cue/render.py index ea6e0c28..3558ac13 100644 --- a/pooltool/objects/cue/render.py +++ b/pooltool/objects/cue/render.py @@ -2,7 +2,7 @@ from direct.interval.IntervalGlobal import LerpPosInterval, Sequence from panda3d.core import ClockObject, CollisionNode, CollisionSegment, Vec3 -import pooltool.utils as utils +from pooltool import utils from pooltool.ani.constants import model_dir from pooltool.ani.globals import Global from pooltool.config import settings diff --git a/pooltool/objects/table/components.py b/pooltool/objects/table/components.py index 64f98d73..e2976ff3 100644 --- a/pooltool/objects/table/components.py +++ b/pooltool/objects/table/components.py @@ -10,7 +10,7 @@ from attrs import define, evolve, field from numpy.typing import NDArray -import pooltool.ptmath as ptmath +from pooltool import ptmath from pooltool.utils.dataclasses import are_dataclasses_equal diff --git a/pooltool/objects/table/datatypes.py b/pooltool/objects/table/datatypes.py index 04cf7104..09ceac62 100644 --- a/pooltool/objects/table/datatypes.py +++ b/pooltool/objects/table/datatypes.py @@ -106,7 +106,7 @@ def w(self) -> float: return x2 - x1 @property - def l(self) -> float: # noqa F743 + def l(self) -> float: """The length of the table. Warning: diff --git a/pooltool/objects/table/specs.py b/pooltool/objects/table/specs.py index 07c6a84a..f021e6a0 100755 --- a/pooltool/objects/table/specs.py +++ b/pooltool/objects/table/specs.py @@ -101,7 +101,7 @@ class PocketTableSpecs: """ # 7-foot table (78x39 in^2 playing surface) - l: float = field(default=1.9812) # noqa E741 + l: float = field(default=1.9812) w: float = field(default=1.9812 / 2) cushion_width: float = field(default=2 * 2.54 / 100) @@ -173,7 +173,7 @@ class SnookerTableSpecs: # https://wpbsa.com/rules/ # The playing area is within the cushion faces and shall measure # 11 ft 8½ in x 5 ft 10 in (3569 mm x 1778 mm) with a tolerance on both dimensions of +/- ½ in (13 mm). - l: float = field(default=3.5445) # noqa E741 + l: float = field(default=3.5445) w: float = field(default=1.7465) cushion_width: float = field(default=1.55 * 25.4 / 1000) diff --git a/pooltool/physics/evolve/__init__.py b/pooltool/physics/evolve/__init__.py index ec1dbac7..e1e19a03 100644 --- a/pooltool/physics/evolve/__init__.py +++ b/pooltool/physics/evolve/__init__.py @@ -15,7 +15,7 @@ from numpy.typing import NDArray import pooltool.constants as const -import pooltool.ptmath as ptmath +from pooltool import ptmath from pooltool.physics.utils import ( get_roll_time, get_slide_time, diff --git a/pooltool/physics/resolve/__init__.py b/pooltool/physics/resolve/__init__.py index 315a52a0..ff5d95b2 100644 --- a/pooltool/physics/resolve/__init__.py +++ b/pooltool/physics/resolve/__init__.py @@ -75,6 +75,6 @@ def display_models(): __all__ = [ - "Resolver", "RESOLVER_PATH", + "Resolver", ] diff --git a/pooltool/physics/resolve/ball_ball/core.py b/pooltool/physics/resolve/ball_ball/core.py index 49f8db67..5746e622 100644 --- a/pooltool/physics/resolve/ball_ball/core.py +++ b/pooltool/physics/resolve/ball_ball/core.py @@ -4,7 +4,7 @@ import numpy as np import pooltool.constants as const -import pooltool.ptmath as ptmath +from pooltool import ptmath from pooltool.objects.ball.datatypes import Ball from pooltool.physics.dimensionality import Dim diff --git a/pooltool/physics/resolve/ball_ball/friction.py b/pooltool/physics/resolve/ball_ball/friction.py index ffe4360e..1c1ef372 100644 --- a/pooltool/physics/resolve/ball_ball/friction.py +++ b/pooltool/physics/resolve/ball_ball/friction.py @@ -3,7 +3,7 @@ import attrs -import pooltool.ptmath as ptmath +from pooltool import ptmath from pooltool.objects.ball.datatypes import Ball from pooltool.physics.utils import tangent_surface_velocity from pooltool.utils.strenum import StrEnum, auto diff --git a/pooltool/physics/resolve/ball_ball/frictional_inelastic/__init__.py b/pooltool/physics/resolve/ball_ball/frictional_inelastic/__init__.py index df08d381..a0cb51cb 100644 --- a/pooltool/physics/resolve/ball_ball/frictional_inelastic/__init__.py +++ b/pooltool/physics/resolve/ball_ball/frictional_inelastic/__init__.py @@ -3,7 +3,7 @@ from numba import jit import pooltool.constants as const -import pooltool.ptmath as ptmath +from pooltool import ptmath from pooltool.objects.ball.datatypes import Ball, BallState from pooltool.physics.dimensionality import Dim from pooltool.physics.resolve.ball_ball.core import CoreBallBallCollision diff --git a/pooltool/physics/resolve/ball_ball/frictionless_elastic/__init__.py b/pooltool/physics/resolve/ball_ball/frictionless_elastic/__init__.py index 5ae5e8f8..9c343984 100644 --- a/pooltool/physics/resolve/ball_ball/frictionless_elastic/__init__.py +++ b/pooltool/physics/resolve/ball_ball/frictionless_elastic/__init__.py @@ -2,7 +2,7 @@ import numpy as np import pooltool.constants as const -import pooltool.ptmath as ptmath +from pooltool import ptmath from pooltool.objects.ball.datatypes import Ball, BallState from pooltool.physics.dimensionality import Dim from pooltool.physics.resolve.ball_ball.core import CoreBallBallCollision diff --git a/pooltool/physics/resolve/ball_cushion/core.py b/pooltool/physics/resolve/ball_cushion/core.py index 3d4a89bb..c0966ae8 100644 --- a/pooltool/physics/resolve/ball_cushion/core.py +++ b/pooltool/physics/resolve/ball_cushion/core.py @@ -4,7 +4,7 @@ import numpy as np import pooltool.constants as const -import pooltool.ptmath as ptmath +from pooltool import ptmath from pooltool.objects.ball.datatypes import Ball from pooltool.objects.table.components import ( CircularCushionSegment, diff --git a/pooltool/physics/resolve/ball_cushion/han_2005/model.py b/pooltool/physics/resolve/ball_cushion/han_2005/model.py index bce3f30a..35a091d6 100644 --- a/pooltool/physics/resolve/ball_cushion/han_2005/model.py +++ b/pooltool/physics/resolve/ball_cushion/han_2005/model.py @@ -2,7 +2,7 @@ import numpy as np import pooltool.constants as const -import pooltool.ptmath as ptmath +from pooltool import ptmath from pooltool.objects.ball.datatypes import Ball, BallState from pooltool.objects.table.components import ( CircularCushionSegment, diff --git a/pooltool/physics/resolve/ball_cushion/han_2005/properties.py b/pooltool/physics/resolve/ball_cushion/han_2005/properties.py index 1b205811..afbe2329 100644 --- a/pooltool/physics/resolve/ball_cushion/han_2005/properties.py +++ b/pooltool/physics/resolve/ball_cushion/han_2005/properties.py @@ -1,7 +1,7 @@ import numpy as np from numpy.typing import NDArray -import pooltool.ptmath as ptmath +from pooltool import ptmath def get_ball_cushion_restitution(rvw: NDArray[np.float64], e_c: float): diff --git a/pooltool/physics/resolve/ball_cushion/mathavan_2010/__init__.py b/pooltool/physics/resolve/ball_cushion/mathavan_2010/__init__.py index 4ad97e14..a9e75949 100644 --- a/pooltool/physics/resolve/ball_cushion/mathavan_2010/__init__.py +++ b/pooltool/physics/resolve/ball_cushion/mathavan_2010/__init__.py @@ -4,6 +4,6 @@ ) __all__ = [ - "Mathavan2010Linear", "Mathavan2010Circular", + "Mathavan2010Linear", ] diff --git a/pooltool/physics/resolve/ball_cushion/mathavan_2010/model.py b/pooltool/physics/resolve/ball_cushion/mathavan_2010/model.py index b3147358..5b1fe19c 100644 --- a/pooltool/physics/resolve/ball_cushion/mathavan_2010/model.py +++ b/pooltool/physics/resolve/ball_cushion/mathavan_2010/model.py @@ -5,7 +5,7 @@ from numba import jit import pooltool.constants as const -import pooltool.ptmath as ptmath +from pooltool import ptmath from pooltool.objects.ball.datatypes import Ball, BallState from pooltool.objects.table.components import ( CircularCushionSegment, diff --git a/pooltool/physics/resolve/ball_cushion/stronge_compliant/model.py b/pooltool/physics/resolve/ball_cushion/stronge_compliant/model.py index e6cd552a..ab71720b 100644 --- a/pooltool/physics/resolve/ball_cushion/stronge_compliant/model.py +++ b/pooltool/physics/resolve/ball_cushion/stronge_compliant/model.py @@ -4,7 +4,7 @@ import numpy as np import pooltool.constants as const -import pooltool.ptmath as ptmath +from pooltool import ptmath from pooltool.objects.ball.datatypes import Ball, BallState from pooltool.objects.table.components import ( CircularCushionSegment, diff --git a/pooltool/physics/resolve/ball_cushion/unrealistic/__init__.py b/pooltool/physics/resolve/ball_cushion/unrealistic/__init__.py index 5c457882..7993421e 100644 --- a/pooltool/physics/resolve/ball_cushion/unrealistic/__init__.py +++ b/pooltool/physics/resolve/ball_cushion/unrealistic/__init__.py @@ -4,7 +4,7 @@ import numpy as np import pooltool.constants as const -import pooltool.ptmath as ptmath +from pooltool import ptmath from pooltool.objects.ball.datatypes import Ball from pooltool.objects.table.components import ( CircularCushionSegment, diff --git a/pooltool/physics/resolve/ball_table/frictional_inelastic/__init__.py b/pooltool/physics/resolve/ball_table/frictional_inelastic/__init__.py index 813c3ad7..d9ac20bd 100644 --- a/pooltool/physics/resolve/ball_table/frictional_inelastic/__init__.py +++ b/pooltool/physics/resolve/ball_table/frictional_inelastic/__init__.py @@ -4,8 +4,7 @@ from numpy.typing import NDArray import pooltool.constants as const -import pooltool.physics as physics -import pooltool.ptmath as ptmath +from pooltool import physics, ptmath from pooltool.objects.ball.datatypes import Ball, BallState from pooltool.physics.resolve.ball_table.core import ( CoreBallTableCollision, diff --git a/pooltool/physics/resolve/sphere_half_space_collision.py b/pooltool/physics/resolve/sphere_half_space_collision.py index 3321680f..fe1b6fa0 100644 --- a/pooltool/physics/resolve/sphere_half_space_collision.py +++ b/pooltool/physics/resolve/sphere_half_space_collision.py @@ -3,7 +3,7 @@ from numba import jit import pooltool.constants as const -import pooltool.ptmath as ptmath +from pooltool import ptmath from pooltool.physics.utils import tangent_surface_velocity diff --git a/pooltool/physics/resolve/stick_ball/instantaneous_point/__init__.py b/pooltool/physics/resolve/stick_ball/instantaneous_point/__init__.py index db227a49..ac168bc5 100644 --- a/pooltool/physics/resolve/stick_ball/instantaneous_point/__init__.py +++ b/pooltool/physics/resolve/stick_ball/instantaneous_point/__init__.py @@ -1,7 +1,7 @@ import attrs import numpy as np -import pooltool.ptmath as ptmath +from pooltool import ptmath from pooltool.objects.ball.datatypes import Ball, BallState from pooltool.objects.cue.datatypes import Cue from pooltool.physics.dimensionality import Dim diff --git a/pooltool/physics/resolve/stronge_compliant.py b/pooltool/physics/resolve/stronge_compliant.py index ef6c6d2f..157467e4 100644 --- a/pooltool/physics/resolve/stronge_compliant.py +++ b/pooltool/physics/resolve/stronge_compliant.py @@ -365,7 +365,7 @@ def f(t): return t_c t_slip = sp.optimize.toms748(f, t_c, t_f) - assert t_c <= t_slip and t_slip <= t_f, f"t_c={t_c} <= t_slip={t_slip} <= t_f={t_f}" + assert t_c <= t_slip <= t_f, f"t_c={t_c} <= t_slip={t_slip} <= t_f={t_f}" return t_slip @@ -404,7 +404,7 @@ def f(t): return t_f t_slip = sp.optimize.toms748(f, t_c, t_f) - assert t_stick <= t_slip and t_slip <= t_f, ( + assert t_stick <= t_slip <= t_f, ( f"t_stick={t_stick} <= t_slip={t_slip} <= t_f={t_f}" ) return t_slip @@ -418,23 +418,25 @@ def nondimensional_stick_time_for_initial_slip( e_n: float, eta_squared: float, ) -> float: - assert mu * eta_squared <= v_t_0_by_v_n_0 and v_t_0_by_v_n_0 <= mu * ( - (1 + e_n) * beta_t_by_beta_n - eta_squared / e_n + assert ( + mu * eta_squared + <= v_t_0_by_v_n_0 + <= mu * ((1 + e_n) * beta_t_by_beta_n - eta_squared / e_n) ) if v_t_0_by_v_n_0 <= mu * beta_t_by_beta_n: x = ((v_t_0_by_v_n_0 / mu) - beta_t_by_beta_n) / ( eta_squared - beta_t_by_beta_n ) - assert -1 <= x and x <= 1, f"x={x}" + assert -1 <= x <= 1, f"x={x}" result = (2 / math.pi) * math.acos(x) - assert 0 <= result and result <= 1, f"result={result}" + assert 0 <= result <= 1, f"result={result}" else: x = ((v_t_0_by_v_n_0 / mu) - beta_t_by_beta_n) / ( eta_squared / e_n - e_n * beta_t_by_beta_n ) - assert -1 <= x and x <= 1, f"x={x}" + assert -1 <= x <= 1, f"x={x}" result = (2 / math.pi) * (math.acos(x) - t_c_shift(e_n)) * e_n - assert 1 <= result and result <= (1 + e_n), f"result={result}, e_n={e_n}" + assert 1 <= result <= (1 + e_n), f"result={result}, e_n={e_n}" return result diff --git a/pooltool/ptmath/__init__.py b/pooltool/ptmath/__init__.py index 5f7ed085..6cdbbc1d 100644 --- a/pooltool/ptmath/__init__.py +++ b/pooltool/ptmath/__init__.py @@ -1,6 +1,6 @@ """Math functions""" -import pooltool.ptmath.roots as roots +from pooltool.ptmath import roots from pooltool.ptmath.utils import ( angle, angle_between_vectors, @@ -25,25 +25,25 @@ ) __all__ = [ - "roots", "angle", "angle_between_vectors", + "are_points_on_same_side", + "convert_2D_to_3D", "coordinate_rotation", "cross", "decompose_normal_tangent", - "squared_norm3d", + "find_intersection_2D", + "is_overlapping", + "norm2d", "norm3d", + "point_on_line_closest_to_point", + "quaternion_from_vector_to_vector", + "roots", + "rotation_from_vector_to_vector", "solve_transcendental", - "convert_2D_to_3D", "squared_norm2d", - "norm2d", - "point_on_line_closest_to_point", - "find_intersection_2D", - "are_points_on_same_side", + "squared_norm3d", "unit_vector", "unit_vector_slow", "wiggle", - "rotation_from_vector_to_vector", - "quaternion_from_vector_to_vector", - "is_overlapping", ] diff --git a/pooltool/ptmath/roots/__init__.py b/pooltool/ptmath/roots/__init__.py index f154ac27..cc6a8599 100644 --- a/pooltool/ptmath/roots/__init__.py +++ b/pooltool/ptmath/roots/__init__.py @@ -1,5 +1,4 @@ -import pooltool.ptmath.roots.quadratic as quadratic -import pooltool.ptmath.roots.quartic as quartic +from pooltool.ptmath.roots import quadratic, quartic from pooltool.ptmath.roots.core import ( get_real_positive_smallest_root, get_real_positive_smallest_roots, @@ -7,9 +6,9 @@ ) __all__ = [ - "quadratic", - "quartic", - "is_real_number", "get_real_positive_smallest_root", "get_real_positive_smallest_roots", + "is_real_number", + "quadratic", + "quartic", ] diff --git a/pooltool/ptmath/roots/_quartic_numba.py b/pooltool/ptmath/roots/_quartic_numba.py index 7a405f44..800bdd7d 100644 --- a/pooltool/ptmath/roots/_quartic_numba.py +++ b/pooltool/ptmath/roots/_quartic_numba.py @@ -193,8 +193,7 @@ def oqs_calc_phi0(a, b, c, d, scaled): maxtt = abs(xxx) else: maxtt = abs(gx) - if abs(h) > maxtt: - maxtt = abs(h) + maxtt = max(maxtt, abs(h)) if abs(f) > macheps * maxtt: for iter in range(8): diff --git a/pooltool/ruleset/__init__.py b/pooltool/ruleset/__init__.py index 336968fe..091e0f92 100755 --- a/pooltool/ruleset/__init__.py +++ b/pooltool/ruleset/__init__.py @@ -62,25 +62,25 @@ def get_ruleset(game: GameType, enforce_rules: bool = True) -> type[Ruleset]: __all__ = [ "AIPlayer", - "Player", "BallInHandOptions", + "Player", + "Ruleset", "ShotConstraints", "ShotInfo", - "Ruleset", - "get_ruleset", + "balls_that_hit_cushion", + "get_ball_ids_on_table", + "get_highest_ball", + "get_id_of_first_ball_hit", + "get_lowest_ball", "get_pocketed_ball_ids", "get_pocketed_ball_ids_during_shot", - "get_id_of_first_ball_hit", + "get_ruleset", + "is_ball_hit", "is_ball_pocketed", "is_ball_pocketed_in_pocket", - "is_target_group_hit_first", - "respot", - "get_ball_ids_on_table", - "get_lowest_ball", - "get_highest_ball", "is_lowest_hit_first", - "balls_that_hit_cushion", - "is_ball_hit", "is_numbered_ball_pocketed", "is_shot_called_if_required", + "is_target_group_hit_first", + "respot", ] diff --git a/pooltool/ruleset/datatypes.py b/pooltool/ruleset/datatypes.py index bbf21705..c1b59576 100644 --- a/pooltool/ruleset/datatypes.py +++ b/pooltool/ruleset/datatypes.py @@ -137,9 +137,7 @@ def can_shoot(self) -> bool: self.call_shot and self.ball_call is not None and self.pocket_call is not None - ): - return True - elif not self.call_shot: + ) or not self.call_shot: return True else: return False @@ -324,4 +322,3 @@ def copy(self) -> Ruleset: def copy(self): return self """ - pass diff --git a/pooltool/serialize/__init__.py b/pooltool/serialize/__init__.py index 7e24cbb5..47700f62 100644 --- a/pooltool/serialize/__init__.py +++ b/pooltool/serialize/__init__.py @@ -55,13 +55,13 @@ __all__ = [ "Convert", - "conversion", + "Pathish", "SerializeFormat", - "to_json", - "to_msgpack", - "to_yaml", + "conversion", "from_json", "from_msgpack", "from_yaml", - "Pathish", + "to_json", + "to_msgpack", + "to_yaml", ] diff --git a/pooltool/system/__init__.py b/pooltool/system/__init__.py index 2da2924b..12034589 100644 --- a/pooltool/system/__init__.py +++ b/pooltool/system/__init__.py @@ -4,8 +4,8 @@ from pooltool.system.render import SystemRender __all__ = [ - "System", "MultiSystem", - "multisystem", + "System", "SystemRender", + "multisystem", ] diff --git a/pooltool/system/datatypes.py b/pooltool/system/datatypes.py index ce6b8374..7c552f13 100644 --- a/pooltool/system/datatypes.py +++ b/pooltool/system/datatypes.py @@ -9,7 +9,7 @@ from attrs import define, field import pooltool.constants as const -import pooltool.ptmath as ptmath +from pooltool import ptmath from pooltool.events import Event from pooltool.objects.ball.datatypes import Ball, BallHistory from pooltool.objects.ball.sets import BallSet diff --git a/pooltool/utils/strenum.py b/pooltool/utils/strenum.py index a2c79653..f5490b4d 100644 --- a/pooltool/utils/strenum.py +++ b/pooltool/utils/strenum.py @@ -3,7 +3,9 @@ from enum import Enum, auto from typing import Any, TypeVar -__all__ = ["auto", "StrEnum"] +from typing_extensions import Self + +__all__ = ["StrEnum", "auto"] _S = TypeVar("_S", bound="StrEnum") @@ -13,7 +15,7 @@ class StrEnum(str, Enum): Enum where members are also (and must be) strings """ - def __new__(cls: type[_S], *values: str) -> _S: + def __new__(cls, *values: str) -> Self: if len(values) > 3: raise TypeError(f"too many arguments for str(): {values!r}") if len(values) == 1: diff --git a/sandbox/arena.py b/sandbox/arena.py index c866ccd7..8e8ce408 100644 --- a/sandbox/arena.py +++ b/sandbox/arena.py @@ -5,7 +5,7 @@ import pooltool as pt -get_pos = lambda table, ball: ( # noqa E731 +get_pos = lambda table, ball: ( (table.w - 2 * ball.params.R) * np.random.rand() + ball.params.R, (table.l - 2 * ball.params.R) * np.random.rand() + ball.params.R, ball.params.R, diff --git a/sandbox/ball_ball_collisions.py b/sandbox/ball_ball_collisions.py index b718bb16..90d17ca6 100644 --- a/sandbox/ball_ball_collisions.py +++ b/sandbox/ball_ball_collisions.py @@ -5,7 +5,7 @@ import plotly.graph_objects as go import plotly.io as pio -import pooltool.ptmath as ptmath +from pooltool import ptmath from pooltool.objects.ball.datatypes import Ball, BallParams from pooltool.physics.resolve.ball_ball.core import BallBallCollisionStrategy diff --git a/sandbox/ball_cushion_collisions.py b/sandbox/ball_cushion_collisions.py index efdf0f5b..bffd6920 100644 --- a/sandbox/ball_cushion_collisions.py +++ b/sandbox/ball_cushion_collisions.py @@ -8,7 +8,7 @@ import plotly.io as pio from numpy.typing import NDArray -import pooltool.ptmath as ptmath +from pooltool import ptmath from pooltool.objects.ball.datatypes import Ball, BallParams from pooltool.objects.table.components import LinearCushionSegment from pooltool.physics.resolve.ball_cushion.core import CoreBallLCushionCollision diff --git a/tests/evolution/event_based/test_ball_ball.py b/tests/evolution/event_based/test_ball_ball.py index f3b0986a..b38f424a 100644 --- a/tests/evolution/event_based/test_ball_ball.py +++ b/tests/evolution/event_based/test_ball_ball.py @@ -3,7 +3,7 @@ import pytest import pooltool.constants as const -import pooltool.ptmath as ptmath +from pooltool import ptmath from pooltool.events import EventType from pooltool.evolution.event_based.cache import CollisionCache from pooltool.evolution.event_based.detect.ball_ball import ( diff --git a/tests/evolution/event_based/test_simulate.py b/tests/evolution/event_based/test_simulate.py index 858dffaf..4e0c77ad 100644 --- a/tests/evolution/event_based/test_simulate.py +++ b/tests/evolution/event_based/test_simulate.py @@ -3,9 +3,7 @@ from numpy.typing import NDArray import pooltool.constants as const -import pooltool.physics as physics -import pooltool.ptmath as ptmath -from pooltool import aim, events +from pooltool import aim, events, physics, ptmath from pooltool.events import EventType, ball_ball_collision, ball_pocket_collision from pooltool.evolution.event_based._utils import _system_has_energy from pooltool.evolution.event_based.cache import CollisionCache diff --git a/tests/ptmath/test_ptmath.py b/tests/ptmath/test_ptmath.py index 8e432a78..2cce89f9 100644 --- a/tests/ptmath/test_ptmath.py +++ b/tests/ptmath/test_ptmath.py @@ -45,19 +45,19 @@ def test_are_points_on_same_side(): def test_transcendental_linear_equation(): - f = lambda x: x - 5 # noqa E731 + f = lambda x: x - 5 root = solve_transcendental(f, 0, 10) assert pytest.approx(root, 0.00001) == 5.0 def test_transcendental_nonlinear_equation(): - f = lambda x: x**2 - 4 * x + 3 # noqa E731 + f = lambda x: x**2 - 4 * x + 3 root = solve_transcendental(f, 0, 2.5) assert pytest.approx(root, 0.00001) == 1.0 def test_transcendental_no_root_error(): - f = lambda x: x**2 + 1 # noqa E731 + f = lambda x: x**2 + 1 with pytest.raises(ValueError): solve_transcendental(f, 0, 10) diff --git a/tests/test_layouts.py b/tests/test_layouts.py index 96934961..0fff9b63 100644 --- a/tests/test_layouts.py +++ b/tests/test_layouts.py @@ -7,7 +7,7 @@ import pytest from numpy.typing import NDArray -import pooltool.ptmath as ptmath +from pooltool import ptmath from pooltool.game.datatypes import GameType from pooltool.layouts import ( BallPos, diff --git a/uv.lock b/uv.lock index 83d45449..9cf6c771 100644 --- a/uv.lock +++ b/uv.lock @@ -382,7 +382,7 @@ resolution-markers = [ "python_full_version < '3.11' and sys_platform != 'darwin'", ] dependencies = [ - { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" } }, + { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/66/54/eb9bfc647b19f2009dd5c7f5ec51c4e6ca831725f1aea7a993034f483147/contourpy-1.3.2.tar.gz", hash = "sha256:b6945942715a034c671b7fc54f9588126b0b8bf23db2696e3ca8328f3ff0ab54", size = 13466130, upload-time = "2025-04-15T17:47:53.79Z" } wheels = [ @@ -459,7 +459,7 @@ resolution-markers = [ "python_full_version == '3.11.*' and sys_platform != 'darwin' and sys_platform != 'emscripten' and sys_platform != 'win32'", ] dependencies = [ - { name = "numpy", version = "2.3.5", source = { registry = "https://pypi.org/simple" } }, + { name = "numpy", version = "2.3.5", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/58/01/1253e6698a07380cd31a736d248a3f2a50a7c88779a1813da27503cadc2a/contourpy-1.3.3.tar.gz", hash = "sha256:083e12155b210502d0bca491432bb04d56dc3432f95a979b429f2848c3dbe880", size = 13466174, upload-time = "2025-07-26T12:03:12.549Z" } wheels = [ @@ -662,7 +662,7 @@ name = "exceptiongroup" version = "1.3.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "typing-extensions" }, + { name = "typing-extensions", marker = "python_full_version < '3.11'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/50/79/66800aadf48771f6b62f7eb014e352e5d06856655206165d775e675a02c9/exceptiongroup-1.3.1.tar.gz", hash = "sha256:8b412432c6055b0b7d14c310000ae93352ed6754f70fa8f7c34141f91c4e3219", size = 30371, upload-time = "2025-11-21T23:01:54.787Z" } wheels = [ @@ -926,17 +926,17 @@ resolution-markers = [ "python_full_version < '3.11' and sys_platform != 'darwin'", ] dependencies = [ - { name = "colorama", marker = "sys_platform == 'win32'" }, - { name = "decorator" }, - { name = "exceptiongroup" }, - { name = "jedi" }, - { name = "matplotlib-inline" }, - { name = "pexpect", marker = "sys_platform != 'emscripten' and sys_platform != 'win32'" }, - { name = "prompt-toolkit" }, - { name = "pygments" }, - { name = "stack-data" }, - { name = "traitlets" }, - { name = "typing-extensions" }, + { name = "colorama", marker = "python_full_version < '3.11' and sys_platform == 'win32'" }, + { name = "decorator", marker = "python_full_version < '3.11'" }, + { name = "exceptiongroup", marker = "python_full_version < '3.11'" }, + { name = "jedi", marker = "python_full_version < '3.11'" }, + { name = "matplotlib-inline", marker = "python_full_version < '3.11'" }, + { name = "pexpect", marker = "python_full_version < '3.11' and sys_platform != 'emscripten' and sys_platform != 'win32'" }, + { name = "prompt-toolkit", marker = "python_full_version < '3.11'" }, + { name = "pygments", marker = "python_full_version < '3.11'" }, + { name = "stack-data", marker = "python_full_version < '3.11'" }, + { name = "traitlets", marker = "python_full_version < '3.11'" }, + { name = "typing-extensions", marker = "python_full_version < '3.11'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/40/18/f8598d287006885e7136451fdea0755af4ebcbfe342836f24deefaed1164/ipython-8.39.0.tar.gz", hash = "sha256:4110ae96012c379b8b6db898a07e186c40a2a1ef5d57a7fa83166047d9da7624", size = 5513971, upload-time = "2026-03-27T10:02:13.94Z" } wheels = [ @@ -958,18 +958,18 @@ resolution-markers = [ "python_full_version == '3.11.*' and sys_platform != 'darwin' and sys_platform != 'emscripten' and sys_platform != 'win32'", ] dependencies = [ - { name = "colorama", marker = "sys_platform == 'win32'" }, - { name = "decorator" }, - { name = "ipython-pygments-lexers" }, - { name = "jedi" }, - { name = "matplotlib-inline" }, - { name = "pexpect", marker = "sys_platform != 'emscripten' and sys_platform != 'win32'" }, - { name = "prompt-toolkit" }, - { name = "psutil", marker = "sys_platform != 'cygwin' and sys_platform != 'emscripten'" }, - { name = "pygments" }, - { name = "stack-data" }, - { name = "traitlets" }, - { name = "typing-extensions", marker = "python_full_version < '3.12'" }, + { name = "colorama", marker = "python_full_version >= '3.11' and sys_platform == 'win32'" }, + { name = "decorator", marker = "python_full_version >= '3.11'" }, + { name = "ipython-pygments-lexers", marker = "python_full_version >= '3.11'" }, + { name = "jedi", marker = "python_full_version >= '3.11'" }, + { name = "matplotlib-inline", marker = "python_full_version >= '3.11'" }, + { name = "pexpect", marker = "python_full_version >= '3.11' and sys_platform != 'emscripten' and sys_platform != 'win32'" }, + { name = "prompt-toolkit", marker = "python_full_version >= '3.11'" }, + { name = "psutil", marker = "python_full_version >= '3.11' and sys_platform != 'cygwin' and sys_platform != 'emscripten'" }, + { name = "pygments", marker = "python_full_version >= '3.11'" }, + { name = "stack-data", marker = "python_full_version >= '3.11'" }, + { name = "traitlets", marker = "python_full_version >= '3.11'" }, + { name = "typing-extensions", marker = "python_full_version == '3.11.*'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/53/59/165d3b4d75cc34add3122c4417ecb229085140ac573103c223cd01dde96f/ipython-9.15.0.tar.gz", hash = "sha256:da2819ce2aa83135257df830660b1176d986c3d2876db24df01974fa955b2756", size = 4442580, upload-time = "2026-06-26T11:03:35.913Z" } wheels = [ @@ -981,7 +981,7 @@ name = "ipython-pygments-lexers" version = "1.1.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "pygments" }, + { name = "pygments", marker = "python_full_version >= '3.11'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/ef/4c/5dd1d8af08107f88c7f741ead7a40854b8ac24ddf9ae850afbcf698aa552/ipython_pygments_lexers-1.1.1.tar.gz", hash = "sha256:09c0138009e56b6854f9535736f4171d855c8c08a563a0dcd8022f78355c7e81", size = 8393, upload-time = "2025-01-17T11:24:34.505Z" } wheels = [ @@ -1469,15 +1469,15 @@ resolution-markers = [ "python_full_version < '3.11' and sys_platform != 'darwin'", ] dependencies = [ - { name = "contourpy", version = "1.3.2", source = { registry = "https://pypi.org/simple" } }, - { name = "cycler" }, - { name = "fonttools" }, - { name = "kiwisolver" }, - { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" } }, - { name = "packaging" }, - { name = "pillow" }, - { name = "pyparsing" }, - { name = "python-dateutil" }, + { name = "contourpy", version = "1.3.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, + { name = "cycler", marker = "python_full_version < '3.11'" }, + { name = "fonttools", marker = "python_full_version < '3.11'" }, + { name = "kiwisolver", marker = "python_full_version < '3.11'" }, + { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, + { name = "packaging", marker = "python_full_version < '3.11'" }, + { name = "pillow", marker = "python_full_version < '3.11'" }, + { name = "pyparsing", marker = "python_full_version < '3.11'" }, + { name = "python-dateutil", marker = "python_full_version < '3.11'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/63/1b/4be5be87d43d327a0cf4de1a56e86f7f84c89312452406cf122efe2839e6/matplotlib-3.10.9.tar.gz", hash = "sha256:fd66508e8c6877d98e586654b608a0456db8d7e8a546eb1e2600efd957302358", size = 34811233, upload-time = "2026-04-24T00:14:13.539Z" } wheels = [ @@ -1538,15 +1538,15 @@ resolution-markers = [ "python_full_version == '3.11.*' and sys_platform != 'darwin' and sys_platform != 'emscripten' and sys_platform != 'win32'", ] dependencies = [ - { name = "contourpy", version = "1.3.3", source = { registry = "https://pypi.org/simple" } }, - { name = "cycler" }, - { name = "fonttools" }, - { name = "kiwisolver" }, - { name = "numpy", version = "2.3.5", source = { registry = "https://pypi.org/simple" } }, - { name = "packaging" }, - { name = "pillow" }, - { name = "pyparsing" }, - { name = "python-dateutil" }, + { name = "contourpy", version = "1.3.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, + { name = "cycler", marker = "python_full_version >= '3.11'" }, + { name = "fonttools", marker = "python_full_version >= '3.11'" }, + { name = "kiwisolver", marker = "python_full_version >= '3.11'" }, + { name = "numpy", version = "2.3.5", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, + { name = "packaging", marker = "python_full_version >= '3.11'" }, + { name = "pillow", marker = "python_full_version >= '3.11'" }, + { name = "pyparsing", marker = "python_full_version >= '3.11'" }, + { name = "python-dateutil", marker = "python_full_version >= '3.11'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/1f/24/080c99d223d158d3a8902769269ab6da5b50f7a0e6e072513907e02b7a6c/matplotlib-3.11.0.tar.gz", hash = "sha256:68c0c7be01b30dcca3638934f7f591df73401235cbdbf0d1ab1c71e7db7f8b57", size = 33251176, upload-time = "2026-06-12T02:29:15.508Z" } wheels = [ @@ -2136,10 +2136,10 @@ resolution-markers = [ "python_full_version < '3.11' and sys_platform != 'darwin'", ] dependencies = [ - { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" } }, - { name = "python-dateutil" }, - { name = "pytz" }, - { name = "tzdata" }, + { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, + { name = "python-dateutil", marker = "python_full_version < '3.11'" }, + { name = "pytz", marker = "python_full_version < '3.11'" }, + { name = "tzdata", marker = "python_full_version < '3.11'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/33/01/d40b85317f86cf08d853a4f495195c73815fdf205eef3993821720274518/pandas-2.3.3.tar.gz", hash = "sha256:e05e1af93b977f7eafa636d043f9f94c7ee3ac81af99c13508215942e64c993b", size = 4495223, upload-time = "2025-09-29T23:34:51.853Z" } wheels = [ @@ -2194,9 +2194,9 @@ resolution-markers = [ "python_full_version == '3.11.*' and sys_platform != 'darwin' and sys_platform != 'emscripten' and sys_platform != 'win32'", ] dependencies = [ - { name = "numpy", version = "2.3.5", source = { registry = "https://pypi.org/simple" } }, - { name = "python-dateutil" }, - { name = "tzdata", marker = "sys_platform == 'emscripten' or sys_platform == 'win32'" }, + { name = "numpy", version = "2.3.5", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, + { name = "python-dateutil", marker = "python_full_version >= '3.11'" }, + { name = "tzdata", marker = "(python_full_version >= '3.11' and sys_platform == 'emscripten') or (python_full_version >= '3.11' and sys_platform == 'win32')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/5a/fd/e0194474c71dbfba82e744f66945c274f15b667acd5f8c117b12555fb91e/pandas-3.0.4.tar.gz", hash = "sha256:62f6062586d159663825f06e70ef49cd1572d45824cb63a9559f3ffd1d0d2a20", size = 4658146, upload-time = "2026-06-28T15:31:51.3Z" } wheels = [ @@ -2250,7 +2250,7 @@ name = "pexpect" version = "4.9.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "ptyprocess" }, + { name = "ptyprocess", marker = "(python_full_version < '3.11' and sys_platform == 'emscripten') or (python_full_version < '3.11' and sys_platform == 'win32') or (sys_platform != 'emscripten' and sys_platform != 'win32')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/42/92/cc564bf6381ff43ce1f4d06852fc19a2f11d180f23dc32d9588bee2f149d/pexpect-4.9.0.tar.gz", hash = "sha256:ee7d41123f3c9911050ea2c2dac107568dc43b2d3b0c7557a33212c398ead30f", size = 166450, upload-time = "2023-11-25T09:07:26.339Z" } wheels = [ @@ -3042,27 +3042,27 @@ wheels = [ [[package]] name = "ruff" -version = "0.15.20" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/43/dc/35b341fc554ba02f217fc10da57d1a75168cfbcf75b0ef2202176d4c4f2d/ruff-0.15.20.tar.gz", hash = "sha256:1416eb04349192646b54de98f146c4f59afe37d0decfc02c3cbbf396f3a28566", size = 4755489, upload-time = "2026-06-25T17:20:37.578Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/94/d9/2d5014f0253ba541d2061d9fa7193f48e941c8b21bb88a7ff9bbe0bd0596/ruff-0.15.20-py3-none-linux_armv6l.whl", hash = "sha256:00e188c53e499c3c1637f73c91dcf2fb56d576cab76ce1be50a27c4e80e37078", size = 10839665, upload-time = "2026-06-25T17:19:44.702Z" }, - { url = "https://files.pythonhosted.org/packages/c6/d3/ac1798ba64f670698867fcfc591d50e7e421bef137db564858f619a30fcf/ruff-0.15.20-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:9ebd1fd9b9c95fc0bd7b2761aebec1f030013d2e193a2901b224af68fe47251b", size = 11208649, upload-time = "2026-06-25T17:19:48.787Z" }, - { url = "https://files.pythonhosted.org/packages/47/47/d3ac899991202095dfcf3d5176be4272642be3cf981a2f1a30f72a2afb95/ruff-0.15.20-py3-none-macosx_11_0_arm64.whl", hash = "sha256:c5b16cdd67ca108185cd36dce98c576350c03b1660a751de725fb049193a0632", size = 10622638, upload-time = "2026-06-25T17:19:51.354Z" }, - { url = "https://files.pythonhosted.org/packages/33/13/4e043fe30aa94d4ff5213a9881fc296d12960f5971b234a5263fdc225312/ruff-0.15.20-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3413bb3c3d2ca6a8208f1f4809cd2dca3c6de6d0b491c0e70847672bde6e6efd", size = 10984227, upload-time = "2026-06-25T17:19:54.044Z" }, - { url = "https://files.pythonhosted.org/packages/76/e6/92e7bf40388bc5800073b96564f56264f7e48bfd1a498f5ced6ae6d5a769/ruff-0.15.20-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bd7ec42b3bb3da066488db093308a69c4ac5ee6d2af333a86ba6e2eb2e7dd44b", size = 10622882, upload-time = "2026-06-25T17:19:57.037Z" }, - { url = "https://files.pythonhosted.org/packages/13/7a/43460be3f24495a3aa46d4b16873e2c4941b3b5f0b00cf88c03b7b94b339/ruff-0.15.20-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e1a36ad0eb77fba9aabfb69ede54de6f376d04ac18ebea022847046d340a8267", size = 11474808, upload-time = "2026-06-25T17:20:00.357Z" }, - { url = "https://files.pythonhosted.org/packages/27/a0/f37077884873221c6b33b4ab49eb18f9f88e54a16a25a5bca59bef46dd66/ruff-0.15.20-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b6df3b1e4610432f0386dba04d853b5f08cbbc903410c6fcc02f620f05aff53c", size = 12293094, upload-time = "2026-06-25T17:20:03.446Z" }, - { url = "https://files.pythonhosted.org/packages/a6/74/165545b60256a9704c21ac0ec4a0d07933b320812f9584836c9f4aca4292/ruff-0.15.20-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e89f198a1ea6ef0d727c1cf16088bc91a6cb0ab947dedc966715691647186eae", size = 11526176, upload-time = "2026-06-25T17:20:06.301Z" }, - { url = "https://files.pythonhosted.org/packages/86/b1/a976a136d40ade83ce743578399865f57001003a409acadc0ecbb3051082/ruff-0.15.20-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:309809086c2acb67624950a3c8133e80f32d0d3e27106c0cd60ff26657c9f24b", size = 11520767, upload-time = "2026-06-25T17:20:09.191Z" }, - { url = "https://files.pythonhosted.org/packages/19/0f/f032696cb01c9b54c0263fa393474d7758f1cdc021a01b04e3cbc2500999/ruff-0.15.20-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:2d2374caa2f2c2f9e2b7da0a50802cfb8b79f55a9b5e49379f564544fbf56487", size = 11500132, upload-time = "2026-06-25T17:20:13.602Z" }, - { url = "https://files.pythonhosted.org/packages/4b/f4/51b1a14bc69e8c224b15dab9cce8e99b425e0455d462caa2b3c9be2b6a8e/ruff-0.15.20-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:a1ed17b65293e0c2f22fc387bc13198a5de94bf4429589b0ff6946b0feaf21a3", size = 10943828, upload-time = "2026-06-25T17:20:16.635Z" }, - { url = "https://files.pythonhosted.org/packages/71/4b/fe267640783cd02bf6c5cc290b1df1051be2ec294c678b5c15fe19e52343/ruff-0.15.20-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:f701305e66b38ea6c91882490eb73459796808e4c6362a1b765255e0cdcd4053", size = 10645418, upload-time = "2026-06-25T17:20:19.4Z" }, - { url = "https://files.pythonhosted.org/packages/b0/c0/a65aa4ec2f5e87a1df32dc3ec1fede434fe3dfd5cbcf3b503cafc676ab54/ruff-0.15.20-py3-none-musllinux_1_2_i686.whl", hash = "sha256:5b9c0c367ad8e5d0d5b5b8537864c469a0a0e55417aadfbeca41fa61333be9f4", size = 11211770, upload-time = "2026-06-25T17:20:22.033Z" }, - { url = "https://files.pythonhosted.org/packages/5a/a4/0caa331d954ae2723d729d351c989cb4ca8b6077d5c6c2cb6de75e98c041/ruff-0.15.20-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:01cc00dd58f0df339d0e902219dd53990ea99996a0344e5d9cc8d45d5307e460", size = 11618698, upload-time = "2026-06-25T17:20:25.259Z" }, - { url = "https://files.pythonhosted.org/packages/10/9b/5f14927848d2fd4aa891fd88d883788c5a7baba561c7874732364045708c/ruff-0.15.20-py3-none-win32.whl", hash = "sha256:ed65ef510e43a137207e0f01cfcf998aeddb1aeeda5c9d35023e910284d7cf21", size = 10857322, upload-time = "2026-06-25T17:20:28.612Z" }, - { url = "https://files.pythonhosted.org/packages/fa/f0/fe47c501f9dea92a26d788ff98bb5d92ed4cb4c88792c5c88af6b697dc8e/ruff-0.15.20-py3-none-win_amd64.whl", hash = "sha256:a525c81c70fb0380344dd1d8745d8cc1c890b7fc94a58d5a07bd8eb9557b8415", size = 11993274, upload-time = "2026-06-25T17:20:31.871Z" }, - { url = "https://files.pythonhosted.org/packages/d7/2b/9555445e1201d92b3195f45cdb153a0b68f24e0a4273f6e3d5ab46e212bb/ruff-0.15.20-py3-none-win_arm64.whl", hash = "sha256:2f5b2a6d614e8700388806a14996c40fab2c47b819ef57d790a34878858ed9ca", size = 11343498, upload-time = "2026-06-25T17:20:35.03Z" }, +version = "0.16.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/70/25/7113f6d5498888c5fb7db34081cba7d5971c4cb1bfb26819966eee68f003/ruff-0.16.1.tar.gz", hash = "sha256:fedad7c801dabd3fb9741d76aca39246e6ddd9ca446a015875207bf19f1e6bc7", size = 4877500, upload-time = "2026-07-30T19:37:01.379Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1b/bd/694da69368e0973de65df2ddc73ab18d43c469d5963d9b150911de6bc513/ruff-0.16.1-py3-none-linux_armv6l.whl", hash = "sha256:58edb313b88f0c5460a26adf5f39a37a3be789494a15e3e411e35fa78b89f9a0", size = 10839126, upload-time = "2026-07-30T19:36:13.697Z" }, + { url = "https://files.pythonhosted.org/packages/3f/f0/b626e5d5bd0dd9576263658ef12885e2288afd1029a48e26ffed65ec1ac1/ruff-0.16.1-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:fde5a99e2f97479af66edd6622c6d5a2a7592c77cf4153d9e4428f5eeb55b60c", size = 11070253, upload-time = "2026-07-30T19:36:17.14Z" }, + { url = "https://files.pythonhosted.org/packages/83/63/f40acfb6b35b88623e71684942b552c3edd96035f5d98f313815f7b277de/ruff-0.16.1-py3-none-macosx_11_0_arm64.whl", hash = "sha256:e0d4c20532fca4f7fa609369161d968dd28f65d83dabbd61d8e9c7edbf7001f6", size = 10561425, upload-time = "2026-07-30T19:36:20.04Z" }, + { url = "https://files.pythonhosted.org/packages/aa/dd/14ec0e9c2b4d315547dd38765004b4863e354e1b52cb308272215d9f6f6d/ruff-0.16.1-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:30affbcedf59ad5703d9c91f82266e02b47739f797e1a7b6e158e5526a6dae38", size = 10948879, upload-time = "2026-07-30T19:36:22.476Z" }, + { url = "https://files.pythonhosted.org/packages/33/e9/9d870cbae575030fdef595f04b4b97573c525b5497cce4f4498cf2f85446/ruff-0.16.1-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:24e9c631573cbca9d20f1283f8f479b2afa4a8503504822bd71a293889f16743", size = 10643691, upload-time = "2026-07-30T19:36:24.914Z" }, + { url = "https://files.pythonhosted.org/packages/c4/09/12743d544e2173f53ecd27217c65f90d2bc0f8424a66a60339e56bbc0457/ruff-0.16.1-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b41bdd48fb420987a9b5212e4957c26ad4abce401fa9ea9d4d85843727945f4f", size = 11435354, upload-time = "2026-07-30T19:36:28.447Z" }, + { url = "https://files.pythonhosted.org/packages/7f/89/a1652b2daee52083c9554a6333b678a8b01d0400f976827bb87857f9449a/ruff-0.16.1-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b0d1e1393b7648079e13669de1c1f4fde06d4583e84d8fd5c1551e0a77a2aa75", size = 12259033, upload-time = "2026-07-30T19:36:31.326Z" }, + { url = "https://files.pythonhosted.org/packages/16/96/ecdcb8c54ee7b123b487f807eb014e6e019155a0b81dfb669acd52f28ce3/ruff-0.16.1-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:07bf434b1c95f4e093be4532068ef4fcf00924eb2ade8796075980902d6fd54a", size = 11667981, upload-time = "2026-07-30T19:36:34.394Z" }, + { url = "https://files.pythonhosted.org/packages/cd/90/c52e12e0d862e9572f2a33aa227409143520abe53111e9a6babbac7b4af8/ruff-0.16.1-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:39897739f112253ee4fdd2e8aa9a4f9ded99fb2be367d5f31dfa4ded6025584c", size = 11468183, upload-time = "2026-07-30T19:36:37.339Z" }, + { url = "https://files.pythonhosted.org/packages/2c/6b/4ffb7ad1d83eb16cf8cbb3c8815d3f11c88460fd162d4b372a2059be1c2a/ruff-0.16.1-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:82ae3c0c0d74daf17b968a10b7b3bb3ef297ab7de0c1f749646b25e690ccb150", size = 11470071, upload-time = "2026-07-30T19:36:39.91Z" }, + { url = "https://files.pythonhosted.org/packages/9c/72/32ae7db4c0b5e32ab611787caa19d1546800676d79f7483b7100a3561bf4/ruff-0.16.1-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:4d5f2ed10f8242d83fc08d521301089364e3375375705356f20c0e31606ef3ef", size = 10919503, upload-time = "2026-07-30T19:36:42.65Z" }, + { url = "https://files.pythonhosted.org/packages/f7/ca/3d901ba6ad6fc38da39c3448fc6c59ac945679293a17c3ceb6d6c1cba13e/ruff-0.16.1-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:a4665b309891f83f3e3c25447935f1213e9abbd4b5640af7a1f2def9f8d413c1", size = 10649861, upload-time = "2026-07-30T19:36:45.18Z" }, + { url = "https://files.pythonhosted.org/packages/92/79/894ef1ced26552d5f8c9cf6d85b0687840e1128c55aeab7b9c2d54a0d880/ruff-0.16.1-py3-none-musllinux_1_2_i686.whl", hash = "sha256:26e9ca5c9bc3971f20d3cf18a957f52ffd6a5f6564ff15c4912a144dcac22494", size = 11148137, upload-time = "2026-07-30T19:36:47.936Z" }, + { url = "https://files.pythonhosted.org/packages/2d/69/3609a09fa1cb46cc28b762363e440a354204e5dff01bd0c8d7437874d6b9/ruff-0.16.1-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:67e1e1e3fa4f0c82f0e36d4cd61e661f6e7a6196cb1aa92fe0828fa7b8f257cd", size = 11559211, upload-time = "2026-07-30T19:36:50.448Z" }, + { url = "https://files.pythonhosted.org/packages/fc/8a/fb22af2fd78a736e241fabf67e30ce1799a64244026377a49e133af90762/ruff-0.16.1-py3-none-win32.whl", hash = "sha256:d31765e131295b8445caf301e3e8a85b34d1b9b211b4109b7ba457888b051806", size = 10838258, upload-time = "2026-07-30T19:36:53.298Z" }, + { url = "https://files.pythonhosted.org/packages/d4/35/e57fd9fb5d423961df087a00b12d42c0a830288dc2f3b45ecca299158b4f/ruff-0.16.1-py3-none-win_amd64.whl", hash = "sha256:09b05e8b90c2cb06ad63464350e7a45e8e44a2dfe52072ebfba6666ca8d3f596", size = 11961111, upload-time = "2026-07-30T19:36:56.107Z" }, + { url = "https://files.pythonhosted.org/packages/cb/46/240ea004bf6dc4feb40e9832f2205a476a47dd5b8a3f8211a5fc5f95e20e/ruff-0.16.1-py3-none-win_arm64.whl", hash = "sha256:dbaadaac38c70239f056d306b7476f246b0bf000fa6b3876402acbf5b227eaf8", size = 11309414, upload-time = "2026-07-30T19:36:58.79Z" }, ] [[package]] @@ -3074,7 +3074,7 @@ resolution-markers = [ "python_full_version < '3.11' and sys_platform != 'darwin'", ] dependencies = [ - { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" } }, + { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/0f/37/6964b830433e654ec7485e45a00fc9a27cf868d622838f6b6d9c5ec0d532/scipy-1.15.3.tar.gz", hash = "sha256:eae3cf522bc7df64b42cad3925c876e1b0b6c35c1337c93e12c0f366f55b0eaf", size = 59419214, upload-time = "2025-05-08T16:13:05.955Z" } wheels = [ @@ -3136,7 +3136,7 @@ resolution-markers = [ "python_full_version == '3.11.*' and sys_platform != 'darwin' and sys_platform != 'emscripten' and sys_platform != 'win32'", ] dependencies = [ - { name = "numpy", version = "2.3.5", source = { registry = "https://pypi.org/simple" } }, + { name = "numpy", version = "2.3.5", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.11.*'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/7a/97/5a3609c4f8d58b039179648e62dd220f89864f56f7357f5d4f45c29eb2cc/scipy-1.17.1.tar.gz", hash = "sha256:95d8e012d8cb8816c226aef832200b1d45109ed4464303e997c5b13122b297c0", size = 30573822, upload-time = "2026-02-23T00:26:24.851Z" } wheels = [ @@ -3193,7 +3193,7 @@ resolution-markers = [ "python_full_version >= '3.12' and sys_platform != 'darwin' and sys_platform != 'emscripten' and sys_platform != 'win32'", ] dependencies = [ - { name = "numpy", version = "2.3.5", source = { registry = "https://pypi.org/simple" } }, + { name = "numpy", version = "2.3.5", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.12'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/a7/25/c2700dfaf6442b4effaa91af24ebce5dc9d31bb4a69706313aae70d72cd0/scipy-1.18.0.tar.gz", hash = "sha256:67b2ad2ad54c72ca6d04975a9b2df8c3638c34ddd5b28738e94fc2b57929d378", size = 30774447, upload-time = "2026-06-19T15:01:43.456Z" } wheels = [ From e5ec23a7e3a9d7d77d126525a2815bc382931178 Mon Sep 17 00:00:00 2001 From: Evan Kiefl Date: Sun, 2 Aug 2026 12:22:32 -0700 Subject: [PATCH 02/11] Apply reviewed unsafe ruff fixes; drop __all__ grouping comments --- pooltool/__init__.py | 57 +++++++++---------- pooltool/ai/aim/core.py | 2 +- pooltool/ai/pot/core.py | 4 +- pooltool/ani/animate.py | 8 +-- pooltool/ani/collision.py | 2 +- pooltool/ani/hud.py | 2 +- pooltool/ani/modes/aim.py | 2 +- pooltool/ani/modes/ball_in_hand.py | 2 +- pooltool/ani/modes/calculate.py | 2 +- pooltool/ani/modes/cam_load.py | 4 +- pooltool/ani/modes/cam_save.py | 4 +- pooltool/ani/modes/shot.py | 6 +- pooltool/ani/modes/stroke.py | 4 +- pooltool/ani/modes/view.py | 4 +- pooltool/config/__init__.py | 2 +- pooltool/layouts.py | 2 +- pooltool/objects/cue/render.py | 9 +-- pooltool/objects/table/render.py | 2 +- pooltool/physics/__init__.py | 32 +++++------ pooltool/physics/evolve/__init__.py | 7 +-- pooltool/ruleset/datatypes.py | 9 +-- pooltool/ruleset/eight_ball.py | 5 +- pooltool/ruleset/nine_ball.py | 5 +- pooltool/ruleset/sandbox.py | 2 +- pooltool/ruleset/snooker/core.py | 7 +-- pooltool/ruleset/three_cushion.py | 4 +- pooltool/ruleset/utils.py | 11 ++-- sandbox/ball_ball_collisions.py | 4 +- sandbox/ball_cushion_collisions.py | 8 +-- .../resolve/ball_ball/test_ball_ball.py | 4 +- 30 files changed, 94 insertions(+), 122 deletions(-) diff --git a/pooltool/__init__.py b/pooltool/__init__.py index c207e634..8199aee4 100755 --- a/pooltool/__init__.py +++ b/pooltool/__init__.py @@ -55,44 +55,39 @@ from pooltool.system import MultiSystem, System __all__ = [ - # subpackages - "events", - "evolution", - "game", - "objects", - "physics", - "ptmath", - "ruleset", - "system", - "utils", - # submodules - "constants", - "interact", - "layouts", - # non-documented - "serialize", - "image", - "ai", - "pot", - "aim", - # objects - "EventType", - "GameType", - "Game", "Ball", "BallParams", "Cue", - "Table", - "TableType", - "Player", + "EventType", + "Game", + "GameType", "MultiSystem", + "Player", "System", - # functions + "Table", + "TableType", + "ai", + "aim", + "constants", "continuize", - "interpolate_ball_states", - "simulate", - "show", + "events", + "evolution", + "game", "generate_layout", "get_rack", "get_ruleset", + "image", + "interact", + "interpolate_ball_states", + "layouts", + "objects", + "physics", + "pot", + "ptmath", + "ruleset", + "serialize", + "show", + "simulate", + "system", + "utils", ] diff --git a/pooltool/ai/aim/core.py b/pooltool/ai/aim/core.py index f28f2e7f..3a02fbe6 100644 --- a/pooltool/ai/aim/core.py +++ b/pooltool/ai/aim/core.py @@ -128,7 +128,7 @@ def _at_ball(cue_ball: Ball, object_ball: Ball, cut: float = 0.0) -> float: assert -89.0 <= cut <= 89.0, "Cut must be less than 89 and more than -89" - left = True if cut < 0 else False + left = cut < 0 cut = np.abs(cut) * np.pi / 180 R = object_ball.params.R d = ptmath.norm3d(object_ball.state.rvw[0] - cue_ball.state.rvw[0]) diff --git a/pooltool/ai/pot/core.py b/pooltool/ai/pot/core.py index 1a6a388f..34ab7253 100644 --- a/pooltool/ai/pot/core.py +++ b/pooltool/ai/pot/core.py @@ -331,13 +331,13 @@ def open_pockets(ball: Ball, table: Table, balls: Iterable[Ball]) -> set[str]: See also: viable_pockets """ - return set( + return { pocket.id for pocket in table.pockets.values() if not is_pocket_occluded(ball, table, pocket, balls) and is_room_for_cue_ball(ball, table, pocket, balls) and not is_jaw_in_way(ball, table, pocket) - ) + } def required_precision( diff --git a/pooltool/ani/animate.py b/pooltool/ani/animate.py index d1a0c769..a9dc58cf 100755 --- a/pooltool/ani/animate.py +++ b/pooltool/ani/animate.py @@ -425,10 +425,10 @@ def show( if settings.graphics.hud: hud.init(hide=[HUDElement.help_text]) - params = dict( - build_animations=True, - playback_mode=PlaybackMode.LOOP, - ) + params = { + "build_animations": True, + "playback_mode": PlaybackMode.LOOP, + } Global.mode_mgr.update_event_baseline() Global.mode_mgr.change_mode(Mode.shot, enter_kwargs=params) Global.task_mgr.run() diff --git a/pooltool/ani/collision.py b/pooltool/ani/collision.py index 28461e02..b555f4f6 100644 --- a/pooltool/ani/collision.py +++ b/pooltool/ani/collision.py @@ -108,7 +108,7 @@ def process_cushion_collision(self, entry): ) # Center ofthe cueing ball - Bx, By, Bz = self.avoid_nodes["cue_stick_focus"].getPos( + _Bx, _By, _Bz = self.avoid_nodes["cue_stick_focus"].getPos( self.avoid_nodes["scene"] ) diff --git a/pooltool/ani/hud.py b/pooltool/ani/hud.py index b394e95e..ddbdcfa6 100644 --- a/pooltool/ani/hud.py +++ b/pooltool/ani/hud.py @@ -42,7 +42,7 @@ def __init__(self): self.elements = None self.initialized = False - def init(self, hide: list[HUDElement] = list()): + def init(self, hide: list[HUDElement] = []): """Initialize HUD elements and start the HUD update task""" self.elements = { diff --git a/pooltool/ani/modes/aim.py b/pooltool/ani/modes/aim.py index a75234c3..5600e94d 100644 --- a/pooltool/ani/modes/aim.py +++ b/pooltool/ani/modes/aim.py @@ -128,7 +128,7 @@ def exit(self): def aim_task(self, task): if self.keymap[Action.view]: - Global.mode_mgr.change_mode(Mode.view, enter_kwargs=dict(move_active=True)) + Global.mode_mgr.change_mode(Mode.view, enter_kwargs={"move_active": True}) return task.done elif self.keymap[Action.stroke]: Global.mode_mgr.change_mode(Mode.stroke) diff --git a/pooltool/ani/modes/ball_in_hand.py b/pooltool/ani/modes/ball_in_hand.py index 2952a0fd..bcb487cf 100644 --- a/pooltool/ani/modes/ball_in_hand.py +++ b/pooltool/ani/modes/ball_in_hand.py @@ -129,7 +129,7 @@ def ball_in_hand_task(self, task): if not self.keymap[Action.ball_in_hand]: Global.mode_mgr.change_mode( Global.mode_mgr.last_mode, - enter_kwargs=dict(load_prev_cam=False), + enter_kwargs={"load_prev_cam": False}, ) return task.done diff --git a/pooltool/ani/modes/calculate.py b/pooltool/ani/modes/calculate.py index eb73dab0..b31b7ab1 100644 --- a/pooltool/ani/modes/calculate.py +++ b/pooltool/ani/modes/calculate.py @@ -59,7 +59,7 @@ def calculate_view_task(self, task): if not tasks.has("run_simulation"): # simulation calculation is finished Global.mode_mgr.change_mode( - Mode.shot, enter_kwargs=dict(build_animations=True) + Mode.shot, enter_kwargs={"build_animations": True} ) elif self.keymap[Action.zoom]: cam.zoom_via_mouse() diff --git a/pooltool/ani/modes/cam_load.py b/pooltool/ani/modes/cam_load.py index c41fa7ee..57a678c3 100644 --- a/pooltool/ani/modes/cam_load.py +++ b/pooltool/ani/modes/cam_load.py @@ -75,9 +75,9 @@ def update_load_selection(self, state, coords): def cam_load_task(self, task): if not self.keymap[Action.cam_load]: enter_kwargs = ( - dict(load_prev_cam=True) + {"load_prev_cam": True} if Global.mode_mgr.last_mode == Mode.aim - else dict() + else {} ) Global.mode_mgr.change_mode( Global.mode_mgr.last_mode, enter_kwargs=enter_kwargs diff --git a/pooltool/ani/modes/cam_save.py b/pooltool/ani/modes/cam_save.py index 425f990d..e03555d3 100644 --- a/pooltool/ani/modes/cam_save.py +++ b/pooltool/ani/modes/cam_save.py @@ -77,9 +77,9 @@ def update_save_selection(self, state, coords): def cam_save_task(self, task): if not self.keymap[Action.cam_save]: enter_kwargs = ( - dict(load_prev_cam=True) + {"load_prev_cam": True} if Global.mode_mgr.last_mode == Mode.aim - else dict() + else {} ) Global.mode_mgr.change_mode( Global.mode_mgr.last_mode, enter_kwargs=enter_kwargs diff --git a/pooltool/ani/modes/shot.py b/pooltool/ani/modes/shot.py index 29ec5239..82079211 100755 --- a/pooltool/ani/modes/shot.py +++ b/pooltool/ani/modes/shot.py @@ -203,7 +203,7 @@ def shot_view_task(self, task): # Either the user has requested to start the next shot, or the animation has # finished - Global.mode_mgr.change_mode(Mode.aim, exit_kwargs=dict(key="advance")) + Global.mode_mgr.change_mode(Mode.aim, exit_kwargs={"key": "advance"}) elif self.keymap[Action.zoom]: cam.zoom_via_mouse() @@ -241,8 +241,8 @@ def shot_animation_task(self, task): elif self.keymap[Action.undo_shot]: Global.mode_mgr.change_mode( Global.mode_mgr.mode_stroked_from, - exit_kwargs=dict(key="reset"), - enter_kwargs=dict(load_prev_cam=True), + exit_kwargs={"key": "reset"}, + enter_kwargs={"load_prev_cam": True}, ) elif self.keymap[Action.parallel] and self.view_only: diff --git a/pooltool/ani/modes/stroke.py b/pooltool/ani/modes/stroke.py index 3ba35072..73d37b80 100644 --- a/pooltool/ani/modes/stroke.py +++ b/pooltool/ani/modes/stroke.py @@ -111,11 +111,11 @@ def stroke_cue_stick(self): if newX < 0: newX = 0 - collision = True if visual.cue.is_shot() else False + collision = bool(visual.cue.is_shot()) else: collision = False cue_stick_node.setX(newX) visual.cue.append_stroke_data() - return True if collision else False + return bool(collision) diff --git a/pooltool/ani/modes/view.py b/pooltool/ani/modes/view.py index d3dd5240..27ef44d9 100755 --- a/pooltool/ani/modes/view.py +++ b/pooltool/ani/modes/view.py @@ -136,7 +136,7 @@ def view_task(self, task): elif self.keymap[Action.power]: self.view_apply_power() elif self.keymap[Action.aim]: - Global.mode_mgr.change_mode(Mode.aim, enter_kwargs=dict(load_prev_cam=True)) + Global.mode_mgr.change_mode(Mode.aim, enter_kwargs={"load_prev_cam": True}) elif self.keymap[Action.exec_shot]: self.keymap[Action.exec_shot] = False if Global.game.shot_constraints.can_shoot(): @@ -150,7 +150,7 @@ def view_task(self, task): visual.switch_to_shot(multisystem.active_index - 1) self._update_hud() Global.mode_mgr.change_mode( - Mode.shot, enter_kwargs=dict(build_animations=False) + Mode.shot, enter_kwargs={"build_animations": False} ) return task.done else: diff --git a/pooltool/config/__init__.py b/pooltool/config/__init__.py index 80e4ebd8..44ea02da 100644 --- a/pooltool/config/__init__.py +++ b/pooltool/config/__init__.py @@ -284,7 +284,7 @@ def load(cls, path: Path) -> Settings: @staticmethod def _attrs() -> set[str]: - return set([attr.name for attr in attrs.fields_dict(Settings).values()]) + return {attr.name for attr in attrs.fields_dict(Settings).values()} # Inherits from Settings so the LSP recognizes Settings attributes. Yet truthfully these diff --git a/pooltool/layouts.py b/pooltool/layouts.py index 428155a3..544472b6 100755 --- a/pooltool/layouts.py +++ b/pooltool/layouts.py @@ -444,7 +444,7 @@ def _get_snooker_rack( if ballset is None: ballset = DEFAULT_SNOOKER_BALLSET - red_ids = set([f"red_{i:02d}" for i in range(1, 16)]) + red_ids = {f"red_{i:02d}" for i in range(1, 16)} first_red_y = 0.75 + (2 * (spacing_factor + 1) * ball_params.R / table.l) diff --git a/pooltool/objects/cue/render.py b/pooltool/objects/cue/render.py index 3558ac13..88d01269 100644 --- a/pooltool/objects/cue/render.py +++ b/pooltool/objects/cue/render.py @@ -195,17 +195,14 @@ def is_shot(self): # There is only a handful of frames return False - if not any([x > 0 for x in self.stroke_pos]): + if not any(x > 0 for x in self.stroke_pos): # No backstroke return False backstroke_time, _, strike_time = self.get_stroke_times() - if (strike_time - backstroke_time) < 0.3: - # Stroke is too short - return False - - return True + stroke_duration = strike_time - backstroke_time + return stroke_duration >= 0.3 def calc_V0_from_stroke(self): """Calculates V0 from the stroke sequence diff --git a/pooltool/objects/table/render.py b/pooltool/objects/table/render.py index 724acbf0..3072fff2 100644 --- a/pooltool/objects/table/render.py +++ b/pooltool/objects/table/render.py @@ -60,7 +60,7 @@ def init_collisions(self): cushion = self._table.cushion_segments.linear[cushion_id] x1, y1, z1 = cushion.p1 - x2, y2, z2 = cushion.p2 + _x2, _y2, _z2 = cushion.p2 n1, n2, n3 = cushion.normal if cushion_id in ["9", "12"]: diff --git a/pooltool/physics/__init__.py b/pooltool/physics/__init__.py index c462d4e2..068950be 100644 --- a/pooltool/physics/__init__.py +++ b/pooltool/physics/__init__.py @@ -50,34 +50,32 @@ ) __all__ = [ - # Resolve - "display_models", - "Resolver", "RESOLVER_PATH", + "BallBallFrictionModel", "BallBallModel", "BallCCushionModel", "BallLCushionModel", "BallPocketModel", "BallTableModel", - "StickBallModel", "BallTransitionModel", - "rel_velocity", - "surface_velocity", - "get_u_vec", - "get_slide_time", - "get_roll_time", - "get_spin_time", - "get_airborne_time", - "get_ball_energy", - "ball_ball_models", - "BallBallFrictionModel", + "Resolver", + "StickBallModel", "ball_ball_friction_models", - "ball_lcushion_models", + "ball_ball_models", "ball_ccushion_models", + "ball_lcushion_models", "ball_pocket_models", "ball_table_models", - "stick_ball_models", "ball_transition_models", - # Evolve + "display_models", "evolve_ball_motion", + "get_airborne_time", + "get_ball_energy", + "get_roll_time", + "get_slide_time", + "get_spin_time", + "get_u_vec", + "rel_velocity", + "stick_ball_models", + "surface_velocity", ] diff --git a/pooltool/physics/evolve/__init__.py b/pooltool/physics/evolve/__init__.py index e1e19a03..8fb11b0a 100644 --- a/pooltool/physics/evolve/__init__.py +++ b/pooltool/physics/evolve/__init__.py @@ -136,7 +136,7 @@ def _evolve_roll_state( if t == 0: return rvw - r_0, v_0, w_0 = rvw + r_0, v_0, _w_0 = rvw v_0_hat = ptmath.unit_vector(v_0) @@ -169,9 +169,8 @@ def _evolve_perpendicular_spin_component( alpha = 5 * u_sp * g / (2 * R) - if t > np.abs(wz) / alpha: - # You can't decay past 0 angular velocity - t = np.abs(wz) / alpha + # You can't decay past 0 angular velocity + t = min(t, np.abs(wz) / alpha) # Always decay towards 0, whether spin is +ve or -ve sign = 1 if wz > 0 else -1 diff --git a/pooltool/ruleset/datatypes.py b/pooltool/ruleset/datatypes.py index c1b59576..b6405c12 100644 --- a/pooltool/ruleset/datatypes.py +++ b/pooltool/ruleset/datatypes.py @@ -133,14 +133,9 @@ def cueball(self, balls: dict[str, Any]) -> str: return self.cueable[0] def can_shoot(self) -> bool: - if ( - self.call_shot - and self.ball_call is not None - and self.pocket_call is not None - ) or not self.call_shot: + if not self.call_shot: return True - else: - return False + return self.ball_call is not None and self.pocket_call is not None @attrs.define(frozen=True) diff --git a/pooltool/ruleset/eight_ball.py b/pooltool/ruleset/eight_ball.py index 971fb1ef..9f4f798e 100755 --- a/pooltool/ruleset/eight_ball.py +++ b/pooltool/ruleset/eight_ball.py @@ -148,10 +148,7 @@ def is_turn_over(shot: System, constraints: ShotConstraints, legal: bool) -> boo assert constraints.ball_call is not None assert constraints.pocket_call is not None - if is_ball_pocketed_in_pocket(shot, constraints.ball_call, constraints.pocket_call): - return False - - return True + return not is_ball_pocketed_in_pocket(shot, constraints.ball_call, constraints.pocket_call) def is_game_over(shot: System) -> bool: diff --git a/pooltool/ruleset/nine_ball.py b/pooltool/ruleset/nine_ball.py index 76651ad6..7ab8846c 100644 --- a/pooltool/ruleset/nine_ball.py +++ b/pooltool/ruleset/nine_ball.py @@ -97,10 +97,7 @@ def is_turn_over(shot: System, legal: bool) -> bool: ids = get_pocketed_ball_ids_during_shot(shot, exclude={"cue"}) - if len(ids): - return False - - return True + return not len(ids) def is_game_over(shot: System, legal: bool) -> bool: diff --git a/pooltool/ruleset/sandbox.py b/pooltool/ruleset/sandbox.py index e4d8a92b..99d9045a 100755 --- a/pooltool/ruleset/sandbox.py +++ b/pooltool/ruleset/sandbox.py @@ -32,7 +32,7 @@ def initial_shot_constraints(self) -> ShotConstraints: ball_in_hand=BallInHandOptions.ANYWHERE, movable=None, cueable=None, - hittable=tuple(), + hittable=(), call_shot=False, ) diff --git a/pooltool/ruleset/snooker/core.py b/pooltool/ruleset/snooker/core.py index 5ad88f6a..21cbaca2 100644 --- a/pooltool/ruleset/snooker/core.py +++ b/pooltool/ruleset/snooker/core.py @@ -117,10 +117,7 @@ def is_game_over(shot: System, legal: bool) -> bool: # Foul on black at this stage is an end of frame return True - if "black" in get_pocketed_ball_ids_during_shot(shot, exclude={"white"}): - return True - - return False + return "black" in get_pocketed_ball_ids_during_shot(shot, exclude={"white"}) def decide_winner( @@ -191,7 +188,7 @@ def next_shot_constraints(self, shot: System) -> ShotConstraints: if self.phase is GamePhase.ALTERNATING: hittable = ball_group.balls - call_shot = True if ball_group is BallGroup.COLORS else False + call_shot = ball_group is BallGroup.COLORS ball_call = None else: lowest = get_lowest_pottable(shot) diff --git a/pooltool/ruleset/three_cushion.py b/pooltool/ruleset/three_cushion.py index bcd279f8..0f6cfa77 100644 --- a/pooltool/ruleset/three_cushion.py +++ b/pooltool/ruleset/three_cushion.py @@ -115,7 +115,7 @@ def initial_shot_constraints(self) -> ShotConstraints: ball_in_hand=BallInHandOptions.NONE, movable=[], cueable=["white"], - hittable=tuple(), + hittable=(), call_shot=False, ) @@ -129,7 +129,7 @@ def next_shot_constraints(self, shot: System) -> ShotConstraints: ball_in_hand=BallInHandOptions.NONE, movable=[], cueable=cueable, - hittable=tuple(), + hittable=(), call_shot=False, ) diff --git a/pooltool/ruleset/utils.py b/pooltool/ruleset/utils.py index 7381e6fe..0013ec06 100644 --- a/pooltool/ruleset/utils.py +++ b/pooltool/ruleset/utils.py @@ -99,12 +99,12 @@ def get_ball_ids_on_table( shot: System, at_start: bool, exclude: set[str] | None = None ) -> set[str]: history_idx = 0 if at_start else -1 - return set( + return { ball.id for ball in shot.balls.values() if ball.history[history_idx].s in const.on_table and (exclude is None or ball.id not in exclude) - ) + } class StateProbe(StrEnum): @@ -197,7 +197,7 @@ def balls_that_hit_cushion(shot: System, exclude: set[str] | None = None) -> set by_ball(numbered_ball_ids), ) - return set(event.agents[0].id for event in cushion_events) + return {event.agents[0].id for event in cushion_events} def is_ball_hit(shot: System) -> bool: @@ -212,7 +212,4 @@ def is_shot_called_if_required(shot_constraints: ShotConstraints) -> bool: if not shot_constraints.call_shot: return True - if shot_constraints.ball_call is None or shot_constraints.pocket_call is None: - return False - - return True + return not (shot_constraints.ball_call is None or shot_constraints.pocket_call is None) diff --git a/sandbox/ball_ball_collisions.py b/sandbox/ball_ball_collisions.py index 90d17ca6..fb32d626 100644 --- a/sandbox/ball_ball_collisions.py +++ b/sandbox/ball_ball_collisions.py @@ -148,7 +148,7 @@ def collision_results_versus_cut_angle( vel[i] = collision_experiment.cb_i.vel avel[i] = collision_experiment.cb_i.avel - cb_f, ob_f = collision_experiment.result() + _cb_f, ob_f = collision_experiment.result() induced_vel[i] = ptmath.coordinate_rotation( ob_f.vel, -config.xy_line_of_centers_angle_radians @@ -202,7 +202,7 @@ def collision_results_versus_sidespin( vel[i] = collision_experiment.cb_i.vel avel[i] = collision_experiment.cb_i.avel - cb_f, ob_f = collision_experiment.result() + _cb_f, ob_f = collision_experiment.result() induced_vel[i] = ptmath.coordinate_rotation( ob_f.vel, -config.xy_line_of_centers_angle_radians diff --git a/sandbox/ball_cushion_collisions.py b/sandbox/ball_cushion_collisions.py index bffd6920..2b93e295 100644 --- a/sandbox/ball_cushion_collisions.py +++ b/sandbox/ball_cushion_collisions.py @@ -239,7 +239,7 @@ def plot_rebound_angle_vs_incident_angle( y=cut_angles_deg, mode="lines", name="1:1 line (perfect reflection)", - line=dict(color="gray", width=1, dash="dash"), + line={"color": "gray", "width": 1, "dash": "dash"}, opacity=0.7, ) ) @@ -278,7 +278,7 @@ def plot_rebound_angle_vs_incident_angle( y=rebound_angles_deg, mode="lines", name=label, - line=dict(color=base_color, width=2), + line={"color": base_color, "width": 2}, opacity=opacity, ) ) @@ -334,7 +334,7 @@ def plot_rebound_speed_vs_incident_angle( y=rebound_speeds, mode="lines", name=label, - line=dict(color=base_color, width=2), + line={"color": base_color, "width": 2}, opacity=opacity, ) ) @@ -398,7 +398,7 @@ def plot_change_in_angular_velocity_vs_incident_angle( y=100 * outgoing_avel_proportion_of_avel, mode="lines", name=label, - line=dict(color=base_color, width=2), + line={"color": base_color, "width": 2}, opacity=opacity, ) ) diff --git a/tests/physics/resolve/ball_ball/test_ball_ball.py b/tests/physics/resolve/ball_ball/test_ball_ball.py index 4e30f6db..1d2c4354 100644 --- a/tests/physics/resolve/ball_ball/test_ball_ball.py +++ b/tests/physics/resolve/ball_ball/test_ball_ball.py @@ -80,7 +80,7 @@ def translating_head_on() -> tuple[Ball, Ball]: @pytest.mark.parametrize("model", [FrictionlessElastic()]) def test_head_on_zero_spin(model: BallBallCollisionStrategy): cb_i, ob_i = head_on() - cb_f, ob_f = model.resolve(cb_i, ob_i, inplace=False) + cb_f, _ob_f = model.resolve(cb_i, ob_i, inplace=False) # Since balls are of equal mass, final cue ball +x speed should not be positive assert cb_f.state.rvw[1][0] <= 0 @@ -193,7 +193,7 @@ def test_gearing_z_spin( v_c = tangent_surface_velocity(cb_i.state.rvw, unit_normal, cb_i.params.R) assert ptmath.norm3d(v_c) < 1e-10, "Relative surface contact speed should be zero" - cb_f, ob_f = model.resolve(cb_i, ob_i, inplace=False) + _cb_f, ob_f = model.resolve(cb_i, ob_i, inplace=False) assert np.allclose( np.cross(ob_f.vel, unit_normal), np.zeros_like(unit_normal), atol=1e-3 From a3b0b733e8713154d84e05100606d1768a450134 Mon Sep 17 00:00:00 2001 From: Evan Kiefl Date: Sun, 2 Aug 2026 12:38:27 -0700 Subject: [PATCH 03/11] Resolve remaining ruff 0.16 violations Restores the circular-import-tolerant aliased facade imports that the PLR0402 auto-fix rewrote, with a per-file ignore documenting why. --- pooltool/__init__.py | 35 ++++++++------- pooltool/ani/action.py | 2 - pooltool/ani/animate.py | 8 ++-- pooltool/ani/camera/_camera.py | 7 ++- pooltool/ani/constants.py | 2 - pooltool/ani/environment.py | 2 - pooltool/ani/hud.py | 5 +-- pooltool/ani/menu/_datatypes.py | 2 +- pooltool/ani/menu/_registry.py | 5 ++- pooltool/ani/modes/__init__.py | 2 - pooltool/ani/modes/aim.py | 4 +- pooltool/ani/modes/ball_in_hand.py | 13 +++--- pooltool/ani/modes/calculate.py | 4 +- pooltool/ani/modes/call_shot.py | 5 +-- pooltool/ani/modes/cam_load.py | 8 ++-- pooltool/ani/modes/cam_save.py | 8 ++-- pooltool/ani/modes/datatypes.py | 22 ++++++---- pooltool/ani/modes/game_over.py | 4 +- pooltool/ani/modes/menu.py | 5 +-- pooltool/ani/modes/pick_ball.py | 5 ++- pooltool/ani/modes/purgatory.py | 4 +- pooltool/ani/modes/shot.py | 5 +-- pooltool/ani/modes/stroke.py | 4 +- pooltool/ani/modes/view.py | 4 +- pooltool/ani/mouse.py | 2 - pooltool/ani/scene.py | 10 ++--- pooltool/ani/tasks.py | 3 +- pooltool/config/__init__.py | 6 +-- pooltool/constants.py | 1 - pooltool/evolution/event_based/cache.py | 5 +-- .../evolution/event_based/introspection.py | 1 - pooltool/evolution/event_based/simulate.py | 2 - pooltool/layouts.py | 0 pooltool/main.py | 3 -- pooltool/objects/cue/datatypes.py | 2 - pooltool/objects/datatypes.py | 4 +- pooltool/objects/table/specs.py | 2 - .../frictional_inelastic/__init__.py | 2 +- .../ball_ball/frictional_mathavan/__init__.py | 2 +- pooltool/ptmath/utils.py | 5 ++- pooltool/ruleset/__init__.py | 0 pooltool/ruleset/datatypes.py | 3 +- pooltool/ruleset/eight_ball.py | 12 +++--- pooltool/ruleset/nine_ball.py | 2 - pooltool/ruleset/sandbox.py | 2 - pooltool/ruleset/snooker/balls.py | 3 +- pooltool/ruleset/snooker/core.py | 5 +-- pooltool/ruleset/snooker/utils.py | 2 - pooltool/ruleset/sum_to_three.py | 2 - pooltool/ruleset/three_cushion.py | 7 ++- pooltool/ruleset/utils.py | 4 +- pooltool/system/datatypes.py | 2 - pooltool/utils/__init__.py | 6 +-- pooltool/utils/strenum.py | 18 +++----- pyproject.toml | 6 +++ sandbox/airborne_demos.py | 0 sandbox/arena.py | 0 sandbox/ball_cushion_collisions.py | 43 ++++++------------- sandbox/break_forever.py | 0 sandbox/collection.py | 0 sandbox/continuize_and_render_timer.py | 0 sandbox/custom_table.py | 0 sandbox/load.py | 0 sandbox/offscreen/offscreen.py | 0 sandbox/offscreen/timing.py | 0 tests/objects/ball/test_datatypes.py | 4 +- tests/objects/table/test_components.py | 2 +- tests/ptmath/roots/data/_speed_comparison.py | 4 +- 68 files changed, 149 insertions(+), 193 deletions(-) mode change 100755 => 100644 pooltool/__init__.py mode change 100755 => 100644 pooltool/ani/animate.py mode change 100755 => 100644 pooltool/ani/modes/call_shot.py mode change 100755 => 100644 pooltool/ani/modes/shot.py mode change 100755 => 100644 pooltool/ani/modes/view.py mode change 100755 => 100644 pooltool/evolution/event_based/simulate.py mode change 100755 => 100644 pooltool/layouts.py mode change 100755 => 100644 pooltool/main.py mode change 100755 => 100644 pooltool/objects/cue/datatypes.py mode change 100755 => 100644 pooltool/objects/table/specs.py mode change 100755 => 100644 pooltool/ruleset/__init__.py mode change 100755 => 100644 pooltool/ruleset/eight_ball.py mode change 100755 => 100644 pooltool/ruleset/sandbox.py mode change 100644 => 100755 sandbox/airborne_demos.py mode change 100644 => 100755 sandbox/arena.py mode change 100644 => 100755 sandbox/ball_cushion_collisions.py mode change 100644 => 100755 sandbox/break_forever.py mode change 100644 => 100755 sandbox/collection.py mode change 100644 => 100755 sandbox/continuize_and_render_timer.py mode change 100644 => 100755 sandbox/custom_table.py mode change 100644 => 100755 sandbox/load.py mode change 100644 => 100755 sandbox/offscreen/offscreen.py mode change 100644 => 100755 sandbox/offscreen/timing.py diff --git a/pooltool/__init__.py b/pooltool/__init__.py old mode 100755 new mode 100644 index 8199aee4..37e2c378 --- a/pooltool/__init__.py +++ b/pooltool/__init__.py @@ -21,24 +21,23 @@ __version__ = version("pooltool-billiards") -from pooltool import ( - ai, - constants, - events, - evolution, - game, - interact, - layouts, - objects, - physics, - ptmath, - ruleset, - serialize, - system, - utils, -) -from pooltool.ai import aim, pot -from pooltool.ani import image +import pooltool.ai as ai +import pooltool.ai.aim as aim +import pooltool.ai.pot as pot +import pooltool.ani.image as image +import pooltool.constants as constants +import pooltool.events as events +import pooltool.evolution as evolution +import pooltool.game as game +import pooltool.interact as interact +import pooltool.layouts as layouts +import pooltool.objects as objects +import pooltool.physics as physics +import pooltool.ptmath as ptmath +import pooltool.ruleset as ruleset +import pooltool.serialize as serialize +import pooltool.system as system +import pooltool.utils as utils from pooltool.events import EventType from pooltool.evolution import continuize, interpolate_ball_states, simulate from pooltool.game.datatypes import GameType diff --git a/pooltool/ani/action.py b/pooltool/ani/action.py index a405a47b..3d6071c6 100644 --- a/pooltool/ani/action.py +++ b/pooltool/ani/action.py @@ -1,5 +1,3 @@ -#! /usr/bin/env python - from pooltool.utils.strenum import StrEnum, auto diff --git a/pooltool/ani/animate.py b/pooltool/ani/animate.py old mode 100755 new mode 100644 index a9dc58cf..022aaf6a --- a/pooltool/ani/animate.py +++ b/pooltool/ani/animate.py @@ -1,5 +1,3 @@ -#! /usr/bin/env python - import gc import sys from collections.abc import Generator @@ -339,7 +337,8 @@ class ShotViewer(Interface): For usage, see :meth:`show`. """ - def __init__(self, config=ShowBaseConfig.default()): + def __init__(self, config=None): + config = ShowBaseConfig.default() if config is None else config Interface.__init__(self, config=config) self._create_title("") @@ -469,7 +468,8 @@ def _stop(self): class Game(Interface): """This class runs the pooltool application""" - def __init__(self, config=ShowBaseConfig.default()): + def __init__(self, config=None): + config = ShowBaseConfig.default() if config is None else config Interface.__init__(self, config=config) # This task chain allows simulations to be run in parallel to the game processes diff --git a/pooltool/ani/camera/_camera.py b/pooltool/ani/camera/_camera.py index 6f20968b..e2f71b52 100644 --- a/pooltool/ani/camera/_camera.py +++ b/pooltool/ani/camera/_camera.py @@ -1,5 +1,3 @@ -#! /usr/bin/env python - from __future__ import annotations from pathlib import Path @@ -19,6 +17,7 @@ ) from pooltool.ani.globals import Global, require_showbase from pooltool.ani.mouse import mouse +from pooltool.error import PoolToolError from pooltool.objects.table.datatypes import Table from pooltool.ptmath import wiggle from pooltool.serialize import conversion @@ -157,7 +156,7 @@ def fixate(self, pos, node): def store_state(self, name, overwrite=False): """Store the current camera state in self.states""" if name in self.states and not overwrite: - raise Exception(f"Camera :: '{name}' is already a camera state") + raise PoolToolError(f"Camera :: '{name}' is already a camera state") self.states[name] = self.state self.last_state = name @@ -168,7 +167,7 @@ def load_saved_state(self, name, ok_if_not_exists=False): if ok_if_not_exists: return else: - raise Exception(f"Camera :: '{name}' is not a camera state") + raise PoolToolError(f"Camera :: '{name}' is not a camera state") self.load_state(self.states[name]) diff --git a/pooltool/ani/constants.py b/pooltool/ani/constants.py index f875f423..da73c5ab 100644 --- a/pooltool/ani/constants.py +++ b/pooltool/ani/constants.py @@ -1,5 +1,3 @@ -#! /usr/bin/env python - from __future__ import annotations from pathlib import Path diff --git a/pooltool/ani/environment.py b/pooltool/ani/environment.py index 75c7df83..b38f13f1 100644 --- a/pooltool/ani/environment.py +++ b/pooltool/ani/environment.py @@ -1,5 +1,3 @@ -#! /usr/bin/env python - from panda3d.core import ( AmbientLight, DirectionalLight, diff --git a/pooltool/ani/hud.py b/pooltool/ani/hud.py index ddbdcfa6..350607e5 100644 --- a/pooltool/ani/hud.py +++ b/pooltool/ani/hud.py @@ -1,5 +1,3 @@ -#! /usr/bin/env python - from abc import ABC, abstractmethod from collections import deque @@ -42,8 +40,9 @@ def __init__(self): self.elements = None self.initialized = False - def init(self, hide: list[HUDElement] = []): + def init(self, hide: list[HUDElement] | None = None): """Initialize HUD elements and start the HUD update task""" + hide = [] if hide is None else hide self.elements = { HUDElement.help_text: Help(), diff --git a/pooltool/ani/menu/_datatypes.py b/pooltool/ani/menu/_datatypes.py index a4fccb4a..00a0e215 100644 --- a/pooltool/ani/menu/_datatypes.py +++ b/pooltool/ani/menu/_datatypes.py @@ -522,7 +522,7 @@ def create( def _command(text: str) -> None: try: cleaned_value = command(text) - except Exception as e: + except Exception as e: # noqa: BLE001 input_field.reset_value() input_field._show_error_message(str(e)) return diff --git a/pooltool/ani/menu/_registry.py b/pooltool/ani/menu/_registry.py index bd58af40..efa43837 100644 --- a/pooltool/ani/menu/_registry.py +++ b/pooltool/ani/menu/_registry.py @@ -1,13 +1,14 @@ import sys from collections.abc import Callable +from typing import ClassVar from pooltool.ani.globals import Global from pooltool.ani.menu._datatypes import BaseMenu class MenuRegistry: - _menus: dict[str, type[BaseMenu]] = {} - _current_menu: BaseMenu | None = None + _menus: ClassVar[dict[str, type[BaseMenu]]] = {} + _current_menu: ClassVar[BaseMenu | None] = None @classmethod def register(cls, menu_class: type[BaseMenu]) -> None: diff --git a/pooltool/ani/modes/__init__.py b/pooltool/ani/modes/__init__.py index 1a95e70a..7a54a089 100644 --- a/pooltool/ani/modes/__init__.py +++ b/pooltool/ani/modes/__init__.py @@ -1,5 +1,3 @@ -#! /usr/bin/env python - from pooltool.ani.modes.aim import AimMode from pooltool.ani.modes.ball_in_hand import BallInHandMode from pooltool.ani.modes.calculate import CalculateMode diff --git a/pooltool/ani/modes/aim.py b/pooltool/ani/modes/aim.py index 5600e94d..abc1f34c 100644 --- a/pooltool/ani/modes/aim.py +++ b/pooltool/ani/modes/aim.py @@ -1,4 +1,4 @@ -#! /usr/bin/env python +from typing import ClassVar import numpy as np @@ -29,7 +29,7 @@ class AimMode(BaseMode): name = Mode.aim - keymap = { + default_keymap: ClassVar[dict[Action, bool]] = { Action.rotate_cue_left: False, Action.rotate_cue_right: False, Action.fine_control: False, diff --git a/pooltool/ani/modes/ball_in_hand.py b/pooltool/ani/modes/ball_in_hand.py index bcb487cf..8b4cb23d 100644 --- a/pooltool/ani/modes/ball_in_hand.py +++ b/pooltool/ani/modes/ball_in_hand.py @@ -1,4 +1,4 @@ -#! /usr/bin/env python +from typing import ClassVar import numpy as np from direct.interval.IntervalGlobal import Parallel @@ -23,7 +23,7 @@ class BallInHandMode(BaseMode): name = Mode.ball_in_hand - keymap = { + default_keymap: ClassVar[dict[Action, bool]] = { Action.quit: False, Action.ball_in_hand: True, Action.next: False, @@ -113,9 +113,12 @@ def exit(self, success=False): if self.picking == "ball": self.remove_grab_selection_highlight() - if self.picking == "placement" and not success: - if self.grabbed_ball is not None: - self.grabbed_ball.set_render_state_as_object_state() + if ( + self.picking == "placement" + and not success + and self.grabbed_ball is not None + ): + self.grabbed_ball.set_render_state_as_object_state() # Clean up instruction message if it exists if self.instruction_message is not None: diff --git a/pooltool/ani/modes/calculate.py b/pooltool/ani/modes/calculate.py index b31b7ab1..cc220033 100644 --- a/pooltool/ani/modes/calculate.py +++ b/pooltool/ani/modes/calculate.py @@ -1,4 +1,4 @@ -#! /usr/bin/env python +from typing import ClassVar import pooltool.ani.utils as autils from pooltool.ani import tasks @@ -14,7 +14,7 @@ class CalculateMode(BaseMode): name = Mode.calculate - keymap = { + default_keymap: ClassVar[dict[Action, bool]] = { Action.move: False, Action.quit: False, Action.zoom: False, diff --git a/pooltool/ani/modes/call_shot.py b/pooltool/ani/modes/call_shot.py old mode 100755 new mode 100644 index 65c34e1e..86f31f02 --- a/pooltool/ani/modes/call_shot.py +++ b/pooltool/ani/modes/call_shot.py @@ -1,5 +1,4 @@ -#! /usr/bin/env python - +from typing import ClassVar import numpy as np from direct.interval.IntervalGlobal import LerpFunc, Parallel @@ -26,7 +25,7 @@ class CallShotMode(BaseMode): name = Mode.call_shot - keymap = { + default_keymap: ClassVar[dict[Action, bool]] = { Action.quit: False, Action.call_shot: True, Action.next: False, diff --git a/pooltool/ani/modes/cam_load.py b/pooltool/ani/modes/cam_load.py index 57a678c3..c5a38a1b 100644 --- a/pooltool/ani/modes/cam_load.py +++ b/pooltool/ani/modes/cam_load.py @@ -1,4 +1,4 @@ -#! /usr/bin/env python +from typing import ClassVar from direct.gui.DirectGui import DGG @@ -13,7 +13,7 @@ class CamLoadMode(BaseMode): name = Mode.cam_load - keymap = { + default_keymap: ClassVar[dict[Action, bool]] = { Action.quit: False, Action.cam_load: True, } @@ -75,9 +75,7 @@ def update_load_selection(self, state, coords): def cam_load_task(self, task): if not self.keymap[Action.cam_load]: enter_kwargs = ( - {"load_prev_cam": True} - if Global.mode_mgr.last_mode == Mode.aim - else {} + {"load_prev_cam": True} if Global.mode_mgr.last_mode == Mode.aim else {} ) Global.mode_mgr.change_mode( Global.mode_mgr.last_mode, enter_kwargs=enter_kwargs diff --git a/pooltool/ani/modes/cam_save.py b/pooltool/ani/modes/cam_save.py index e03555d3..749e57f8 100644 --- a/pooltool/ani/modes/cam_save.py +++ b/pooltool/ani/modes/cam_save.py @@ -1,4 +1,4 @@ -#! /usr/bin/env python +from typing import ClassVar from direct.gui.DirectGui import DGG @@ -13,7 +13,7 @@ class CamSaveMode(BaseMode): name = Mode.cam_save - keymap = { + default_keymap: ClassVar[dict[Action, bool]] = { Action.quit: False, Action.cam_save: True, } @@ -77,9 +77,7 @@ def update_save_selection(self, state, coords): def cam_save_task(self, task): if not self.keymap[Action.cam_save]: enter_kwargs = ( - {"load_prev_cam": True} - if Global.mode_mgr.last_mode == Mode.aim - else {} + {"load_prev_cam": True} if Global.mode_mgr.last_mode == Mode.aim else {} ) Global.mode_mgr.change_mode( Global.mode_mgr.last_mode, enter_kwargs=enter_kwargs diff --git a/pooltool/ani/modes/datatypes.py b/pooltool/ani/modes/datatypes.py index 2ed64413..b055da75 100644 --- a/pooltool/ani/modes/datatypes.py +++ b/pooltool/ani/modes/datatypes.py @@ -1,6 +1,7 @@ import copy -import pdb +import pdb # noqa: T100 from abc import ABC, abstractmethod +from typing import ClassVar from pooltool.ani import tasks from pooltool.ani.action import Action @@ -27,13 +28,13 @@ class Mode(StrEnum): class BaseMode(ABC): - keymap: dict[Action, bool] = {} + default_keymap: ClassVar[dict[Action, bool]] = {} name: Mode = Mode.none def __init__(self): - if not len(self.keymap): + if not len(self.default_keymap): raise NotImplementedError( - "Subclasses of BaseMode must have non-empty keymap" + "Subclasses of BaseMode must have non-empty default_keymap" ) if self.name == Mode.none: @@ -41,7 +42,7 @@ def __init__(self): "Subclasses of BaseMode must have 'name' attribute" ) - self.defaults = copy.deepcopy(self.keymap) + self.keymap: dict[Action, bool] = copy.deepcopy(self.default_keymap) def shared_task(self, task): if self.keymap.get(Action.quit): @@ -51,8 +52,8 @@ def shared_task(self, task): elif self.keymap.get(Action.introspect): self.keymap[Action.introspect] = False - shot = multisystem.active # noqa F841 - pdb.set_trace() + shot = multisystem.active # noqa: F841 + pdb.set_trace() # noqa: T100 elif self.keymap.get(Action.show_help): self.keymap[Action.show_help] = False @@ -74,7 +75,7 @@ def register_keymap_event(self, keystroke, action_name, action_state): tasks.register_event(keystroke, self.update_keymap, [action_name, action_state]) def reset_action_states(self): - self.keymap = copy.deepcopy(self.defaults) + self.keymap = copy.deepcopy(self.default_keymap) @abstractmethod def enter(self): @@ -111,9 +112,12 @@ def update_event_baseline(self): """ self.baseline_events = Global.base.messenger.get_events() - def change_mode(self, mode, exit_kwargs={}, enter_kwargs={}): + def change_mode(self, mode, exit_kwargs=None, enter_kwargs=None): assert mode in Mode + exit_kwargs = {} if exit_kwargs is None else exit_kwargs + enter_kwargs = {} if enter_kwargs is None else enter_kwargs + # Teardown operations for the old mode self.end_mode(**exit_kwargs) diff --git a/pooltool/ani/modes/game_over.py b/pooltool/ani/modes/game_over.py index 6e24f654..2f8cf27c 100644 --- a/pooltool/ani/modes/game_over.py +++ b/pooltool/ani/modes/game_over.py @@ -1,4 +1,4 @@ -#! /usr/bin/env python +from typing import ClassVar import pooltool.ani.utils as autils from pooltool.ani.action import Action @@ -14,7 +14,7 @@ class GameOverMode(BaseMode): stat_font_size = 0.04 left_most = -0.33 top_most = 0.4 - keymap = { + default_keymap: ClassVar[dict[Action, bool]] = { Action.quit: False, } diff --git a/pooltool/ani/modes/menu.py b/pooltool/ani/modes/menu.py index 672adef0..ef8f8b55 100644 --- a/pooltool/ani/modes/menu.py +++ b/pooltool/ani/modes/menu.py @@ -1,6 +1,5 @@ -#! /usr/bin/env python - import sys +from typing import ClassVar from pooltool.ani import tasks from pooltool.ani.action import Action @@ -13,7 +12,7 @@ class MenuMode(BaseMode): name = Mode.menu - keymap = { + default_keymap: ClassVar[dict[Action, bool]] = { Action.exit: False, Action.new_game: False, Action.scroll_up: False, diff --git a/pooltool/ani/modes/pick_ball.py b/pooltool/ani/modes/pick_ball.py index e5cf70bb..f6acbdd9 100644 --- a/pooltool/ani/modes/pick_ball.py +++ b/pooltool/ani/modes/pick_ball.py @@ -1,4 +1,5 @@ -#! /usr/bin/env python +from typing import ClassVar + """A mode to for picking which ball to cue""" import numpy as np @@ -18,7 +19,7 @@ class PickBallMode(BaseMode): name = Mode.pick_ball - keymap = { + default_keymap: ClassVar[dict[Action, bool]] = { Action.quit: False, Action.pick_ball: True, Action.done: False, diff --git a/pooltool/ani/modes/purgatory.py b/pooltool/ani/modes/purgatory.py index 7c7d3659..e2e2d85c 100644 --- a/pooltool/ani/modes/purgatory.py +++ b/pooltool/ani/modes/purgatory.py @@ -1,4 +1,4 @@ -#! /usr/bin/env python +from typing import ClassVar import pooltool.ani.utils as autils from pooltool.ani import tasks @@ -28,7 +28,7 @@ class PurgatoryMode(BaseMode): """ name = Mode.purgatory - keymap = { + default_keymap: ClassVar[dict[Action, bool]] = { Action.regain_control: False, } diff --git a/pooltool/ani/modes/shot.py b/pooltool/ani/modes/shot.py old mode 100755 new mode 100644 index 82079211..f7c6e296 --- a/pooltool/ani/modes/shot.py +++ b/pooltool/ani/modes/shot.py @@ -1,5 +1,4 @@ -#! /usr/bin/env python - +from typing import ClassVar from pooltool.ani import tasks from pooltool.ani.action import Action @@ -17,7 +16,7 @@ class ShotMode(BaseMode): name = Mode.shot - keymap = { + default_keymap: ClassVar[dict[Action, bool]] = { Action.aim: False, Action.move: False, Action.toggle_pause: False, diff --git a/pooltool/ani/modes/stroke.py b/pooltool/ani/modes/stroke.py index 73d37b80..15b2b7c7 100644 --- a/pooltool/ani/modes/stroke.py +++ b/pooltool/ani/modes/stroke.py @@ -1,4 +1,4 @@ -#! /usr/bin/env python +from typing import ClassVar import pooltool.ani.utils as autils from pooltool.ani import tasks @@ -18,7 +18,7 @@ class StrokeMode(BaseMode): name = Mode.stroke - keymap = { + default_keymap: ClassVar[dict[Action, bool]] = { Action.fine_control: False, Action.stroke: True, } diff --git a/pooltool/ani/modes/view.py b/pooltool/ani/modes/view.py old mode 100755 new mode 100644 index 27ef44d9..0bbcea16 --- a/pooltool/ani/modes/view.py +++ b/pooltool/ani/modes/view.py @@ -1,4 +1,4 @@ -#! /usr/bin/env python +from typing import ClassVar import numpy as np @@ -28,7 +28,7 @@ class ViewMode(BaseMode): name = Mode.view - keymap = { + default_keymap: ClassVar[dict[Action, bool]] = { Action.aim: False, Action.call_shot: False, Action.fine_control: False, diff --git a/pooltool/ani/mouse.py b/pooltool/ani/mouse.py index 8bb86231..186225f4 100644 --- a/pooltool/ani/mouse.py +++ b/pooltool/ani/mouse.py @@ -1,5 +1,3 @@ -#! /usr/bin/env python - import numpy as np from panda3d.core import ClockObject, WindowProperties diff --git a/pooltool/ani/scene.py b/pooltool/ani/scene.py index f4be6d9f..ca7163fa 100644 --- a/pooltool/ani/scene.py +++ b/pooltool/ani/scene.py @@ -292,9 +292,8 @@ def unrender_balls(self) -> None: def unrender_cue(self) -> None: self.system.cue.remove_nodes() - def buildup( - self, components: list[SceneComponents] = list(SceneComponents) - ) -> None: + def buildup(self, components: list[SceneComponents] | None = None) -> None: + components = list(SceneComponents) if components is None else components self.playback_speed = 1 if SceneComponents.TABLE in components: @@ -306,10 +305,9 @@ def buildup( if SceneComponents.ENVIRONMENT in components: self.environment.init(self.system.table._table) - def teardown( - self, components: list[SceneComponents] = list(SceneComponents) - ) -> None: + def teardown(self, components: list[SceneComponents] | None = None) -> None: """Stop animations and remove all nodes""" + components = list(SceneComponents) if components is None else components self.reset_animation() was_in_parallel_mode = self.parallel_manager.is_active diff --git a/pooltool/ani/tasks.py b/pooltool/ani/tasks.py index 96f67772..69e63b50 100644 --- a/pooltool/ani/tasks.py +++ b/pooltool/ani/tasks.py @@ -24,7 +24,7 @@ def remove(name): @require_showbase -def register_event(sequence, func, func_args=[]): +def register_event(sequence, func, func_args=None): """Register event listener that triggers based on keystroke/mouse/message Args: @@ -51,4 +51,5 @@ def register_event(sequence, func, func_args=[]): Global.base.messenger.send("test") """ + func_args = [] if func_args is None else func_args Global.base.accept(sequence, func, func_args) diff --git a/pooltool/config/__init__.py b/pooltool/config/__init__.py index 44ea02da..65a981cc 100644 --- a/pooltool/config/__init__.py +++ b/pooltool/config/__init__.py @@ -215,7 +215,7 @@ class GraphicsConfig: @attrs.define(kw_only=True) class GameplayConfig: - game_type: GameType = settings_field( + game_type: GameType = settings_field( # noqa: RUF009 default=GameType.NINEBALL, metadata=SettingsMetadata( display_name="Game Type", @@ -224,7 +224,7 @@ class GameplayConfig: display_type=DisplayType.DROPDOWN, ), ) - table_name: TableName = settings_field( + table_name: TableName = settings_field( # noqa: RUF009 default=TableName.SEVEN_FOOT_SHOWOOD, metadata=SettingsMetadata( display_name="Table", @@ -341,7 +341,7 @@ def read(self) -> Settings: if self.path.exists(): try: cfg = Settings.load(self.path) - except Exception: + except Exception: # noqa: BLE001 full_traceback = traceback.format_exc() dump_path = self.path.parent / f".{self.path.name}" run.info( diff --git a/pooltool/constants.py b/pooltool/constants.py index c71d475c..8be919a8 100644 --- a/pooltool/constants.py +++ b/pooltool/constants.py @@ -1,4 +1,3 @@ -#! /usr/bin/env python """Constants Notes: diff --git a/pooltool/evolution/event_based/cache.py b/pooltool/evolution/event_based/cache.py index ca2528e6..184056e7 100644 --- a/pooltool/evolution/event_based/cache.py +++ b/pooltool/evolution/event_based/cache.py @@ -1,5 +1,3 @@ -#! /usr/bin/env python - from __future__ import annotations import attrs @@ -60,7 +58,8 @@ def update(self, event: Event) -> None: """Update transition cache for all balls in Event""" for agent in event.agents: if agent.agent_type == AgentType.BALL: - assert isinstance(ball := agent.final, Ball) + ball = agent.final + assert isinstance(ball, Ball) self.transitions[agent.id] = _next_transition(ball) @classmethod diff --git a/pooltool/evolution/event_based/introspection.py b/pooltool/evolution/event_based/introspection.py index e0607557..1b226232 100644 --- a/pooltool/evolution/event_based/introspection.py +++ b/pooltool/evolution/event_based/introspection.py @@ -1,4 +1,3 @@ -#! /usr/bin/env python """Event-based simulation introspection tools. This module provides utilities for capturing and analyzing simulation state at each diff --git a/pooltool/evolution/event_based/simulate.py b/pooltool/evolution/event_based/simulate.py old mode 100755 new mode 100644 index 75ed10a7..0f39a02f --- a/pooltool/evolution/event_based/simulate.py +++ b/pooltool/evolution/event_based/simulate.py @@ -1,5 +1,3 @@ -#! /usr/bin/env python - from __future__ import annotations import attrs diff --git a/pooltool/layouts.py b/pooltool/layouts.py old mode 100755 new mode 100644 diff --git a/pooltool/main.py b/pooltool/main.py old mode 100755 new mode 100644 index 3a449ede..b1eb8776 --- a/pooltool/main.py +++ b/pooltool/main.py @@ -1,6 +1,3 @@ -#!/usr/bin/env python - - import attrs import click diff --git a/pooltool/objects/cue/datatypes.py b/pooltool/objects/cue/datatypes.py old mode 100755 new mode 100644 index e3997f5f..7697f763 --- a/pooltool/objects/cue/datatypes.py +++ b/pooltool/objects/cue/datatypes.py @@ -1,5 +1,3 @@ -#! /usr/bin/env python - from __future__ import annotations from attrs import define, evolve, field, fields_dict diff --git a/pooltool/objects/datatypes.py b/pooltool/objects/datatypes.py index c7781523..98173239 100644 --- a/pooltool/objects/datatypes.py +++ b/pooltool/objects/datatypes.py @@ -56,7 +56,7 @@ def remove_nodes(self): def hide_node(self, name): self.nodes[name].hide() - def hide_nodes(self, ignore=set()): + def hide_nodes(self, ignore=frozenset()): for node_name in self.nodes: if node_name in ignore: continue @@ -65,7 +65,7 @@ def hide_nodes(self, ignore=set()): def show_node(self, name): self.nodes[name].show() - def show_nodes(self, ignore=set()): + def show_nodes(self, ignore=frozenset()): for node_name in self.nodes: if node_name in ignore: continue diff --git a/pooltool/objects/table/specs.py b/pooltool/objects/table/specs.py old mode 100755 new mode 100644 index f021e6a0..1708ad71 --- a/pooltool/objects/table/specs.py +++ b/pooltool/objects/table/specs.py @@ -1,5 +1,3 @@ -#! /usr/bin/env python - from __future__ import annotations from typing import Protocol diff --git a/pooltool/physics/resolve/ball_ball/frictional_inelastic/__init__.py b/pooltool/physics/resolve/ball_ball/frictional_inelastic/__init__.py index a0cb51cb..7cebccd0 100644 --- a/pooltool/physics/resolve/ball_ball/frictional_inelastic/__init__.py +++ b/pooltool/physics/resolve/ball_ball/frictional_inelastic/__init__.py @@ -112,7 +112,7 @@ class FrictionalInelastic(CoreBallBallCollision): more complete analysis of velocity and angular velocity in their vector forms. """ - friction: BallBallFrictionStrategy = AlciatoreBallBallFriction() + friction: BallBallFrictionStrategy = attrs.field(factory=AlciatoreBallBallFriction) model: BallBallModel = attrs.field( default=BallBallModel.FRICTIONAL_INELASTIC, init=False, repr=False diff --git a/pooltool/physics/resolve/ball_ball/frictional_mathavan/__init__.py b/pooltool/physics/resolve/ball_ball/frictional_mathavan/__init__.py index cdc41452..a7c144fd 100644 --- a/pooltool/physics/resolve/ball_ball/frictional_mathavan/__init__.py +++ b/pooltool/physics/resolve/ball_ball/frictional_mathavan/__init__.py @@ -235,7 +235,7 @@ class FrictionalMathavan(CoreBallBallCollision): https://billiards.colostate.edu/physics_articles/Mathavan_Sports_2014.pdf """ - friction: BallBallFrictionStrategy = AlciatoreBallBallFriction() + friction: BallBallFrictionStrategy = attrs.field(factory=AlciatoreBallBallFriction) num_iterations: int = 1000 model: BallBallModel = attrs.field( diff --git a/pooltool/ptmath/utils.py b/pooltool/ptmath/utils.py index b77b4282..58d0f3e4 100644 --- a/pooltool/ptmath/utils.py +++ b/pooltool/ptmath/utils.py @@ -179,8 +179,11 @@ def unit_vector( return vector / norm +_X_AXIS = np.array([1, 0]) + + @jit(nopython=True, cache=const.use_numba_cache) -def angle(v2: NDArray[np.float64], v1: NDArray[np.float64] = np.array([1, 0])) -> float: +def angle(v2: NDArray[np.float64], v1: NDArray[np.float64] = _X_AXIS) -> float: """Returns counter-clockwise angle of projections of v1 and v2 onto the x-y plane (just-in-time compiled) diff --git a/pooltool/ruleset/__init__.py b/pooltool/ruleset/__init__.py old mode 100755 new mode 100644 diff --git a/pooltool/ruleset/datatypes.py b/pooltool/ruleset/datatypes.py index b6405c12..a56c23c7 100644 --- a/pooltool/ruleset/datatypes.py +++ b/pooltool/ruleset/datatypes.py @@ -1,4 +1,3 @@ -#! /usr/bin/env python from __future__ import annotations import copy @@ -128,7 +127,7 @@ def cueball(self, balls: dict[str, Any]) -> str: if cue in balls: return cue - return list(balls.keys())[0] + return next(iter(balls)) return self.cueable[0] diff --git a/pooltool/ruleset/eight_ball.py b/pooltool/ruleset/eight_ball.py old mode 100755 new mode 100644 index 9f4f798e..7b015ed8 --- a/pooltool/ruleset/eight_ball.py +++ b/pooltool/ruleset/eight_ball.py @@ -1,5 +1,3 @@ -#! /usr/bin/env python - from __future__ import annotations from collections import Counter @@ -148,7 +146,9 @@ def is_turn_over(shot: System, constraints: ShotConstraints, legal: bool) -> boo assert constraints.ball_call is not None assert constraints.pocket_call is not None - return not is_ball_pocketed_in_pocket(shot, constraints.ball_call, constraints.pocket_call) + return not is_ball_pocketed_in_pocket( + shot, constraints.ball_call, constraints.pocket_call + ) def is_game_over(shot: System) -> bool: @@ -269,8 +269,10 @@ def get_score(self, shot: System) -> Counter: num_active = num_stripes num_other = num_solids - assert (ball_call := self.shot_constraints.ball_call) == "8" - assert (pocket_call := self.shot_constraints.pocket_call) is not None + ball_call = self.shot_constraints.ball_call + pocket_call = self.shot_constraints.pocket_call + assert ball_call == "8" + assert pocket_call is not None if ( is_ball_pocketed_in_pocket(shot, ball_call, pocket_call) and self.shot_info.legal diff --git a/pooltool/ruleset/nine_ball.py b/pooltool/ruleset/nine_ball.py index 7ab8846c..80ef9c0b 100644 --- a/pooltool/ruleset/nine_ball.py +++ b/pooltool/ruleset/nine_ball.py @@ -1,5 +1,3 @@ -#! /usr/bin/env python - from __future__ import annotations import copy diff --git a/pooltool/ruleset/sandbox.py b/pooltool/ruleset/sandbox.py old mode 100755 new mode 100644 index 99d9045a..b3778099 --- a/pooltool/ruleset/sandbox.py +++ b/pooltool/ruleset/sandbox.py @@ -1,5 +1,3 @@ -#! /usr/bin/env python - from __future__ import annotations from collections import Counter diff --git a/pooltool/ruleset/snooker/balls.py b/pooltool/ruleset/snooker/balls.py index 9aa45b58..7b9a26b2 100644 --- a/pooltool/ruleset/snooker/balls.py +++ b/pooltool/ruleset/snooker/balls.py @@ -53,7 +53,8 @@ def __attrs_post_init__(self): if self.id == "red": return - assert isinstance((loc := snooker_color_locs[self.id].relative_to), tuple) + loc = snooker_color_locs[self.id].relative_to + assert isinstance(loc, tuple) self.respot = loc diff --git a/pooltool/ruleset/snooker/core.py b/pooltool/ruleset/snooker/core.py index 21cbaca2..cecc50d0 100644 --- a/pooltool/ruleset/snooker/core.py +++ b/pooltool/ruleset/snooker/core.py @@ -1,5 +1,3 @@ -#! /usr/bin/env python - from __future__ import annotations from collections import Counter @@ -221,7 +219,8 @@ def respot_balls(self, shot: System): if self.phase is GamePhase.ALTERNATING: check.extend(list(BallGroup.COLORS.balls)) else: - assert (ball_call := self.shot_constraints.ball_call) is not None + ball_call = self.shot_constraints.ball_call + assert ball_call is not None check.extend( get_color_balls_to_be_potted( shot, diff --git a/pooltool/ruleset/snooker/utils.py b/pooltool/ruleset/snooker/utils.py index faa50f52..92a70a36 100644 --- a/pooltool/ruleset/snooker/utils.py +++ b/pooltool/ruleset/snooker/utils.py @@ -1,5 +1,3 @@ -#! /usr/bin/env python - from __future__ import annotations from collections.abc import Iterable diff --git a/pooltool/ruleset/sum_to_three.py b/pooltool/ruleset/sum_to_three.py index ed97ab6d..5e2d9194 100644 --- a/pooltool/ruleset/sum_to_three.py +++ b/pooltool/ruleset/sum_to_three.py @@ -1,5 +1,3 @@ -#! /usr/bin/env python - from __future__ import annotations from collections import Counter diff --git a/pooltool/ruleset/three_cushion.py b/pooltool/ruleset/three_cushion.py index 0f6cfa77..43b18345 100644 --- a/pooltool/ruleset/three_cushion.py +++ b/pooltool/ruleset/three_cushion.py @@ -1,5 +1,3 @@ -#! /usr/bin/env python - from __future__ import annotations from collections import Counter @@ -21,7 +19,7 @@ def _other(cue: str, event: Event) -> str: if id != cue: return id - raise Exception() + raise ValueError(f"Event {event} does not involve a ball other than '{cue}'") def is_point(shot: System) -> bool: @@ -120,7 +118,8 @@ def initial_shot_constraints(self) -> ShotConstraints: ) def next_shot_constraints(self, shot: System) -> ShotConstraints: - assert (cueable := self.shot_constraints.cueable) is not None + cueable = self.shot_constraints.cueable + assert cueable is not None if self.shot_info.turn_over: cueable = [next_cue(cueable[0], len(self.players))] diff --git a/pooltool/ruleset/utils.py b/pooltool/ruleset/utils.py index 0013ec06..d75d7901 100644 --- a/pooltool/ruleset/utils.py +++ b/pooltool/ruleset/utils.py @@ -212,4 +212,6 @@ def is_shot_called_if_required(shot_constraints: ShotConstraints) -> bool: if not shot_constraints.call_shot: return True - return not (shot_constraints.ball_call is None or shot_constraints.pocket_call is None) + return not ( + shot_constraints.ball_call is None or shot_constraints.pocket_call is None + ) diff --git a/pooltool/system/datatypes.py b/pooltool/system/datatypes.py index 7c552f13..37d4c771 100644 --- a/pooltool/system/datatypes.py +++ b/pooltool/system/datatypes.py @@ -1,5 +1,3 @@ -#! /usr/bin/env python - from __future__ import annotations from collections.abc import Iterator diff --git a/pooltool/utils/__init__.py b/pooltool/utils/__init__.py index c4d4c4b0..bd5ea846 100644 --- a/pooltool/utils/__init__.py +++ b/pooltool/utils/__init__.py @@ -59,7 +59,7 @@ def __init__(self): self.timer_start = self.timestamp() def timestamp(self) -> datetime.datetime: - return datetime.datetime.fromtimestamp(time.time()) + return datetime.datetime.now(tz=datetime.timezone.utc).astimezone() def timedelta_to_checkpoint( self, timestamp: datetime.datetime @@ -165,8 +165,8 @@ def get_total_memory_usage() -> int: for child in current_process.children(recursive=True): try: mem += child.memory_info().rss - except Exception: - pass + except psutil.Error: + continue return mem diff --git a/pooltool/utils/strenum.py b/pooltool/utils/strenum.py index f5490b4d..4dbecbf4 100644 --- a/pooltool/utils/strenum.py +++ b/pooltool/utils/strenum.py @@ -1,14 +1,12 @@ from __future__ import annotations from enum import Enum, auto -from typing import Any, TypeVar +from typing import Any from typing_extensions import Self __all__ = ["StrEnum", "auto"] -_S = TypeVar("_S", bound="StrEnum") - class StrEnum(str, Enum): """ @@ -18,19 +16,17 @@ class StrEnum(str, Enum): def __new__(cls, *values: str) -> Self: if len(values) > 3: raise TypeError(f"too many arguments for str(): {values!r}") - if len(values) == 1: - # it must be a string - if not isinstance(values[0], str): - raise TypeError(f"{values[0]!r} is not a string") + # it must be a string + if len(values) == 1 and not isinstance(values[0], str): + raise TypeError(f"{values[0]!r} is not a string") if len(values) >= 2: # check that encoding argument is a string value = values[1] # type: ignore if not isinstance(value, str): raise TypeError(f"encoding must be a string, not {value!r}") - if len(values) == 3: - # check that errors argument is a string - if not isinstance(values[2], str): - raise TypeError(f"errors must be a string, not {values[2]!r}") + # check that errors argument is a string + if len(values) == 3 and not isinstance(values[2], str): + raise TypeError(f"errors must be a string, not {values[2]!r}") value = str(*values) member = str.__new__(cls, value) member._value_ = value diff --git a/pyproject.toml b/pyproject.toml index b8d939d0..e13085fa 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -147,6 +147,12 @@ ignore = [ "E741", # Ambiguous variable name ] +[tool.ruff.lint.per-file-ignores] +# The top-level facade participates in import cycles that its submodules +# tolerate only via the aliased `import pooltool.x as x` form, whose statement +# order also controls initialization order. +"pooltool/__init__.py" = ["PLR0402"] + [tool.pytest.ini_options] addopts = [ "--import-mode=importlib", diff --git a/sandbox/airborne_demos.py b/sandbox/airborne_demos.py old mode 100644 new mode 100755 diff --git a/sandbox/arena.py b/sandbox/arena.py old mode 100644 new mode 100755 diff --git a/sandbox/ball_cushion_collisions.py b/sandbox/ball_cushion_collisions.py old mode 100644 new mode 100755 index 2b93e295..0d5fc3b4 --- a/sandbox/ball_cushion_collisions.py +++ b/sandbox/ball_cushion_collisions.py @@ -252,17 +252,12 @@ def plot_rebound_angle_vs_incident_angle( ) base_color = base_colors[config_idx % len(base_colors)] - trajectory_idx = 0 num_trajectories = len(results) - for (speed, topspin_factor, sidespin_factor), ( - _, - _, - _, - _, - rebound_angles, - _, - ) in results.items(): + for trajectory_idx, ( + (speed, topspin_factor, sidespin_factor), + (_, _, _, _, rebound_angles, _), + ) in enumerate(results.items()): label = f"{config.model.model}: speed={speed:.3} m/s" if topspin_factors is not None: label += f", topspin_factor={topspin_factor:.2}" @@ -282,7 +277,6 @@ def plot_rebound_angle_vs_incident_angle( opacity=opacity, ) ) - trajectory_idx += 1 fig.update_layout( title=title, @@ -309,17 +303,12 @@ def plot_rebound_speed_vs_incident_angle( ) base_color = base_colors[config_idx % len(base_colors)] - trajectory_idx = 0 num_trajectories = len(results) - for (speed, topspin_factor, sidespin_factor), ( - _, - _, - _, - _, - _, - rebound_speeds, - ) in results.items(): + for trajectory_idx, ( + (speed, topspin_factor, sidespin_factor), + (_, _, _, _, _, rebound_speeds), + ) in enumerate(results.items()): label = f"{config.model.model}: speed={speed:.3} m/s" if topspin_factors is not None: label += f", topspin_factor={topspin_factor:.2}" @@ -338,7 +327,6 @@ def plot_rebound_speed_vs_incident_angle( opacity=opacity, ) ) - trajectory_idx += 1 fig.update_layout( title=title, @@ -369,17 +357,12 @@ def plot_change_in_angular_velocity_vs_incident_angle( ) base_color = base_colors[config_idx % len(base_colors)] - trajectory_idx = 0 num_trajectories = len(results) - for (speed, topspin_factor, sidespin_factor), ( - _, - avel, - _, - outgoing_avel, - _, - _, - ) in results.items(): + for trajectory_idx, ( + (speed, topspin_factor, sidespin_factor), + (_, avel, _, outgoing_avel, _, _), + ) in enumerate(results.items()): label = f"{config.model.model}: speed={speed:.3} m/s" if topspin_factors is not None: label += f", topspin_factor={topspin_factor:.2}" @@ -403,8 +386,6 @@ def plot_change_in_angular_velocity_vs_incident_angle( ) ) - trajectory_idx += 1 - fig.update_layout( title=title, xaxis_title="incident angle (deg)", diff --git a/sandbox/break_forever.py b/sandbox/break_forever.py old mode 100644 new mode 100755 diff --git a/sandbox/collection.py b/sandbox/collection.py old mode 100644 new mode 100755 diff --git a/sandbox/continuize_and_render_timer.py b/sandbox/continuize_and_render_timer.py old mode 100644 new mode 100755 diff --git a/sandbox/custom_table.py b/sandbox/custom_table.py old mode 100644 new mode 100755 diff --git a/sandbox/load.py b/sandbox/load.py old mode 100644 new mode 100755 diff --git a/sandbox/offscreen/offscreen.py b/sandbox/offscreen/offscreen.py old mode 100644 new mode 100755 diff --git a/sandbox/offscreen/timing.py b/sandbox/offscreen/timing.py old mode 100644 new mode 100755 diff --git a/tests/objects/ball/test_datatypes.py b/tests/objects/ball/test_datatypes.py index dea3ad93..7d6e2786 100644 --- a/tests/objects/ball/test_datatypes.py +++ b/tests/objects/ball/test_datatypes.py @@ -98,8 +98,8 @@ def test_ball_history_equality(): history1 = BallHistory(states=[state1]) history2 = BallHistory(states=[state2]) - assert history1 == history1 - assert history2 == history2 + assert history1 == history1 # noqa: PLR0124 + assert history2 == history2 # noqa: PLR0124 assert history1 != history2 diff --git a/tests/objects/table/test_components.py b/tests/objects/table/test_components.py index fde63e8b..0aa5548c 100644 --- a/tests/objects/table/test_components.py +++ b/tests/objects/table/test_components.py @@ -163,7 +163,7 @@ def test_pocket_copy(pocket): assert pocket == copy # center is read only, so its safe that they share the same reference - pocket.center is copy.center # type: ignore + assert pocket.center is copy.center # contains is mutable, so separate objects is necessary assert pocket.contains == copy.contains diff --git a/tests/ptmath/roots/data/_speed_comparison.py b/tests/ptmath/roots/data/_speed_comparison.py index 3af97226..e4103dbb 100644 --- a/tests/ptmath/roots/data/_speed_comparison.py +++ b/tests/ptmath/roots/data/_speed_comparison.py @@ -77,7 +77,9 @@ def main(): print(f"Numba: {numba_mean * 1e6:8.4f} μs ± {numba_std * 1e6:6.4f} μs") benchmark_path = Path(__file__).parent / "_1010_source_code" / "benchmark" - result = subprocess.run([str(benchmark_path)], capture_output=True, text=True) + result = subprocess.run( + [str(benchmark_path)], capture_output=True, text=True, check=True + ) print(result.stdout.strip()) From f53c751b02fe17b13eb1c574a5cd6de28ce5d7e3 Mon Sep 17 00:00:00 2001 From: Evan Kiefl Date: Sun, 2 Aug 2026 13:02:01 -0700 Subject: [PATCH 04/11] Exclude PLR0402 project-wide and restore aliased submodule imports --- pooltool/ai/aim/core.py | 2 +- pooltool/ani/animate.py | 2 +- pooltool/ani/collision.py | 2 +- pooltool/ani/hud.py | 2 +- pooltool/ani/menu/_datatypes.py | 2 +- pooltool/ani/modes/aim.py | 2 +- pooltool/ani/modes/ball_in_hand.py | 4 ++-- pooltool/ani/modes/calculate.py | 2 +- pooltool/ani/modes/call_shot.py | 4 ++-- pooltool/ani/modes/cam_load.py | 2 +- pooltool/ani/modes/cam_save.py | 2 +- pooltool/ani/modes/datatypes.py | 2 +- pooltool/ani/modes/menu.py | 2 +- pooltool/ani/modes/pick_ball.py | 4 ++-- pooltool/ani/modes/purgatory.py | 2 +- pooltool/ani/modes/shot.py | 2 +- pooltool/ani/modes/stroke.py | 2 +- pooltool/ani/modes/view.py | 2 +- pooltool/ani/utils.py | 2 +- pooltool/evolution/continuous.py | 2 +- pooltool/evolution/event_based/detect/ball_ball.py | 2 +- pooltool/evolution/event_based/detect/ball_cushion.py | 4 ++-- pooltool/evolution/event_based/detect/ball_pocket.py | 2 +- .../event_based/detect/ball_position_polynomial.py | 2 +- pooltool/evolution/event_based/detect/detector.py | 2 +- pooltool/evolution/event_based/simulate.py | 2 +- pooltool/objects/ball/datatypes.py | 2 +- pooltool/objects/ball/render.py | 2 +- pooltool/objects/cue/render.py | 2 +- pooltool/objects/table/components.py | 2 +- pooltool/physics/evolve/__init__.py | 2 +- pooltool/physics/resolve/ball_ball/core.py | 2 +- pooltool/physics/resolve/ball_ball/friction.py | 2 +- .../resolve/ball_ball/frictional_inelastic/__init__.py | 2 +- .../resolve/ball_ball/frictionless_elastic/__init__.py | 2 +- pooltool/physics/resolve/ball_cushion/core.py | 2 +- pooltool/physics/resolve/ball_cushion/han_2005/model.py | 2 +- .../physics/resolve/ball_cushion/han_2005/properties.py | 2 +- .../physics/resolve/ball_cushion/mathavan_2010/model.py | 2 +- .../resolve/ball_cushion/stronge_compliant/model.py | 2 +- .../physics/resolve/ball_cushion/unrealistic/__init__.py | 2 +- .../resolve/ball_table/frictional_inelastic/__init__.py | 3 ++- pooltool/physics/resolve/sphere_half_space_collision.py | 2 +- .../resolve/stick_ball/instantaneous_point/__init__.py | 2 +- pooltool/ptmath/__init__.py | 2 +- pooltool/ptmath/roots/__init__.py | 3 ++- pooltool/system/datatypes.py | 2 +- pyproject.toml | 7 +------ sandbox/ball_ball_collisions.py | 2 +- sandbox/ball_cushion_collisions.py | 2 +- tests/evolution/event_based/test_ball_ball.py | 2 +- tests/evolution/event_based/test_simulate.py | 4 +++- tests/test_layouts.py | 2 +- 53 files changed, 61 insertions(+), 62 deletions(-) diff --git a/pooltool/ai/aim/core.py b/pooltool/ai/aim/core.py index 3a02fbe6..852bf398 100644 --- a/pooltool/ai/aim/core.py +++ b/pooltool/ai/aim/core.py @@ -4,7 +4,7 @@ import numpy as np from numpy.typing import NDArray -from pooltool import ptmath +import pooltool.ptmath as ptmath from pooltool.objects.ball.datatypes import Ball from pooltool.system.datatypes import System diff --git a/pooltool/ani/animate.py b/pooltool/ani/animate.py index 022aaf6a..0d109271 100644 --- a/pooltool/ani/animate.py +++ b/pooltool/ani/animate.py @@ -13,8 +13,8 @@ WindowProperties, ) +import pooltool.ani.tasks as tasks import pooltool.ani.utils as autils -from pooltool.ani import tasks from pooltool.ani.camera import CameraState, cam from pooltool.ani.collision import cue_avoid from pooltool.ani.constants import menu_text_scale diff --git a/pooltool/ani/collision.py b/pooltool/ani/collision.py index b555f4f6..0eb7ad3d 100644 --- a/pooltool/ani/collision.py +++ b/pooltool/ani/collision.py @@ -1,7 +1,7 @@ import numpy as np from panda3d.core import CollisionHandlerQueue, CollisionTraverser -from pooltool import ptmath +import pooltool.ptmath as ptmath from pooltool.ani.globals import Global from pooltool.ani.scene import visual from pooltool.config import settings diff --git a/pooltool/ani/hud.py b/pooltool/ani/hud.py index 350607e5..a19445e0 100644 --- a/pooltool/ani/hud.py +++ b/pooltool/ani/hud.py @@ -6,8 +6,8 @@ from direct.interval.LerpInterval import LerpFunc from panda3d.core import CardMaker, NodePath, TextNode, TransparencyAttrib +import pooltool.ani.tasks as tasks import pooltool.ani.utils as autils -from pooltool.ani import tasks from pooltool.ani.constants import ( logo_paths, max_stroke_speed, diff --git a/pooltool/ani/menu/_datatypes.py b/pooltool/ani/menu/_datatypes.py index 00a0e215..b8cf566c 100644 --- a/pooltool/ani/menu/_datatypes.py +++ b/pooltool/ani/menu/_datatypes.py @@ -28,8 +28,8 @@ Vec4, ) +import pooltool.ani.tasks as tasks import pooltool.ani.utils as autils -from pooltool.ani import tasks from pooltool.ani.constants import logo_paths, model_dir from pooltool.ani.fonts import load_font from pooltool.ani.globals import Global diff --git a/pooltool/ani/modes/aim.py b/pooltool/ani/modes/aim.py index abc1f34c..88aa759d 100644 --- a/pooltool/ani/modes/aim.py +++ b/pooltool/ani/modes/aim.py @@ -2,7 +2,7 @@ import numpy as np -from pooltool.ani import tasks +import pooltool.ani.tasks as tasks from pooltool.ani.action import Action from pooltool.ani.camera import cam from pooltool.ani.collision import cue_avoid diff --git a/pooltool/ani/modes/ball_in_hand.py b/pooltool/ani/modes/ball_in_hand.py index 8b4cb23d..bade9659 100644 --- a/pooltool/ani/modes/ball_in_hand.py +++ b/pooltool/ani/modes/ball_in_hand.py @@ -4,10 +4,10 @@ from direct.interval.IntervalGlobal import Parallel from panda3d.core import TransparencyAttrib +import pooltool.ani.tasks as tasks import pooltool.ani.utils as autils import pooltool.constants as c -from pooltool import ptmath -from pooltool.ani import tasks +import pooltool.ptmath as ptmath from pooltool.ani.action import Action from pooltool.ani.camera import cam from pooltool.ani.constants import ball_highlight diff --git a/pooltool/ani/modes/calculate.py b/pooltool/ani/modes/calculate.py index cc220033..7066758a 100644 --- a/pooltool/ani/modes/calculate.py +++ b/pooltool/ani/modes/calculate.py @@ -1,7 +1,7 @@ from typing import ClassVar +import pooltool.ani.tasks as tasks import pooltool.ani.utils as autils -from pooltool.ani import tasks from pooltool.ani.action import Action from pooltool.ani.camera import cam from pooltool.ani.constants import rotate_downtime diff --git a/pooltool/ani/modes/call_shot.py b/pooltool/ani/modes/call_shot.py index 86f31f02..e126709c 100644 --- a/pooltool/ani/modes/call_shot.py +++ b/pooltool/ani/modes/call_shot.py @@ -4,10 +4,10 @@ from direct.interval.IntervalGlobal import LerpFunc, Parallel from panda3d.core import TransparencyAttrib +import pooltool.ani.tasks as tasks import pooltool.ani.utils as autils import pooltool.constants as c -from pooltool import ptmath -from pooltool.ani import tasks +import pooltool.ptmath as ptmath from pooltool.ani.action import Action from pooltool.ani.camera import cam from pooltool.ani.constants import ball_highlight diff --git a/pooltool/ani/modes/cam_load.py b/pooltool/ani/modes/cam_load.py index c5a38a1b..72ba655b 100644 --- a/pooltool/ani/modes/cam_load.py +++ b/pooltool/ani/modes/cam_load.py @@ -2,8 +2,8 @@ from direct.gui.DirectGui import DGG +import pooltool.ani.tasks as tasks import pooltool.ani.utils as autils -from pooltool.ani import tasks from pooltool.ani.action import Action from pooltool.ani.camera import cam from pooltool.ani.globals import Global diff --git a/pooltool/ani/modes/cam_save.py b/pooltool/ani/modes/cam_save.py index 749e57f8..962534bc 100644 --- a/pooltool/ani/modes/cam_save.py +++ b/pooltool/ani/modes/cam_save.py @@ -2,8 +2,8 @@ from direct.gui.DirectGui import DGG +import pooltool.ani.tasks as tasks import pooltool.ani.utils as autils -from pooltool.ani import tasks from pooltool.ani.action import Action from pooltool.ani.camera import cam from pooltool.ani.globals import Global diff --git a/pooltool/ani/modes/datatypes.py b/pooltool/ani/modes/datatypes.py index b055da75..30fa2dc4 100644 --- a/pooltool/ani/modes/datatypes.py +++ b/pooltool/ani/modes/datatypes.py @@ -3,7 +3,7 @@ from abc import ABC, abstractmethod from typing import ClassVar -from pooltool.ani import tasks +import pooltool.ani.tasks as tasks from pooltool.ani.action import Action from pooltool.ani.globals import Global, require_showbase from pooltool.system.datatypes import multisystem diff --git a/pooltool/ani/modes/menu.py b/pooltool/ani/modes/menu.py index ef8f8b55..ccd056f8 100644 --- a/pooltool/ani/modes/menu.py +++ b/pooltool/ani/modes/menu.py @@ -1,7 +1,7 @@ import sys from typing import ClassVar -from pooltool.ani import tasks +import pooltool.ani.tasks as tasks from pooltool.ani.action import Action from pooltool.ani.globals import Global from pooltool.ani.menu import MenuRegistry diff --git a/pooltool/ani/modes/pick_ball.py b/pooltool/ani/modes/pick_ball.py index f6acbdd9..f87c98ed 100644 --- a/pooltool/ani/modes/pick_ball.py +++ b/pooltool/ani/modes/pick_ball.py @@ -4,9 +4,9 @@ import numpy as np +import pooltool.ani.tasks as tasks import pooltool.constants as c -from pooltool import ptmath -from pooltool.ani import tasks +import pooltool.ptmath as ptmath from pooltool.ani.action import Action from pooltool.ani.camera import cam from pooltool.ani.constants import ball_highlight diff --git a/pooltool/ani/modes/purgatory.py b/pooltool/ani/modes/purgatory.py index e2e2d85c..4b0b97b5 100644 --- a/pooltool/ani/modes/purgatory.py +++ b/pooltool/ani/modes/purgatory.py @@ -1,7 +1,7 @@ from typing import ClassVar +import pooltool.ani.tasks as tasks import pooltool.ani.utils as autils -from pooltool.ani import tasks from pooltool.ani.action import Action from pooltool.ani.globals import Global from pooltool.ani.modes.datatypes import BaseMode, Mode diff --git a/pooltool/ani/modes/shot.py b/pooltool/ani/modes/shot.py index f7c6e296..3cd7432b 100644 --- a/pooltool/ani/modes/shot.py +++ b/pooltool/ani/modes/shot.py @@ -1,6 +1,6 @@ from typing import ClassVar -from pooltool.ani import tasks +import pooltool.ani.tasks as tasks from pooltool.ani.action import Action from pooltool.ani.camera import cam from pooltool.ani.collision import cue_avoid diff --git a/pooltool/ani/modes/stroke.py b/pooltool/ani/modes/stroke.py index 15b2b7c7..8d8b5a68 100644 --- a/pooltool/ani/modes/stroke.py +++ b/pooltool/ani/modes/stroke.py @@ -1,7 +1,7 @@ from typing import ClassVar +import pooltool.ani.tasks as tasks import pooltool.ani.utils as autils -from pooltool.ani import tasks from pooltool.ani.action import Action from pooltool.ani.camera import cam from pooltool.ani.constants import ( diff --git a/pooltool/ani/modes/view.py b/pooltool/ani/modes/view.py index 0bbcea16..0370a9da 100644 --- a/pooltool/ani/modes/view.py +++ b/pooltool/ani/modes/view.py @@ -2,7 +2,7 @@ import numpy as np -from pooltool.ani import tasks +import pooltool.ani.tasks as tasks from pooltool.ani.action import Action from pooltool.ani.camera import cam from pooltool.ani.collision import cue_avoid diff --git a/pooltool/ani/utils.py b/pooltool/ani/utils.py index ac9d6d86..2005386b 100644 --- a/pooltool/ani/utils.py +++ b/pooltool/ani/utils.py @@ -17,7 +17,7 @@ Vec4, ) -from pooltool import ptmath +import pooltool.ptmath as ptmath from pooltool.ani.fonts import load_font from pooltool.ani.globals import Global diff --git a/pooltool/evolution/continuous.py b/pooltool/evolution/continuous.py index c704a2db..07f7e8f3 100644 --- a/pooltool/evolution/continuous.py +++ b/pooltool/evolution/continuous.py @@ -8,9 +8,9 @@ import numpy as np from numpy.typing import NDArray +import pooltool.physics.evolve as evolve from pooltool.events import filter_ball from pooltool.objects.ball.datatypes import Ball, BallHistory, BallState -from pooltool.physics import evolve from pooltool.system.datatypes import System diff --git a/pooltool/evolution/event_based/detect/ball_ball.py b/pooltool/evolution/event_based/detect/ball_ball.py index ec967ef2..f654f722 100644 --- a/pooltool/evolution/event_based/detect/ball_ball.py +++ b/pooltool/evolution/event_based/detect/ball_ball.py @@ -7,7 +7,7 @@ from numpy.typing import NDArray import pooltool.constants as const -from pooltool import ptmath +import pooltool.ptmath as ptmath from pooltool.events import Event, EventType, ball_ball_collision, null_event from pooltool.evolution.event_based.cache import CollisionCache from pooltool.evolution.event_based.detect.ball_position_polynomial import ( diff --git a/pooltool/evolution/event_based/detect/ball_cushion.py b/pooltool/evolution/event_based/detect/ball_cushion.py index 8b76b96d..6363358b 100644 --- a/pooltool/evolution/event_based/detect/ball_cushion.py +++ b/pooltool/evolution/event_based/detect/ball_cushion.py @@ -6,7 +6,8 @@ from numpy.typing import NDArray import pooltool.constants as const -from pooltool import ptmath +import pooltool.physics.evolve as evolve +import pooltool.ptmath as ptmath from pooltool.events import ( Event, EventType, @@ -23,7 +24,6 @@ ) from pooltool.objects.ball.datatypes import Ball from pooltool.objects.table.components import LinearCushionSegment -from pooltool.physics import evolve from pooltool.physics.utils import get_u_vec from pooltool.ptmath import quaternion_from_vector_to_vector from pooltool.ptmath.roots import ( diff --git a/pooltool/evolution/event_based/detect/ball_pocket.py b/pooltool/evolution/event_based/detect/ball_pocket.py index 5cf61543..cf70444a 100644 --- a/pooltool/evolution/event_based/detect/ball_pocket.py +++ b/pooltool/evolution/event_based/detect/ball_pocket.py @@ -5,7 +5,7 @@ from numpy.typing import NDArray import pooltool.constants as const -from pooltool import ptmath +import pooltool.ptmath as ptmath from pooltool.events import Event, EventType, ball_pocket_collision, null_event from pooltool.evolution.event_based.cache import CollisionCache from pooltool.physics.utils import get_airborne_time, get_u_vec diff --git a/pooltool/evolution/event_based/detect/ball_position_polynomial.py b/pooltool/evolution/event_based/detect/ball_position_polynomial.py index 4f092cb5..6efb9839 100644 --- a/pooltool/evolution/event_based/detect/ball_position_polynomial.py +++ b/pooltool/evolution/event_based/detect/ball_position_polynomial.py @@ -3,7 +3,7 @@ from numpy.typing import NDArray import pooltool.constants as const -from pooltool import ptmath +import pooltool.ptmath as ptmath from pooltool.physics.utils import tangent_surface_velocity diff --git a/pooltool/evolution/event_based/detect/detector.py b/pooltool/evolution/event_based/detect/detector.py index ce0257f3..914f19e2 100644 --- a/pooltool/evolution/event_based/detect/detector.py +++ b/pooltool/evolution/event_based/detect/detector.py @@ -3,7 +3,7 @@ import attrs import numpy as np -from pooltool import ptmath +import pooltool.ptmath as ptmath from pooltool.events import Event, EventType, null_event from pooltool.evolution.event_based.cache import CollisionCache, TransitionCache from pooltool.evolution.event_based.detect.ball_ball import ( diff --git a/pooltool/evolution/event_based/simulate.py b/pooltool/evolution/event_based/simulate.py index 0f39a02f..a6bd231b 100644 --- a/pooltool/evolution/event_based/simulate.py +++ b/pooltool/evolution/event_based/simulate.py @@ -3,13 +3,13 @@ import attrs import numpy as np +import pooltool.physics.evolve as evolve from pooltool.events import Event, EventType, null_event from pooltool.evolution.continuous import continuize from pooltool.evolution.engine import SimulationEngine from pooltool.evolution.event_based.cache import CollisionCache, TransitionCache from pooltool.evolution.event_based.config import INCLUDED_EVENTS from pooltool.objects.ball.datatypes import BallState -from pooltool.physics import evolve from pooltool.system.datatypes import System DEFAULT_ENGINE = SimulationEngine() diff --git a/pooltool/objects/ball/datatypes.py b/pooltool/objects/ball/datatypes.py index bec5caa0..43f2e01c 100644 --- a/pooltool/objects/ball/datatypes.py +++ b/pooltool/objects/ball/datatypes.py @@ -9,7 +9,7 @@ from numpy.typing import NDArray import pooltool.constants as c -from pooltool import ptmath +import pooltool.ptmath as ptmath from pooltool.objects.ball.params import BallParams from pooltool.objects.ball.sets import BallSet from pooltool.serialize import SerializeFormat, conversion diff --git a/pooltool/objects/ball/render.py b/pooltool/objects/ball/render.py index 2cc4a64a..78ba44e0 100644 --- a/pooltool/objects/ball/render.py +++ b/pooltool/objects/ball/render.py @@ -15,9 +15,9 @@ TransparencyAttrib, ) +import pooltool.ani.tasks as tasks import pooltool.ani.utils as autils import pooltool.constants as c -from pooltool.ani import tasks from pooltool.ani.globals import Global from pooltool.config import settings from pooltool.objects.ball.datatypes import Ball, BallHistory, BallOrientation diff --git a/pooltool/objects/cue/render.py b/pooltool/objects/cue/render.py index 88d01269..71a6b0c3 100644 --- a/pooltool/objects/cue/render.py +++ b/pooltool/objects/cue/render.py @@ -2,7 +2,7 @@ from direct.interval.IntervalGlobal import LerpPosInterval, Sequence from panda3d.core import ClockObject, CollisionNode, CollisionSegment, Vec3 -from pooltool import utils +import pooltool.utils as utils from pooltool.ani.constants import model_dir from pooltool.ani.globals import Global from pooltool.config import settings diff --git a/pooltool/objects/table/components.py b/pooltool/objects/table/components.py index e2976ff3..64f98d73 100644 --- a/pooltool/objects/table/components.py +++ b/pooltool/objects/table/components.py @@ -10,7 +10,7 @@ from attrs import define, evolve, field from numpy.typing import NDArray -from pooltool import ptmath +import pooltool.ptmath as ptmath from pooltool.utils.dataclasses import are_dataclasses_equal diff --git a/pooltool/physics/evolve/__init__.py b/pooltool/physics/evolve/__init__.py index 8fb11b0a..2be196de 100644 --- a/pooltool/physics/evolve/__init__.py +++ b/pooltool/physics/evolve/__init__.py @@ -15,7 +15,7 @@ from numpy.typing import NDArray import pooltool.constants as const -from pooltool import ptmath +import pooltool.ptmath as ptmath from pooltool.physics.utils import ( get_roll_time, get_slide_time, diff --git a/pooltool/physics/resolve/ball_ball/core.py b/pooltool/physics/resolve/ball_ball/core.py index 5746e622..49f8db67 100644 --- a/pooltool/physics/resolve/ball_ball/core.py +++ b/pooltool/physics/resolve/ball_ball/core.py @@ -4,7 +4,7 @@ import numpy as np import pooltool.constants as const -from pooltool import ptmath +import pooltool.ptmath as ptmath from pooltool.objects.ball.datatypes import Ball from pooltool.physics.dimensionality import Dim diff --git a/pooltool/physics/resolve/ball_ball/friction.py b/pooltool/physics/resolve/ball_ball/friction.py index 1c1ef372..ffe4360e 100644 --- a/pooltool/physics/resolve/ball_ball/friction.py +++ b/pooltool/physics/resolve/ball_ball/friction.py @@ -3,7 +3,7 @@ import attrs -from pooltool import ptmath +import pooltool.ptmath as ptmath from pooltool.objects.ball.datatypes import Ball from pooltool.physics.utils import tangent_surface_velocity from pooltool.utils.strenum import StrEnum, auto diff --git a/pooltool/physics/resolve/ball_ball/frictional_inelastic/__init__.py b/pooltool/physics/resolve/ball_ball/frictional_inelastic/__init__.py index 7cebccd0..aa63d6d3 100644 --- a/pooltool/physics/resolve/ball_ball/frictional_inelastic/__init__.py +++ b/pooltool/physics/resolve/ball_ball/frictional_inelastic/__init__.py @@ -3,7 +3,7 @@ from numba import jit import pooltool.constants as const -from pooltool import ptmath +import pooltool.ptmath as ptmath from pooltool.objects.ball.datatypes import Ball, BallState from pooltool.physics.dimensionality import Dim from pooltool.physics.resolve.ball_ball.core import CoreBallBallCollision diff --git a/pooltool/physics/resolve/ball_ball/frictionless_elastic/__init__.py b/pooltool/physics/resolve/ball_ball/frictionless_elastic/__init__.py index 9c343984..5ae5e8f8 100644 --- a/pooltool/physics/resolve/ball_ball/frictionless_elastic/__init__.py +++ b/pooltool/physics/resolve/ball_ball/frictionless_elastic/__init__.py @@ -2,7 +2,7 @@ import numpy as np import pooltool.constants as const -from pooltool import ptmath +import pooltool.ptmath as ptmath from pooltool.objects.ball.datatypes import Ball, BallState from pooltool.physics.dimensionality import Dim from pooltool.physics.resolve.ball_ball.core import CoreBallBallCollision diff --git a/pooltool/physics/resolve/ball_cushion/core.py b/pooltool/physics/resolve/ball_cushion/core.py index c0966ae8..3d4a89bb 100644 --- a/pooltool/physics/resolve/ball_cushion/core.py +++ b/pooltool/physics/resolve/ball_cushion/core.py @@ -4,7 +4,7 @@ import numpy as np import pooltool.constants as const -from pooltool import ptmath +import pooltool.ptmath as ptmath from pooltool.objects.ball.datatypes import Ball from pooltool.objects.table.components import ( CircularCushionSegment, diff --git a/pooltool/physics/resolve/ball_cushion/han_2005/model.py b/pooltool/physics/resolve/ball_cushion/han_2005/model.py index 35a091d6..bce3f30a 100644 --- a/pooltool/physics/resolve/ball_cushion/han_2005/model.py +++ b/pooltool/physics/resolve/ball_cushion/han_2005/model.py @@ -2,7 +2,7 @@ import numpy as np import pooltool.constants as const -from pooltool import ptmath +import pooltool.ptmath as ptmath from pooltool.objects.ball.datatypes import Ball, BallState from pooltool.objects.table.components import ( CircularCushionSegment, diff --git a/pooltool/physics/resolve/ball_cushion/han_2005/properties.py b/pooltool/physics/resolve/ball_cushion/han_2005/properties.py index afbe2329..1b205811 100644 --- a/pooltool/physics/resolve/ball_cushion/han_2005/properties.py +++ b/pooltool/physics/resolve/ball_cushion/han_2005/properties.py @@ -1,7 +1,7 @@ import numpy as np from numpy.typing import NDArray -from pooltool import ptmath +import pooltool.ptmath as ptmath def get_ball_cushion_restitution(rvw: NDArray[np.float64], e_c: float): diff --git a/pooltool/physics/resolve/ball_cushion/mathavan_2010/model.py b/pooltool/physics/resolve/ball_cushion/mathavan_2010/model.py index 5b1fe19c..b3147358 100644 --- a/pooltool/physics/resolve/ball_cushion/mathavan_2010/model.py +++ b/pooltool/physics/resolve/ball_cushion/mathavan_2010/model.py @@ -5,7 +5,7 @@ from numba import jit import pooltool.constants as const -from pooltool import ptmath +import pooltool.ptmath as ptmath from pooltool.objects.ball.datatypes import Ball, BallState from pooltool.objects.table.components import ( CircularCushionSegment, diff --git a/pooltool/physics/resolve/ball_cushion/stronge_compliant/model.py b/pooltool/physics/resolve/ball_cushion/stronge_compliant/model.py index ab71720b..e6cd552a 100644 --- a/pooltool/physics/resolve/ball_cushion/stronge_compliant/model.py +++ b/pooltool/physics/resolve/ball_cushion/stronge_compliant/model.py @@ -4,7 +4,7 @@ import numpy as np import pooltool.constants as const -from pooltool import ptmath +import pooltool.ptmath as ptmath from pooltool.objects.ball.datatypes import Ball, BallState from pooltool.objects.table.components import ( CircularCushionSegment, diff --git a/pooltool/physics/resolve/ball_cushion/unrealistic/__init__.py b/pooltool/physics/resolve/ball_cushion/unrealistic/__init__.py index 7993421e..5c457882 100644 --- a/pooltool/physics/resolve/ball_cushion/unrealistic/__init__.py +++ b/pooltool/physics/resolve/ball_cushion/unrealistic/__init__.py @@ -4,7 +4,7 @@ import numpy as np import pooltool.constants as const -from pooltool import ptmath +import pooltool.ptmath as ptmath from pooltool.objects.ball.datatypes import Ball from pooltool.objects.table.components import ( CircularCushionSegment, diff --git a/pooltool/physics/resolve/ball_table/frictional_inelastic/__init__.py b/pooltool/physics/resolve/ball_table/frictional_inelastic/__init__.py index d9ac20bd..813c3ad7 100644 --- a/pooltool/physics/resolve/ball_table/frictional_inelastic/__init__.py +++ b/pooltool/physics/resolve/ball_table/frictional_inelastic/__init__.py @@ -4,7 +4,8 @@ from numpy.typing import NDArray import pooltool.constants as const -from pooltool import physics, ptmath +import pooltool.physics as physics +import pooltool.ptmath as ptmath from pooltool.objects.ball.datatypes import Ball, BallState from pooltool.physics.resolve.ball_table.core import ( CoreBallTableCollision, diff --git a/pooltool/physics/resolve/sphere_half_space_collision.py b/pooltool/physics/resolve/sphere_half_space_collision.py index fe1b6fa0..3321680f 100644 --- a/pooltool/physics/resolve/sphere_half_space_collision.py +++ b/pooltool/physics/resolve/sphere_half_space_collision.py @@ -3,7 +3,7 @@ from numba import jit import pooltool.constants as const -from pooltool import ptmath +import pooltool.ptmath as ptmath from pooltool.physics.utils import tangent_surface_velocity diff --git a/pooltool/physics/resolve/stick_ball/instantaneous_point/__init__.py b/pooltool/physics/resolve/stick_ball/instantaneous_point/__init__.py index ac168bc5..db227a49 100644 --- a/pooltool/physics/resolve/stick_ball/instantaneous_point/__init__.py +++ b/pooltool/physics/resolve/stick_ball/instantaneous_point/__init__.py @@ -1,7 +1,7 @@ import attrs import numpy as np -from pooltool import ptmath +import pooltool.ptmath as ptmath from pooltool.objects.ball.datatypes import Ball, BallState from pooltool.objects.cue.datatypes import Cue from pooltool.physics.dimensionality import Dim diff --git a/pooltool/ptmath/__init__.py b/pooltool/ptmath/__init__.py index 6cdbbc1d..56b57535 100644 --- a/pooltool/ptmath/__init__.py +++ b/pooltool/ptmath/__init__.py @@ -1,6 +1,6 @@ """Math functions""" -from pooltool.ptmath import roots +import pooltool.ptmath.roots as roots from pooltool.ptmath.utils import ( angle, angle_between_vectors, diff --git a/pooltool/ptmath/roots/__init__.py b/pooltool/ptmath/roots/__init__.py index cc6a8599..f455eac7 100644 --- a/pooltool/ptmath/roots/__init__.py +++ b/pooltool/ptmath/roots/__init__.py @@ -1,4 +1,5 @@ -from pooltool.ptmath.roots import quadratic, quartic +import pooltool.ptmath.roots.quadratic as quadratic +import pooltool.ptmath.roots.quartic as quartic from pooltool.ptmath.roots.core import ( get_real_positive_smallest_root, get_real_positive_smallest_roots, diff --git a/pooltool/system/datatypes.py b/pooltool/system/datatypes.py index 37d4c771..48984c58 100644 --- a/pooltool/system/datatypes.py +++ b/pooltool/system/datatypes.py @@ -7,7 +7,7 @@ from attrs import define, field import pooltool.constants as const -from pooltool import ptmath +import pooltool.ptmath as ptmath from pooltool.events import Event from pooltool.objects.ball.datatypes import Ball, BallHistory from pooltool.objects.ball.sets import BallSet diff --git a/pyproject.toml b/pyproject.toml index e13085fa..6ababd7d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -145,14 +145,9 @@ extend-select = [ ] ignore = [ "E741", # Ambiguous variable name + "PLR0402", # The architecture relies on `import pooltool.x as x` submodule aliasing ] -[tool.ruff.lint.per-file-ignores] -# The top-level facade participates in import cycles that its submodules -# tolerate only via the aliased `import pooltool.x as x` form, whose statement -# order also controls initialization order. -"pooltool/__init__.py" = ["PLR0402"] - [tool.pytest.ini_options] addopts = [ "--import-mode=importlib", diff --git a/sandbox/ball_ball_collisions.py b/sandbox/ball_ball_collisions.py index fb32d626..ba160e72 100644 --- a/sandbox/ball_ball_collisions.py +++ b/sandbox/ball_ball_collisions.py @@ -5,7 +5,7 @@ import plotly.graph_objects as go import plotly.io as pio -from pooltool import ptmath +import pooltool.ptmath as ptmath from pooltool.objects.ball.datatypes import Ball, BallParams from pooltool.physics.resolve.ball_ball.core import BallBallCollisionStrategy diff --git a/sandbox/ball_cushion_collisions.py b/sandbox/ball_cushion_collisions.py index 0d5fc3b4..78f21fdc 100755 --- a/sandbox/ball_cushion_collisions.py +++ b/sandbox/ball_cushion_collisions.py @@ -8,7 +8,7 @@ import plotly.io as pio from numpy.typing import NDArray -from pooltool import ptmath +import pooltool.ptmath as ptmath from pooltool.objects.ball.datatypes import Ball, BallParams from pooltool.objects.table.components import LinearCushionSegment from pooltool.physics.resolve.ball_cushion.core import CoreBallLCushionCollision diff --git a/tests/evolution/event_based/test_ball_ball.py b/tests/evolution/event_based/test_ball_ball.py index b38f424a..f3b0986a 100644 --- a/tests/evolution/event_based/test_ball_ball.py +++ b/tests/evolution/event_based/test_ball_ball.py @@ -3,7 +3,7 @@ import pytest import pooltool.constants as const -from pooltool import ptmath +import pooltool.ptmath as ptmath from pooltool.events import EventType from pooltool.evolution.event_based.cache import CollisionCache from pooltool.evolution.event_based.detect.ball_ball import ( diff --git a/tests/evolution/event_based/test_simulate.py b/tests/evolution/event_based/test_simulate.py index 4e0c77ad..858dffaf 100644 --- a/tests/evolution/event_based/test_simulate.py +++ b/tests/evolution/event_based/test_simulate.py @@ -3,7 +3,9 @@ from numpy.typing import NDArray import pooltool.constants as const -from pooltool import aim, events, physics, ptmath +import pooltool.physics as physics +import pooltool.ptmath as ptmath +from pooltool import aim, events from pooltool.events import EventType, ball_ball_collision, ball_pocket_collision from pooltool.evolution.event_based._utils import _system_has_energy from pooltool.evolution.event_based.cache import CollisionCache diff --git a/tests/test_layouts.py b/tests/test_layouts.py index 0fff9b63..96934961 100644 --- a/tests/test_layouts.py +++ b/tests/test_layouts.py @@ -7,7 +7,7 @@ import pytest from numpy.typing import NDArray -from pooltool import ptmath +import pooltool.ptmath as ptmath from pooltool.game.datatypes import GameType from pooltool.layouts import ( BallPos, From 7d8aa001a1bd9192682f0539305626c7c2ddd310 Mon Sep 17 00:00:00 2001 From: Evan Kiefl Date: Sun, 2 Aug 2026 13:14:34 -0700 Subject: [PATCH 05/11] Remove vestigial getPos call --- pooltool/ani/collision.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/pooltool/ani/collision.py b/pooltool/ani/collision.py index 0eb7ad3d..537bdce7 100644 --- a/pooltool/ani/collision.py +++ b/pooltool/ani/collision.py @@ -107,11 +107,6 @@ def process_cushion_collision(self, entry): self.avoid_nodes["scene"] ) - # Center ofthe cueing ball - _Bx, _By, _Bz = self.avoid_nodes["cue_stick_focus"].getPos( - self.avoid_nodes["scene"] - ) - # The desired point where cue contacts collision plane, excluding cue width Dx, Dy, Dz = Px, Py, cushion_height From a3353fb7fcf4ec1b431d1f4a2ae5a4c6cd5ff772 Mon Sep 17 00:00:00 2001 From: Evan Kiefl Date: Sun, 2 Aug 2026 15:19:07 -0700 Subject: [PATCH 06/11] Remove vestigial cushion p2 unpack --- pooltool/objects/table/render.py | 1 - 1 file changed, 1 deletion(-) diff --git a/pooltool/objects/table/render.py b/pooltool/objects/table/render.py index 3072fff2..c6292f58 100644 --- a/pooltool/objects/table/render.py +++ b/pooltool/objects/table/render.py @@ -60,7 +60,6 @@ def init_collisions(self): cushion = self._table.cushion_segments.linear[cushion_id] x1, y1, z1 = cushion.p1 - _x2, _y2, _z2 = cushion.p2 n1, n2, n3 = cushion.normal if cushion_id in ["9", "12"]: From a7295d08faa94cdf50b69377f3e2a33ac7182aa1 Mon Sep 17 00:00:00 2001 From: Evan Kiefl Date: Sun, 2 Aug 2026 15:21:46 -0700 Subject: [PATCH 07/11] Use ruff's autofix form for can_shoot --- pooltool/ruleset/datatypes.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/pooltool/ruleset/datatypes.py b/pooltool/ruleset/datatypes.py index a56c23c7..f680b79e 100644 --- a/pooltool/ruleset/datatypes.py +++ b/pooltool/ruleset/datatypes.py @@ -132,9 +132,12 @@ def cueball(self, balls: dict[str, Any]) -> str: return self.cueable[0] def can_shoot(self) -> bool: - if not self.call_shot: - return True - return self.ball_call is not None and self.pocket_call is not None + return bool( + self.call_shot + and self.ball_call is not None + and self.pocket_call is not None + or not self.call_shot + ) @attrs.define(frozen=True) From 453fd939ec805243a37dfbf53852787550dea6ef Mon Sep 17 00:00:00 2001 From: Evan Kiefl Date: Sun, 2 Aug 2026 15:32:33 -0700 Subject: [PATCH 08/11] Keep vendored strenum.py as-is with per-file rule exclusions --- pooltool/utils/strenum.py | 22 ++++++++++++---------- pyproject.toml | 4 ++++ 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/pooltool/utils/strenum.py b/pooltool/utils/strenum.py index 4dbecbf4..a2c79653 100644 --- a/pooltool/utils/strenum.py +++ b/pooltool/utils/strenum.py @@ -1,11 +1,11 @@ from __future__ import annotations from enum import Enum, auto -from typing import Any +from typing import Any, TypeVar -from typing_extensions import Self +__all__ = ["auto", "StrEnum"] -__all__ = ["StrEnum", "auto"] +_S = TypeVar("_S", bound="StrEnum") class StrEnum(str, Enum): @@ -13,20 +13,22 @@ class StrEnum(str, Enum): Enum where members are also (and must be) strings """ - def __new__(cls, *values: str) -> Self: + def __new__(cls: type[_S], *values: str) -> _S: if len(values) > 3: raise TypeError(f"too many arguments for str(): {values!r}") - # it must be a string - if len(values) == 1 and not isinstance(values[0], str): - raise TypeError(f"{values[0]!r} is not a string") + if len(values) == 1: + # it must be a string + if not isinstance(values[0], str): + raise TypeError(f"{values[0]!r} is not a string") if len(values) >= 2: # check that encoding argument is a string value = values[1] # type: ignore if not isinstance(value, str): raise TypeError(f"encoding must be a string, not {value!r}") - # check that errors argument is a string - if len(values) == 3 and not isinstance(values[2], str): - raise TypeError(f"errors must be a string, not {values[2]!r}") + if len(values) == 3: + # check that errors argument is a string + if not isinstance(values[2], str): + raise TypeError(f"errors must be a string, not {values[2]!r}") value = str(*values) member = str.__new__(cls, value) member._value_ = value diff --git a/pyproject.toml b/pyproject.toml index 6ababd7d..2311bb39 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -148,6 +148,10 @@ ignore = [ "PLR0402", # The architecture relies on `import pooltool.x as x` submodule aliasing ] +[tool.ruff.lint.per-file-ignores] +# Vendored StrEnum backport, kept byte-faithful to upstream +"pooltool/utils/strenum.py" = ["PYI019", "RUF022", "SIM102"] + [tool.pytest.ini_options] addopts = [ "--import-mode=importlib", From 5f4f5d147c7b118ba26c56abdc7e19435f185588 Mon Sep 17 00:00:00 2001 From: Evan Kiefl Date: Sun, 2 Aug 2026 15:34:13 -0700 Subject: [PATCH 09/11] Ignore all lint rules for vendored strenum.py --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 2311bb39..29bad701 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -150,7 +150,7 @@ ignore = [ [tool.ruff.lint.per-file-ignores] # Vendored StrEnum backport, kept byte-faithful to upstream -"pooltool/utils/strenum.py" = ["PYI019", "RUF022", "SIM102"] +"pooltool/utils/strenum.py" = ["ALL"] [tool.pytest.ini_options] addopts = [ From d892cb7cb21057611088b367427ae794925067b6 Mon Sep 17 00:00:00 2001 From: Evan Kiefl Date: Sun, 2 Aug 2026 15:37:14 -0700 Subject: [PATCH 10/11] Exclude vendored strenum.py from ruff entirely --- pyproject.toml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 29bad701..4c08ec92 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -136,6 +136,7 @@ target-version = "py310" # Minimum supported version line-length = 88 exclude = [ "docs", + "pooltool/utils/strenum.py", # Vendored StrEnum backport, kept byte-faithful to upstream ] [tool.ruff.lint] @@ -148,10 +149,6 @@ ignore = [ "PLR0402", # The architecture relies on `import pooltool.x as x` submodule aliasing ] -[tool.ruff.lint.per-file-ignores] -# Vendored StrEnum backport, kept byte-faithful to upstream -"pooltool/utils/strenum.py" = ["ALL"] - [tool.pytest.ini_options] addopts = [ "--import-mode=importlib", From badcbbe3aad5a561f89b3a9749e6d5da046ee2d1 Mon Sep 17 00:00:00 2001 From: Evan Kiefl Date: Sun, 2 Aug 2026 16:25:00 -0700 Subject: [PATCH 11/11] Bound ruff to <0.17 so lock refreshes can't change lint defaults --- pyproject.toml | 2 +- uv.lock | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 4c08ec92..6e8e0358 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -102,7 +102,7 @@ dev = [ "pytest-cov>=5.0.0", "pre-commit>=3.7.1", "pyright>=1.1.373", - "ruff>=0.5.5", + "ruff>0.16,<0.17", # Diagnostics "psutil>=6.0.0", "ipython>=8.18.1", diff --git a/uv.lock b/uv.lock index 9cf6c771..31165715 100644 --- a/uv.lock +++ b/uv.lock @@ -2438,7 +2438,7 @@ dev = [ { name = "pyright", specifier = ">=1.1.373" }, { name = "pytest", specifier = ">=8.3.2" }, { name = "pytest-cov", specifier = ">=5.0.0" }, - { name = "ruff", specifier = ">=0.5.5" }, + { name = "ruff", specifier = ">0.16,<0.17" }, ] docs = [ { name = "astroid", specifier = "==3.3.11" },