Skip to content

Commit 1281be5

Browse files
committed
fixes, refactors and docs
1 parent 2990746 commit 1281be5

File tree

10 files changed

+128
-62
lines changed

10 files changed

+128
-62
lines changed

buildconfig/stubs/pygame/__init__.pyi

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -646,8 +646,4 @@ from .constants import (
646646
WINDOWSHOWN as WINDOWSHOWN,
647647
WINDOWSIZECHANGED as WINDOWSIZECHANGED,
648648
WINDOWTAKEFOCUS as WINDOWTAKEFOCUS,
649-
)
650-
from .geometry import (
651-
Circle as Circle,
652-
CircleType as CircleType
653649
)

buildconfig/stubs/pygame/geometry.py renamed to buildconfig/stubs/pygame/geometry.pyi

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,10 @@ def __init__(self, x: float, y: float, r: float) -> None: ...
1313
@overload
1414
def __init__(self, pos: Sequence[float], r: float) -> None: ...
1515
@overload
16-
def __init__(self, circle) -> None: ...
17-
def __copy__(self) -> "Circle": ...
16+
def __init__(self, circle: Circle) -> None: ...
17+
@overload
18+
def __init__(self, obj_with_circle_attr) -> None: ...
19+
def __copy__(self) -> Circle: ...
1820
copy = __copy__
1921

2022
CircleType = Circle

docs/reST/ext/boilerplate.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -337,6 +337,7 @@ def lowercase_name(d):
337337
"music",
338338
"pygame",
339339
"Rect",
340+
"geometry",
340341
"Surface",
341342
"sprite",
342343
"time",

docs/reST/index.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,9 @@ Reference
179179
:doc:`ref/rect`
180180
Flexible container for a rectangle.
181181

182+
:doc:`ref/geometry`
183+
Geometry types and operations.
184+
182185
:doc:`ref/scrap`
183186
Native clipboard access.
184187

docs/reST/ref/geometry.rst

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
.. include:: common.txt
2+
3+
:mod:`pygame.geometry`
4+
======================
5+
6+
.. module:: pygame.geometry
7+
:synopsis: pygame geometry module
8+
9+
| :sl:`pygame module for the Circle, Rect, and Polygon objects`
10+
11+
.. currentmodule:: pygame
12+
13+
.. class:: Circle
14+
15+
| :sl:`pygame object representing a circle`
16+
| :sg:`Circle(center, radius) -> Circle`
17+
| :sg:`Circle(x, y, radius) -> Circle`
18+
| :sg:`Circle(object) -> Circle`
19+
20+
.. attribute:: x
21+
22+
| :sl:`center x coordinate of the circle`
23+
| :sg:`x -> float`
24+
25+
The `x` coordinate of the center of the circle.
26+
27+
.. ## Circle.x ##
28+
29+
.. attribute:: y
30+
31+
| :sl:`center y coordinate of the circle`
32+
| :sg:`y -> float`
33+
34+
The `y` coordinate of the center of the circle.
35+
36+
.. ## Circle.y ##
37+
38+
.. attribute:: r
39+
40+
| :sl:`radius of the circle`
41+
| :sg:`r -> float`
42+
43+
The `r` coordinate of the center of the circle. You cannot set the radius to a negative value.
44+
45+
.. ## Circle.r ##
46+
47+
.. method:: copy
48+
49+
| :sl:`returns a copy of the circle`
50+
| :sg:`copy() -> Circle`
51+
52+
The `copy` method returns a new `Circle` object having the same position and radius
53+
as the original `Circle`. The function takes no arguments.
54+
55+
.. ## Circle.copy ##
56+
57+
.. ## pygame.Circle ##

docs/reST/themes/classic/elements.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ <h5>pygame-ce documentation</h5>
4040
We render three sets of items based on how useful to most apps.
4141

4242
#}
43-
{%- set basic = ['Color', 'display', 'draw', 'event', 'font', 'image', 'key', 'locals', 'mixer', 'mouse', 'music', 'pygame', 'Rect', 'Surface', 'time'] %}
43+
{%- set basic = ['Color', 'display', 'draw', 'event', 'font', 'image', 'key', 'locals', 'mixer', 'mouse', 'music', 'pygame', 'Rect', 'geometry', 'Surface', 'time'] %}
4444
{%- set advanced = ['BufferProxy', 'freetype', 'gfxdraw', 'midi', 'PixelArray', 'pixelcopy', 'sndarray', 'surfarray', 'cursors', 'joystick', 'mask', 'math', 'sprite', 'transform'] %}
4545
{%- set hidden = ['Overlay', 'cdrom', 'sdl2_video', 'sdl2_controller'] %}
4646
{%- if pyg_sections %}

src_c/circle.c

Lines changed: 55 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#include "geometry.h"
2+
#include "doc/geometry_doc.h"
23

34
static PyObject *
45
_pg_circle_subtype_new(PyTypeObject *type, pgCircleBase *circle)
@@ -34,13 +35,14 @@ pgCircle_FromObject(PyObject *obj, pgCircleBase *out)
3435
return 1;
3536
}
3637

38+
/* Paths for sequences */
3739
if (pgSequenceFast_Check(obj)) {
3840
PyObject **f_arr = PySequence_Fast_ITEMS(obj);
3941
length = PySequence_Fast_GET_SIZE(obj);
4042

4143
if (length == 3) {
42-
if (!pg_DoubleFromObj(f_arr[0], &(out->x)) ||
43-
!pg_DoubleFromObj(f_arr[1], &(out->y)) ||
44+
if (!pg_DoubleFromObj(f_arr[0], &out->x) ||
45+
!pg_DoubleFromObj(f_arr[1], &out->y) ||
4446
!_pg_circle_set_radius(f_arr[2], out)) {
4547
return 0;
4648
}
@@ -53,7 +55,7 @@ pgCircle_FromObject(PyObject *obj, pgCircleBase *out)
5355
return 1;
5456
}
5557
else if (length == 2) {
56-
if (!pg_TwoDoublesFromObj(f_arr[0], &(out->x), &(out->y)) ||
58+
if (!pg_TwoDoublesFromObj(f_arr[0], &out->x, &out->y) ||
5759
!_pg_circle_set_radius(f_arr[1], out)) {
5860
return 0;
5961
}
@@ -66,21 +68,20 @@ pgCircle_FromObject(PyObject *obj, pgCircleBase *out)
6668
}
6769
}
6870
else if (PySequence_Check(obj)) {
69-
/* Path for other sequences or Types that count as sequences*/
7071
PyObject *tmp = NULL;
7172
length = PySequence_Length(obj);
7273
if (length == 3) {
7374
/*These are to be substituted with better pg_DoubleFromSeqIndex()
7475
* implementations*/
7576
tmp = PySequence_ITEM(obj, 0);
76-
if (!pg_DoubleFromObj(tmp, &(out->x))) {
77+
if (!pg_DoubleFromObj(tmp, &out->x)) {
7778
Py_DECREF(tmp);
7879
return 0;
7980
}
8081
Py_DECREF(tmp);
8182

8283
tmp = PySequence_ITEM(obj, 1);
83-
if (!pg_DoubleFromObj(tmp, &(out->y))) {
84+
if (!pg_DoubleFromObj(tmp, &out->y)) {
8485
Py_DECREF(tmp);
8586
return 0;
8687
}
@@ -97,7 +98,7 @@ pgCircle_FromObject(PyObject *obj, pgCircleBase *out)
9798
}
9899
else if (length == 2) {
99100
tmp = PySequence_ITEM(obj, 0);
100-
if (!pg_TwoDoublesFromObj(tmp, &(out->x), &(out->y))) {
101+
if (!pg_TwoDoublesFromObj(tmp, &out->x, &out->y)) {
101102
Py_DECREF(tmp);
102103
return 0;
103104
}
@@ -128,41 +129,41 @@ pgCircle_FromObject(PyObject *obj, pgCircleBase *out)
128129
}
129130
}
130131

131-
if (PyObject_HasAttrString(obj, "circle")) {
132-
PyObject *circleattr;
133-
circleattr = PyObject_GetAttrString(obj, "circle");
134-
if (!circleattr) {
135-
PyErr_Clear();
136-
return 0;
137-
}
138-
if (PyCallable_Check(circleattr)) /*call if it's a method*/
139-
{
140-
PyObject *circleresult = PyObject_CallObject(circleattr, NULL);
141-
Py_DECREF(circleattr);
142-
if (!circleresult) {
143-
PyErr_Clear();
144-
return 0;
145-
}
146-
circleattr = circleresult;
147-
}
148-
if (!pgCircle_FromObject(circleattr, out)) {
132+
/* Path for objects that have a circle attribute */
133+
PyObject *circleattr;
134+
if (!(circleattr = PyObject_GetAttrString(obj, "circle"))) {
135+
PyErr_Clear();
136+
return 0;
137+
}
138+
139+
if (PyCallable_Check(circleattr)) /*call if it's a method*/
140+
{
141+
PyObject *circleresult = PyObject_CallObject(circleattr, NULL);
142+
Py_DECREF(circleattr);
143+
if (!circleresult) {
149144
PyErr_Clear();
150-
Py_DECREF(circleattr);
151145
return 0;
152146
}
153-
Py_DECREF(circleattr);
147+
circleattr = circleresult;
148+
}
154149

155-
return 1;
150+
if (!pgCircle_FromObject(circleattr, out)) {
151+
PyErr_Clear();
152+
Py_DECREF(circleattr);
153+
return 0;
156154
}
157-
return 0;
155+
156+
Py_DECREF(circleattr);
157+
158+
return 1;
158159
}
159160

160161
static PyObject *
161162
pg_circle_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
162163
{
163164
pgCircleObject *self = (pgCircleObject *)type->tp_alloc(type, 0);
164165

165-
if (self != NULL) {
166+
if (self) {
166167
self->circle.x = self->circle.y = 0;
167168
self->circle.r = 1;
168169
self->weakreflist = NULL;
@@ -174,18 +175,19 @@ static int
174175
pg_circle_init(pgCircleObject *self, PyObject *args, PyObject *kwds)
175176
{
176177
if (!pgCircle_FromObject(args, &self->circle)) {
177-
PyErr_SetString(PyExc_TypeError,
178-
"Argument must be Circle style object");
178+
PyErr_SetString(
179+
PyExc_TypeError,
180+
"Arguments must be a Circle, a sequence of length 3 or 2, or an "
181+
"object with an attribute called 'circle'");
179182
return -1;
180183
}
181-
182184
return 0;
183185
}
184186

185187
static void
186188
pg_circle_dealloc(pgCircleObject *self)
187189
{
188-
if (self->weakreflist != NULL) {
190+
if (self->weakreflist) {
189191
PyObject_ClearWeakRefs((PyObject *)self);
190192
}
191193

@@ -235,11 +237,11 @@ pg_circle_str(pgCircleObject *self)
235237
}
236238

237239
static struct PyMethodDef pg_circle_methods[] = {
238-
{"__copy__", (PyCFunction)pg_circle_copy, METH_NOARGS, NULL},
239-
{"copy", (PyCFunction)pg_circle_copy, METH_NOARGS, NULL},
240+
{"__copy__", (PyCFunction)pg_circle_copy, METH_NOARGS, DOC_CIRCLE_COPY},
241+
{"copy", (PyCFunction)pg_circle_copy, METH_NOARGS, DOC_CIRCLE_COPY},
240242
{NULL, NULL, 0, NULL}};
241243

242-
#define GETSET_FOR_SIMPLE(name) \
244+
#define GETTER_SETTER(name) \
243245
static PyObject *pg_circle_get##name(pgCircleObject *self, void *closure) \
244246
{ \
245247
return PyFloat_FromDouble(self->circle.name); \
@@ -249,19 +251,19 @@ static struct PyMethodDef pg_circle_methods[] = {
249251
{ \
250252
double val; \
251253
DEL_ATTR_NOT_SUPPORTED_CHECK_NO_NAME(value); \
252-
if (pg_DoubleFromObj(value, &val)) { \
253-
self->circle.name = val; \
254-
return 0; \
254+
if (!pg_DoubleFromObj(value, &val)) { \
255+
PyErr_Format(PyExc_TypeError, "Expected a number, got '%s'", \
256+
Py_TYPE(value)->tp_name); \
257+
return -1; \
255258
} \
256-
PyErr_SetString(PyExc_TypeError, "Expected a number"); \
257-
return -1; \
259+
self->circle.name = val; \
260+
return 0; \
258261
}
259262

260-
// they are repetitive enough that we can abstract them like this
261-
GETSET_FOR_SIMPLE(x)
262-
GETSET_FOR_SIMPLE(y)
263+
GETTER_SETTER(x)
264+
GETTER_SETTER(y)
263265

264-
#undef GETSET_FOR_SIMPLE
266+
#undef GETTER_SETTER
265267

266268
static PyObject *
267269
pg_circle_getr(pgCircleObject *self, void *closure)
@@ -277,13 +279,13 @@ pg_circle_setr(pgCircleObject *self, PyObject *value, void *closure)
277279
DEL_ATTR_NOT_SUPPORTED_CHECK_NO_NAME(value);
278280

279281
if (!pg_DoubleFromObj(value, &radius)) {
280-
PyErr_SetString(PyExc_TypeError,
281-
"Invalid type for radius, must be numeric");
282+
PyErr_Format(PyExc_TypeError, "Expected a number, got '%s'",
283+
Py_TYPE(value)->tp_name);
282284
return -1;
283285
}
284286

285287
if (radius <= 0) {
286-
PyErr_SetString(PyExc_ValueError, "Invalid radius value, must be > 0");
288+
PyErr_SetString(PyExc_ValueError, "Radius must be positive");
287289
return -1;
288290
}
289291

@@ -293,9 +295,9 @@ pg_circle_setr(pgCircleObject *self, PyObject *value, void *closure)
293295
}
294296

295297
static PyGetSetDef pg_circle_getsets[] = {
296-
{"x", (getter)pg_circle_getx, (setter)pg_circle_setx, NULL, NULL},
297-
{"y", (getter)pg_circle_gety, (setter)pg_circle_sety, NULL, NULL},
298-
{"r", (getter)pg_circle_getr, (setter)pg_circle_setr, NULL, NULL},
298+
{"x", (getter)pg_circle_getx, (setter)pg_circle_setx, DOC_CIRCLE_X, NULL},
299+
{"y", (getter)pg_circle_gety, (setter)pg_circle_sety, DOC_CIRCLE_Y, NULL},
300+
{"r", (getter)pg_circle_getr, (setter)pg_circle_setr, DOC_CIRCLE_R, NULL},
299301
{NULL, 0, NULL, NULL, NULL}};
300302

301303
static PyTypeObject pgCircle_Type = {
@@ -305,7 +307,7 @@ static PyTypeObject pgCircle_Type = {
305307
.tp_repr = (reprfunc)pg_circle_repr,
306308
.tp_str = (reprfunc)pg_circle_str,
307309
.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
308-
.tp_doc = NULL,
310+
.tp_doc = DOC_CIRCLE,
309311
.tp_weaklistoffset = offsetof(pgCircleObject, weakreflist),
310312
.tp_methods = pg_circle_methods,
311313
.tp_getset = pg_circle_getsets,

src_c/doc/geometry_doc.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
/* Auto generated file: with makeref.py . Docs go in docs/reST/ref/ . */
2+
#define DOC_GEOMETRY "pygame module for the Circle, Rect, and Polygon objects"
3+
#define DOC_CIRCLE "Circle(center, radius) -> Circle\nCircle(x, y, radius) -> Circle\nCircle(object) -> Circle\npygame object representing a circle"
4+
#define DOC_CIRCLE_X "x -> float\ncenter x coordinate of the circle"
5+
#define DOC_CIRCLE_Y "y -> float\ncenter y coordinate of the circle"
6+
#define DOC_CIRCLE_R "r -> float\nradius of the circle"
7+
#define DOC_CIRCLE_COPY "copy() -> Circle\nreturns a copy of the circle"

src_c/geometry.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ MODINIT_DEFINE(geometry)
2525
return NULL;
2626
}
2727

28-
/* create the module */
2928
module = PyModule_Create(&_module);
3029
if (!module) {
3130
return NULL;

src_c/geometry.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ typedef struct {
2222

2323
static PyTypeObject pgCircle_Type;
2424

25-
// return 1 if success and 0 if failure
2625
static int
2726
pgCircle_FromObject(PyObject *obj, pgCircleBase *out);
2827

0 commit comments

Comments
 (0)