Skip to content

Commit

Permalink
Merge branch 'main' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
faulhaberben authored Apr 30, 2023
2 parents 4b0dcef + 74a2b79 commit c6a8741
Show file tree
Hide file tree
Showing 4 changed files with 128 additions and 12 deletions.
53 changes: 42 additions & 11 deletions Doc/library/turtle.rst
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ Turtle motion
| :func:`right` | :func:`rt`
| :func:`left` | :func:`lt`
| :func:`goto` | :func:`setpos` | :func:`setposition`
| :func:`teleport`
| :func:`setx`
| :func:`sety`
| :func:`setheading` | :func:`seth`
Expand Down Expand Up @@ -372,6 +373,44 @@ Turtle motion
(0.00,0.00)


.. function:: teleport(x, y=None, *, fill_gap=False)

:param x: a number or ``None``
:param y: a number or ``None``
:param fill_gap: a boolean

Move turtle to an absolute position. Unlike goto(x, y), a line will not
be drawn. The turtle's orientation does not change. If currently
filling, the polygon(s) teleported from will be filled after leaving,
and filling will begin again after teleporting. This can be disabled
with fill_gap=True, which makes the imaginary line traveled during
teleporting act as a fill barrier like in goto(x, y).

.. doctest::
:skipif: _tkinter is None
:hide:

>>> turtle.goto(0, 0)

.. doctest::
:skipif: _tkinter is None

>>> tp = turtle.pos()
>>> tp
(0.00,0.00)
>>> turtle.teleport(60)
>>> turtle.pos()
(60.00,0.00)
>>> turtle.teleport(y=10)
>>> turtle.pos()
(60.00,10.00)
>>> turtle.teleport(20, 30)
>>> turtle.pos()
(20.00,30.00)

.. versionadded: 3.12
.. function:: setx(x)

:param x: a number (integer or float)
Expand Down Expand Up @@ -537,8 +576,7 @@ Turtle motion
:skipif: _tkinter is None

>>> turtle.color("blue")
>>> turtle.stamp()
11
>>> stamp_id = turtle.stamp()
>>> turtle.fd(50)


Expand Down Expand Up @@ -575,15 +613,8 @@ Turtle motion
.. doctest::

>>> for i in range(8):
... turtle.stamp(); turtle.fd(30)
13
14
15
16
17
18
19
20
... unused_stamp_id = turtle.stamp()
... turtle.fd(30)
>>> turtle.clearstamps(2)
>>> turtle.clearstamps(-2)
>>> turtle.clearstamps()
Expand Down
20 changes: 20 additions & 0 deletions Lib/test/test_turtle.py
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,14 @@ def test_goto(self):
self.assertAlmostEqual(self.nav.xcor(), 100)
self.assertAlmostEqual(self.nav.ycor(), -100)

def test_teleport(self):
self.nav.teleport(20, -30, fill_gap=True)
self.assertAlmostEqual(self.nav.xcor(), 20)
self.assertAlmostEqual(self.nav.ycor(), -30)
self.nav.teleport(-20, 30, fill_gap=False)
self.assertAlmostEqual(self.nav.xcor(), -20)
self.assertAlmostEqual(self.nav.ycor(), 30)

def test_pos(self):
self.assertEqual(self.nav.pos(), self.nav._position)
self.nav.goto(100, -100)
Expand Down Expand Up @@ -440,6 +448,18 @@ def test_showturtle_hideturtle_and_isvisible(self):
tpen.showturtle()
self.assertTrue(tpen.isvisible())

def test_teleport(self):

tpen = turtle.TPen()

for fill_gap_value in [True, False]:
tpen.penup()
tpen.teleport(100, 100, fill_gap=fill_gap_value)
self.assertFalse(tpen.isdown())
tpen.pendown()
tpen.teleport(-100, -100, fill_gap=fill_gap_value)
self.assertTrue(tpen.isdown())


if __name__ == '__main__':
unittest.main()
66 changes: 65 additions & 1 deletion Lib/turtle.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@
'pu', 'radians', 'right', 'reset', 'resizemode', 'rt',
'seth', 'setheading', 'setpos', 'setposition', 'settiltangle',
'setundobuffer', 'setx', 'sety', 'shape', 'shapesize', 'shapetransform', 'shearfactor', 'showturtle',
'speed', 'st', 'stamp', 'tilt', 'tiltangle', 'towards',
'speed', 'st', 'stamp', 'teleport', 'tilt', 'tiltangle', 'towards',
'turtlesize', 'undo', 'undobufferentries', 'up', 'width',
'write', 'xcor', 'ycor']
_tg_utilities = ['write_docstringdict', 'done']
Expand Down Expand Up @@ -1614,6 +1614,13 @@ def _goto(self, end):
"""move turtle to position end."""
self._position = end

def teleport(self, x=None, y=None, *, fill_gap: bool = False) -> None:
"""To be overwritten by child class RawTurtle.
Includes no TPen references."""
new_x = x if x is not None else self._position[0]
new_y = y if y is not None else self._position[1]
self._position = Vec2D(new_x, new_y)

def forward(self, distance):
"""Move the turtle forward by the specified distance.
Expand Down Expand Up @@ -2293,6 +2300,15 @@ def fillcolor(self, *args):
else:
return self._color(self._fillcolor)

def teleport(self, x=None, y=None, *, fill_gap: bool = False) -> None:
"""To be overwritten by child class RawTurtle.
Includes no TNavigator references.
"""
pendown = self.isdown()
if pendown:
self.pen(pendown=False)
self.pen(pendown=pendown)

def showturtle(self):
"""Makes the turtle visible.
Expand Down Expand Up @@ -2710,6 +2726,54 @@ def _cc(self, args):
if not ((0 <= r <= 255) and (0 <= g <= 255) and (0 <= b <= 255)):
raise TurtleGraphicsError("bad color sequence: %s" % str(args))
return "#%02x%02x%02x" % (r, g, b)

def teleport(self, x=None, y=None, *, fill_gap: bool = False) -> None:
"""Instantly move turtle to an absolute position.
Arguments:
x -- a number or None
y -- a number None
fill_gap -- a boolean This argument must be specified by name.
call: teleport(x, y) # two coordinates
--or: teleport(x) # teleport to x position, keeping y as is
--or: teleport(y=y) # teleport to y position, keeping x as is
--or: teleport(x, y, fill_gap=True)
# teleport but fill the gap in between
Move turtle to an absolute position. Unlike goto(x, y), a line will not
be drawn. The turtle's orientation does not change. If currently
filling, the polygon(s) teleported from will be filled after leaving,
and filling will begin again after teleporting. This can be disabled
with fill_gap=True, which makes the imaginary line traveled during
teleporting act as a fill barrier like in goto(x, y).
Example (for a Turtle instance named turtle):
>>> tp = turtle.pos()
>>> tp
(0.00,0.00)
>>> turtle.teleport(60)
>>> turtle.pos()
(60.00,0.00)
>>> turtle.teleport(y=10)
>>> turtle.pos()
(60.00,10.00)
>>> turtle.teleport(20, 30)
>>> turtle.pos()
(20.00,30.00)
"""
pendown = self.isdown()
was_filling = self.filling()
if pendown:
self.pen(pendown=False)
if was_filling and not fill_gap:
self.end_fill()
new_x = x if x is not None else self._position[0]
new_y = y if y is not None else self._position[1]
self._position = Vec2D(new_x, new_y)
self.pen(pendown=pendown)
if was_filling and not fill_gap:
self.begin_fill()

def clone(self):
"""Create and return a clone of the turtle.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Added :func:`turtle.teleport` to the :mod:`turtle` module to move a turtle to a new point without tracing a line, visible or invisible. Patch by Liam Gersten.

0 comments on commit c6a8741

Please sign in to comment.