Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
104 changes: 54 additions & 50 deletions Doc/library/turtle.rst
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ Move and draw
.. function:: forward(distance)
fd(distance)

:param distance: a number (integer or float)
:param distance: a number

Move the turtle forward by the specified *distance*, in the direction the
turtle is headed.
Expand All @@ -238,7 +238,7 @@ Move and draw
:param distance: a number

Move the turtle backward by *distance*, opposite to the direction the
turtle is headed. Do not change the turtle's heading.
turtle is headed. The turtle's heading does not change.

.. doctest::
:skipif: _tkinter is None
Expand All @@ -259,11 +259,12 @@ Move and draw
.. function:: right(angle)
rt(angle)

:param angle: a number (integer or float)
:param angle: a number

Turn turtle right by *angle* units. (Units are by default degrees, but
can be set via the :func:`degrees` and :func:`radians` functions.) Angle
orientation depends on the turtle mode, see :func:`mode`.
Turn the turtle right by the specified *angle*. The angle is measured in
degrees by default; the unit can be changed with :func:`degrees` or
:func:`radians`. How the heading is measured depends on the turtle mode,
see :func:`mode`.

.. doctest::
:skipif: _tkinter is None
Expand All @@ -284,11 +285,12 @@ Move and draw
.. function:: left(angle)
lt(angle)

:param angle: a number (integer or float)
:param angle: a number

Turn turtle left by *angle* units. (Units are by default degrees, but
can be set via the :func:`degrees` and :func:`radians` functions.) Angle
orientation depends on the turtle mode, see :func:`mode`.
Turn the turtle left by the specified *angle*. The angle is measured in
degrees by default; the unit can be changed with :func:`degrees` or
:func:`radians`. How the heading is measured depends on the turtle mode,
see :func:`mode`.

.. doctest::
:skipif: _tkinter is None
Expand All @@ -313,11 +315,10 @@ Move and draw
:param x: a number or a pair/vector of numbers
:param y: a number or ``None``

If *y* is ``None``, *x* must be a pair of coordinates or a :class:`Vec2D`
(e.g. as returned by :func:`pos`).

Move turtle to an absolute position. If the pen is down, draw line. Do
not change the turtle's orientation.
Move the turtle to an absolute position. If *y* is ``None``, *x* must be a
pair of coordinates or a :class:`Vec2D`, for example as returned by
:func:`pos`. If the pen is down, a line is drawn. The turtle's heading does
not change.

.. doctest::
:skipif: _tkinter is None
Expand All @@ -331,13 +332,13 @@ Move and draw
>>> tp = turtle.pos()
>>> tp
(0.00,0.00)
>>> turtle.setpos(60,30)
>>> turtle.goto(60,30)
>>> turtle.pos()
(60.00,30.00)
>>> turtle.setpos((20,80))
>>> turtle.goto((20,80))
>>> turtle.pos()
(20.00,80.00)
>>> turtle.setpos(tp)
>>> turtle.goto(tp)
>>> turtle.pos()
(0.00,0.00)

Expand Down Expand Up @@ -382,10 +383,9 @@ Move and draw

.. function:: setx(x)

:param x: a number (integer or float)
:param x: a number

Set the turtle's first coordinate to *x*, leave second coordinate
unchanged.
Set the turtle's x coordinate to *x*. The y coordinate is unchanged.

.. doctest::
:skipif: _tkinter is None
Expand All @@ -405,9 +405,9 @@ Move and draw

.. function:: sety(y)

:param y: a number (integer or float)
:param y: a number

Set the turtle's second coordinate to *y*, leave first coordinate unchanged.
Set the turtle's y coordinate to *y*. The x coordinate is unchanged.

.. doctest::
:skipif: _tkinter is None
Expand All @@ -428,10 +428,10 @@ Move and draw
.. function:: setheading(to_angle)
seth(to_angle)

:param to_angle: a number (integer or float)
:param to_angle: a number

Set the orientation of the turtle to *to_angle*. Here are some common
directions in degrees:
Set the turtle's heading to *to_angle*. Here are some common directions in
degrees:

=================== ====================
standard mode logo mode
Expand All @@ -452,8 +452,9 @@ Move and draw

.. function:: home()

Move turtle to the origin -- coordinates (0,0) -- and set its heading to
its start-orientation (which depends on the mode, see :func:`mode`).
Move the turtle to the origin, coordinates (0,0). The turtle's heading is
set to its start orientation, which depends on the turtle mode, see
:func:`mode`.

.. doctest::
:skipif: _tkinter is None
Expand All @@ -479,20 +480,20 @@ Move and draw
.. function:: circle(radius, extent=None, steps=None)

:param radius: a number
:param extent: a number (or ``None``)
:param steps: an integer (or ``None``)
:param extent: a number or ``None``
:param steps: an integer or ``None``

Draw a circle with given *radius*. The center is *radius* units left of
the turtle; *extent* -- an angle -- determines which part of the circle
is drawn. If *extent* is not given, draw the entire circle. If *extent*
is not a full circle, one endpoint of the arc is the current pen
position. Draw the arc in counterclockwise direction if *radius* is
positive, otherwise in clockwise direction. Finally the direction of the
turtle is changed by the amount of *extent*.
Draw a circle with the given *radius*. The center is *radius* units left
of the turtle; *extent*, an angle, determines which part of the circle is
drawn. If *extent* is not given, draw the entire circle. If *extent* is
not a full circle, one endpoint of the arc is the current pen position.
Draw the arc in counterclockwise direction if *radius* is positive,
otherwise in clockwise direction. Finally, the turtle's heading is changed
by *extent*.

As the circle is approximated by an inscribed regular polygon, *steps*
determines the number of steps to use. If not given, it will be
calculated automatically. May be used to draw regular polygons.
determines the number of steps to use. If not given, it will be calculated
automatically. May be used to draw regular polygons.

.. doctest::
:skipif: _tkinter is None
Expand Down Expand Up @@ -651,7 +652,7 @@ Tell Turtle's state
.. function:: position()
pos()

Return the turtle's current location (x,y) (as a :class:`Vec2D` vector).
Return the turtle's current location (x,y) as a :class:`Vec2D` vector.

.. doctest::
:skipif: _tkinter is None
Expand All @@ -665,9 +666,11 @@ Tell Turtle's state
:param x: a number or a pair/vector of numbers or a turtle instance
:param y: a number if *x* is a number, else ``None``

Return the angle between the line from turtle position to position specified
by (x,y), the vector or the other turtle. This depends on the turtle's start
orientation which depends on the mode - "standard"/"world" or "logo".
Return the angle of the line from the turtle's position to (x,y). If *y* is
``None``, *x* must be a pair of coordinates, a :class:`Vec2D`, for example
as returned by :func:`pos`, or another turtle. The angle is measured from
the turtle's start orientation, which depends on the turtle mode, see
:func:`mode`.

.. doctest::
:skipif: _tkinter is None
Expand Down Expand Up @@ -711,8 +714,8 @@ Tell Turtle's state

.. function:: heading()

Return the turtle's current heading (value depends on the turtle mode, see
:func:`mode`).
Return the turtle's current heading. The value depends on the turtle mode,
see :func:`mode`.

.. doctest::
:skipif: _tkinter is None
Expand All @@ -728,8 +731,9 @@ Tell Turtle's state
:param x: a number or a pair/vector of numbers or a turtle instance
:param y: a number if *x* is a number, else ``None``

Return the distance from the turtle to (x,y), the given vector, or the given
other turtle, in turtle step units.
Return the distance from the turtle to (x,y) in turtle step units. If *y* is
``None``, *x* must be a pair of coordinates, a :class:`Vec2D`, for example
as returned by :func:`pos`, or another turtle.

.. doctest::
:skipif: _tkinter is None
Expand All @@ -752,8 +756,8 @@ Settings for measurement

:param fullcircle: a number

Set angle measurement units, i.e. set number of "degrees" for a full circle.
Default value is 360 degrees.
Set the angle measurement units to degrees. The number of degrees in a full
circle is set to *fullcircle*, which defaults to 360.

.. doctest::
:skipif: _tkinter is None
Expand All @@ -776,7 +780,7 @@ Settings for measurement
.. function:: radians()

Set the angle measurement units to radians. Equivalent to
``degrees(2*math.pi)``.
``degrees(2 * math.pi)``.

.. doctest::
:skipif: _tkinter is None
Expand Down
22 changes: 19 additions & 3 deletions Include/cpython/object.h
Original file line number Diff line number Diff line change
Expand Up @@ -342,9 +342,9 @@ PyAPI_FUNC(PyObject *) _PyObject_FunctionStr(PyObject *);
* `dst` points to a valid object.
*
* Temporary variables are used to only evaluate macro arguments once and so
* avoid the duplication of side effects. _Py_TYPEOF() or memcpy() is used to
* avoid a miscompilation caused by type punning. See Py_CLEAR() comment for
* implementation details about type punning.
* avoid the duplication of side effects. _Py_TYPEOF(), C++ auto, or memcpy()
* is used to avoid a miscompilation caused by type punning. See Py_CLEAR()
* comment for implementation details about type punning.
*
* The memcpy() implementation does not emit a compiler warning if 'src' has
* not the same type than 'src': any pointer type is accepted for 'src'.
Expand All @@ -357,6 +357,14 @@ PyAPI_FUNC(PyObject *) _PyObject_FunctionStr(PyObject *);
*_tmp_dst_ptr = (src); \
Py_DECREF(_tmp_old_dst); \
} while (0)
#elif defined(__cplusplus) && (__cplusplus >= 201103L || _MSVC_LANG >= 201103L)
#define Py_SETREF(dst, src) \
do { \
auto _tmp_dst_ptr = &(dst); \
auto _tmp_old_dst = (*_tmp_dst_ptr); \
*_tmp_dst_ptr = (src); \
Py_DECREF(_tmp_old_dst); \
} while (0)
#else
#define Py_SETREF(dst, src) \
do { \
Expand All @@ -379,6 +387,14 @@ PyAPI_FUNC(PyObject *) _PyObject_FunctionStr(PyObject *);
*_tmp_dst_ptr = (src); \
Py_XDECREF(_tmp_old_dst); \
} while (0)
#elif defined(__cplusplus) && (__cplusplus >= 201103L || _MSVC_LANG >= 201103L)
#define Py_XSETREF(dst, src) \
do { \
auto _tmp_dst_ptr = &(dst); \
auto _tmp_old_dst = (*_tmp_dst_ptr); \
*_tmp_dst_ptr = (src); \
Py_XDECREF(_tmp_old_dst); \
} while (0)
#else
#define Py_XSETREF(dst, src) \
do { \
Expand Down
12 changes: 5 additions & 7 deletions Include/pyport.h
Original file line number Diff line number Diff line change
Expand Up @@ -538,17 +538,15 @@ extern "C" {
//
// Example: _Py_TYPEOF(x) x_copy = (x);
//
// On C23, use typeof(). On C++11, use decltype(). Otherwise, use __typeof__()
// On C23, use typeof(). Otherwise, use __typeof__()
// if on GCC, clang or MSVC 17.9 and newer.
//
// On MSVC, check also _MSVC_LANG since __cplusplus is 199711L unless
// the /Zc:__cplusplus flag is used.
// gh-157649: Do not use decltype() on C++, since it produces invalid code in
// Py_CLEAR()/Py_SETREF().
#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 202311L
# define _Py_TYPEOF(expr) typeof(expr)
#elif defined(__cplusplus) && (__cplusplus >= 201103L || _MSVC_LANG >= 201103L)
# define _Py_TYPEOF(expr) decltype(expr)
#elif defined(__GNUC__) || defined(__clang__) || \
(defined(_MSC_VER) && _MSC_VER >= 1939)
#elif (defined(__GNUC__) || defined(__clang__) \
|| (defined(_MSC_VER) && _MSC_VER >= 1939 && !defined(__cplusplus)))
# define _Py_TYPEOF(expr) __typeof__(expr)
#endif

Expand Down
13 changes: 13 additions & 0 deletions Include/refcount.h
Original file line number Diff line number Diff line change
Expand Up @@ -478,6 +478,9 @@ static inline Py_ALWAYS_INLINE void Py_DECREF(PyObject *op)
* and so avoid type punning. Otherwise, use memcpy() which causes type erasure
* and so prevents the compiler to reuse an old cached 'op' value after
* Py_CLEAR().
*
* On C++11 and newer, use "auto". On MSVC, check also _MSVC_LANG since
* __cplusplus is 199711L unless the /Zc:__cplusplus flag is used.
*/
#ifdef _Py_TYPEOF
#define Py_CLEAR(op) \
Expand All @@ -489,6 +492,16 @@ static inline Py_ALWAYS_INLINE void Py_DECREF(PyObject *op)
Py_DECREF(_tmp_old_op); \
} \
} while (0)
#elif defined(__cplusplus) && (__cplusplus >= 201103L || _MSVC_LANG >= 201103L)
#define Py_CLEAR(op) \
do { \
auto _tmp_op_ptr = &(op); \
auto _tmp_old_op = (*_tmp_op_ptr); \
if (_tmp_old_op != _Py_NULL) { \
*_tmp_op_ptr = _Py_NULL; \
Py_DECREF(_tmp_old_op); \
} \
} while (0)
#else
#define Py_CLEAR(op) \
do { \
Expand Down
16 changes: 16 additions & 0 deletions Lib/test/test_cext/extension.c
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ static PyObject *
test_macros(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args))
{
PyObject *obj, *dict;
PyObject *slots[1];

// test Py_BUILD_ASSERT() and Py_BUILD_ASSERT_EXPR()
Py_BUILD_ASSERT(sizeof(int) == sizeof(unsigned int));
Expand All @@ -97,16 +98,31 @@ test_macros(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args))
Py_CLEAR(obj);
assert(obj == _Py_NULL);

// gh-157649: Test Py_CLEAR() on an array
slots[0] = Py_None;
Py_CLEAR(slots[0]);
assert(slots[0] == _Py_NULL);

#ifndef Py_LIMITED_API
// Test Py_SETREF(): use typeof()/__typeof__() if available, or memcpy()
obj = Py_None;
Py_SETREF(obj, _Py_NULL);
assert(obj == _Py_NULL);

// gh-157649: Test Py_SETREF() on an array
slots[0] = Py_None;
Py_SETREF(slots[0], _Py_NULL);
assert(slots[0] == _Py_NULL);

// Test Py_XSETREF(): use typeof()/__typeof__() if available, or memcpy()
obj = Py_None;
Py_XSETREF(obj, _Py_NULL);
assert(obj == _Py_NULL);

// gh-157649: Test Py_XSETREF() on an array
slots[0] = Py_None;
Py_XSETREF(slots[0], _Py_NULL);
assert(slots[0] == _Py_NULL);
#endif

// Test that Py_BEGIN_CRITICAL_SECTION is available
Expand Down
Loading
Loading