Skip to content

Conversation

@JanEricNitschke
Copy link
Contributor

@JanEricNitschke JanEricNitschke commented Nov 4, 2025

(cherry picked from commit 2462807)

Wasnt 100% sure how to best do this, because all of the TestTurtleScreen and TestTurtle tests didn't exist at all in 3.13. So i just chose the simples way and clicked "accept incoming" on the resolution which added all tests in these classes because i think it makes sense. And obviously added the required imports.

Or should i keep it to the absolutely minimal changes and only do

class TestTurtle(unittest.TestCase):
    def setUp(self):
        with patch_screen():
            self.turtle = turtle.Turtle()

        # Reset the Screen singleton to avoid reference leaks
        self.addCleanup(setattr, turtle.Turtle, '_screen', None)

    def test_dot_signature(self):
        self.turtle.dot()
        self.turtle.dot(10)
        self.turtle.dot(size=10)
        self.turtle.dot((0, 0, 0))
        self.turtle.dot(size=(0, 0, 0))
        self.turtle.dot("blue")
        self.turtle.dot("")
        self.turtle.dot(size="blue")
        self.turtle.dot(20, "blue")
        self.turtle.dot(20, "blue")
        self.turtle.dot(20, (0, 0, 0))
        self.turtle.dot(20, 0, 0, 0)
        with self.assertRaises(TypeError):
            self.turtle.dot(color="blue")
        self.assertRaises(turtle.TurtleGraphicsError, self.turtle.dot, "_not_a_color_")
        self.assertRaises(turtle.TurtleGraphicsError, self.turtle.dot, 0, (0, 0, 0, 0))
        self.assertRaises(turtle.TurtleGraphicsError, self.turtle.dot, 0, 0, 0, 0, 0)
        self.assertRaises(turtle.TurtleGraphicsError, self.turtle.dot, 0, (-1, 0, 0))
        self.assertRaises(turtle.TurtleGraphicsError, self.turtle.dot, 0, -1, 0, 0)
        self.assertRaises(turtle.TurtleGraphicsError, self.turtle.dot, 0, (0, 257, 0))
        self.assertRaises(turtle.TurtleGraphicsError, self.turtle.dot, 0, 0, 257, 0)

@hugovk
Copy link
Member

hugovk commented Nov 4, 2025

Let's keep it minimal and just add test_dot_signature in the TestTurtle class, along with any setup/mocks/imports needed.

It can be another decision whether to backport all the other stuff.

@JanEricNitschke
Copy link
Contributor Author

Should be ready now

Copy link
Member

@hugovk hugovk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you!

Comment on lines +509 to +515
self.turtle.dot(size="blue")
self.turtle.dot(20, "blue")
self.turtle.dot(20, "blue")
self.turtle.dot(20, (0, 0, 0))
self.turtle.dot(20, 0, 0, 0)
with self.assertRaises(TypeError):
self.turtle.dot(color="blue")
Copy link
Contributor

@adorilson adorilson Nov 4, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These lines

self.turtle.dot(size="blue")

and

 with self.assertRaises(TypeError):
      self.turtle.dot(color="blue")

are surprising.

I've tested these and it worked as here, but it doesn't make sense.
And the docs say size is an integer, and color is a color string, as expected.
Is it a bug, alright?

(just checked before open a new issue)

Copy link
Contributor Author

@JanEricNitschke JanEricNitschke Nov 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, it is a bit weird, but the actual logic is:

    def dot(self, size=None, *color):
        """Draw a dot with diameter size, using color.

        Optional arguments:
        size -- an integer >= 1 (if given)
        color -- a colorstring or a numeric color tuple

        Draw a circular dot with diameter size, using color.
        If size is not given, the maximum of pensize+4 and 2*pensize is used.

        Example (for a Turtle instance named turtle):
        >>> turtle.dot()
        >>> turtle.fd(50); turtle.dot(20, "blue"); turtle.fd(50)
        """
        if not color:
            if isinstance(size, (str, tuple)):
                color = self._colorstr(size)
                size = self._pensize + max(self._pensize, 4)
            else:
                color = self._pencolor
                if not size:
                    size = self._pensize + max(self._pensize, 4)
        else:
            if size is None:
                size = self._pensize + max(self._pensize, 4)
            color = self._colorstr(color)

And the correct matching typehint is

    @overload
    def dot(self, size: int | _Color | None = None) -> None: ...
    @overload
    def dot(self, size: int | None, color: _Color, /) -> None: ...
    @overload
    def dot(self, size: int | None, r: float, g: float, b: float, /) -> None: ...

The signature from the docs is

turtle.dot()
turtle.dot(size)
turtle.dot(color, /)
turtle.dot(size, color, /)
turtle.dot(size, r, g, b, /)

This makes it pretty clear the "color" is not a keyword arg, so (color="blue") shouldnt, work. But to make ("blue") and (20) work you have to have (size="blue") be valid, even though is probably isnt desired or recommended.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've opened an issue concerning size="blue": #141062

@hugovk hugovk merged commit 15db242 into python:3.13 Nov 5, 2025
41 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

skip news tests Tests in the Lib/test dir

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants