From bbedc0abd2b110cce36d3e784ad5dae6174a17ab Mon Sep 17 00:00:00 2001 From: zoldalma <46655437+zoldalma999@users.noreply.github.com> Date: Sun, 20 Oct 2024 20:19:21 +0200 Subject: [PATCH 1/8] Generate reST/ref docs from python or stub files --- buildconfig/stubs/gen_stubs.py | 2 + buildconfig/stubs/pygame/__init__.pyi | 2 +- docs/reST/conf.py | 19 ++++- docs/reST/ext/documenters.py | 112 ++++++++++++++++++++++++++ docs/reST/ext/indexer.py | 2 +- pyproject.toml | 1 + src_py/camera.py | 4 +- 7 files changed, 135 insertions(+), 7 deletions(-) create mode 100644 docs/reST/ext/documenters.py diff --git a/buildconfig/stubs/gen_stubs.py b/buildconfig/stubs/gen_stubs.py index 488ba2cfc7..7b2c60d4c7 100644 --- a/buildconfig/stubs/gen_stubs.py +++ b/buildconfig/stubs/gen_stubs.py @@ -131,6 +131,8 @@ def get_all(mod: Any): f.write(misc_stubs) for mod, items in pygame_all_imports.items(): + if mod == "pygame": + mod = "." if len(items) <= 4: # try to write imports in a single line if it can fit the line limit import_items = (f"{string} as {string}" for string in items) diff --git a/buildconfig/stubs/pygame/__init__.pyi b/buildconfig/stubs/pygame/__init__.pyi index ffb58f4cdb..e1e404ed37 100644 --- a/buildconfig/stubs/pygame/__init__.pyi +++ b/buildconfig/stubs/pygame/__init__.pyi @@ -2,7 +2,7 @@ # A script to auto-generate locals.pyi, constants.pyi and __init__.pyi typestubs # IMPORTANT NOTE: Do not edit this file by hand! -from pygame import ( +from . import ( display as display, draw as draw, event as event, diff --git a/docs/reST/conf.py b/docs/reST/conf.py index 136a723ae3..25b927c8e9 100644 --- a/docs/reST/conf.py +++ b/docs/reST/conf.py @@ -10,7 +10,7 @@ # All configuration values have a default; values that are commented out # serve to show the default. -import sys, os +import sys, os, pathlib # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the @@ -23,11 +23,22 @@ # Add any Sphinx extension module names here, as strings. They can be extensions # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. -extensions = ['sphinx.ext.autodoc', 'sphinx.ext.doctest', - 'sphinx.ext.coverage', 'ext.headers', 'ext.boilerplate', - 'ext.customversion', 'ext.edit_on_github'] +extensions = ['autoapi.extension', 'ext.headers', 'ext.boilerplate', + 'ext.customversion', 'ext.edit_on_github', 'ext.documenters'] +autoapi_dirs = [ + pathlib.Path(os.path.abspath(".")).parent.parent / 'buildconfig' / 'stubs' / 'pygame' / '', + pathlib.Path(os.path.abspath(".")).parent.parent / 'src_py' / '', +] + +autoapi_options = ['members', 'undoc-members'] +autoapi_ignore = ["*controller.py", "*_sdl2/window.py", "*freetype.py", "*ftfont.py", "*__pyinstaller*", "*__init__.py", "*__briefcase*"] +autoapi_generate_api_docs = False +autodoc_typehints = 'none' +suppress_warnings = ['autoapi.python_import_resolution'] +autodoc_member_order = 'bysource' + # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] diff --git a/docs/reST/ext/documenters.py b/docs/reST/ext/documenters.py new file mode 100644 index 0000000000..53514d112f --- /dev/null +++ b/docs/reST/ext/documenters.py @@ -0,0 +1,112 @@ +import autoapi +import autoapi.documenters +from autoapi._objects import PythonClass + + +def build_signatures(object): + name = object.short_name + + if isinstance(object, PythonClass): + if object.constructor is not None: + object = object.constructor + object.obj["return_annotation"] = name + object.obj["overloads"] = [ + (arg, name) for arg, _ in object.obj["overloads"] + ] + + else: + for child in object.children: + if child.short_name == "__new__": + object = child + break + + if object is None: + return + + sigs = [(object.obj["args"], object.obj["return_annotation"])] + sigs.extend(object.obj["overloads"]) + + for args, ret in sigs: + arg_string = "" + for modifier, arg_name, _, default in args: + modifier = modifier or "" + arg_name = arg_name or "" + default = default or "" + + if default: + default = "=" + default + arg_string += f", {modifier}{arg_name}{default}" + + if arg_string: + arg_string = arg_string[2:] + + if ret.count("[") > 2 or ret.count(",") > 3: + ret = "..." + + yield f"| :sg:`{name}({arg_string}) -> {ret}`" + + +class AutopgDocumenter(autoapi.documenters.AutoapiDocumenter): + def format_signature(self, **kwargs): + return "" + + def get_doc(self, encoding=None, ignore=1): + if self.object.docstring: + return super().get_doc(encoding, ignore) + + # If we don't already have docs, check if a python implementation exists of this + # module and return its docstring if it does + python_object = self.env.autoapi_all_objects.get( + self.object.id.replace("pygame", "src_py"), None + ) + if python_object is not None: + return [python_object.docstring.splitlines()] + + return [""] + + def process_doc(self, docstrings: list[str]): + for docstring in docstrings: + if not docstring: + continue + + yield f"| :sl:`{docstring[0]}`" + + if "args" in self.object.obj or hasattr(self.object, "constructor"): + yield from build_signatures(self.object) + else: + annotation = self.object.obj.get("annotation", None) + if annotation is not None: + if annotation.count("[") > 2 or annotation.count(",") > 3: + annotation = "..." + yield f"| :sg:`{self.object.short_name} -> {annotation}`" + + yield from docstring[1:] + + yield "" + + +def setup(app): + names = [ + "function", + "property", + "decorator", + "class", + "method", + "data", + "attribute", + "module", + "exception", + ] + + for name in names: + capitalized = name.capitalize() + app.add_autodocumenter( + type( + f"Autopg{capitalized}Documenter", + ( + AutopgDocumenter, + getattr(autoapi.documenters, f"Autoapi{capitalized}Documenter"), + ), + {"objtype": f"pg{name}"}, + ) + ) diff --git a/docs/reST/ext/indexer.py b/docs/reST/ext/indexer.py index 2ece8dfd64..1eab793211 100644 --- a/docs/reST/ext/indexer.py +++ b/docs/reST/ext/indexer.py @@ -65,7 +65,6 @@ def collect_document_info(app, doctree): class CollectInfo(Visitor): - """Records the information for a document""" desctypes = { @@ -74,6 +73,7 @@ class CollectInfo(Visitor): "exception", "class", "attribute", + "property", "method", "staticmethod", "classmethod", diff --git a/pyproject.toml b/pyproject.toml index 476a08242e..8713c3d411 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -59,6 +59,7 @@ requires = [ "ninja<=1.11.1.1", "cython<=3.0.11", "sphinx<=7.2.6", + "autoapi<=3.3.2", ] build-backend = 'mesonpy' diff --git a/src_py/camera.py b/src_py/camera.py index 2a5db6c4f2..971efd9031 100644 --- a/src_py/camera.py +++ b/src_py/camera.py @@ -56,7 +56,9 @@ def _pre_init_placeholder_varargs(*_, **__): class _PreInitPlaceholderCamera(AbstractCamera): - __init__ = _pre_init_placeholder_varargs + def __init__(self, *args, **kwargs): + _pre_init_placeholder() + start = _pre_init_placeholder_varargs stop = _pre_init_placeholder_varargs get_controls = _pre_init_placeholder_varargs From 9258b191e0db906e81a1229a37b59f3e622e9cb9 Mon Sep 17 00:00:00 2001 From: zoldalma <46655437+zoldalma999@users.noreply.github.com> Date: Mon, 21 Oct 2024 22:57:37 +0200 Subject: [PATCH 2/8] Move cursors docs to python source --- docs/reST/ref/cursors.rst | 244 +------------------------------------- src_c/doc/cursors_doc.h | 14 +-- src_py/cursors.py | 238 ++++++++++++++++++++++++++++++------- 3 files changed, 203 insertions(+), 293 deletions(-) diff --git a/docs/reST/ref/cursors.rst b/docs/reST/ref/cursors.rst index c45af2a973..ad90f09126 100644 --- a/docs/reST/ref/cursors.rst +++ b/docs/reST/ref/cursors.rst @@ -3,248 +3,12 @@ :mod:`pygame.cursors` ===================== -.. module:: pygame.cursors - :synopsis: pygame module for cursor resources +.. autopgmodule:: pygame.cursors + :members: compile, load_xbm -| :sl:`pygame module for cursor resources` -Pygame offers control over the system hardware cursor. Pygame supports -black and white cursors (bitmap cursors), as well as system variant cursors and color cursors. -You control the cursor with functions inside :mod:`pygame.mouse`. - -This cursors module contains functions for loading and decoding various -cursor formats. These allow you to easily store your cursors in external files -or directly as encoded python strings. - -The module includes several standard cursors. The :func:`pygame.mouse.set_cursor()` -function takes several arguments. All those arguments have been stored in a -single tuple you can call like this: - -:: - - >>> pygame.mouse.set_cursor(*pygame.cursors.arrow) - -The following variables can be passed to ``pygame.mouse.set_cursor`` function: - - * ``pygame.cursors.arrow`` - - * ``pygame.cursors.diamond`` - - * ``pygame.cursors.broken_x`` - - * ``pygame.cursors.tri_left`` - - * ``pygame.cursors.tri_right`` - -This module also contains a few cursors as formatted strings. You'll need to -pass these to ``pygame.cursors.compile()`` function before you can use them. -The example call would look like this: - -:: - - >>> cursor = pygame.cursors.compile(pygame.cursors.textmarker_strings) - >>> pygame.mouse.set_cursor((8, 16), (0, 0), *cursor) - -The following strings can be converted into cursor bitmaps with -``pygame.cursors.compile()`` : - - * ``pygame.cursors.thickarrow_strings`` - - * ``pygame.cursors.sizer_x_strings`` - - * ``pygame.cursors.sizer_y_strings`` - - * ``pygame.cursors.sizer_xy_strings`` - - * ``pygame.cursor.textmarker_strings`` - -.. function:: compile - - | :sl:`create binary cursor data from simple strings` - | :sg:`compile(strings, black='X', white='.', xor='o') -> data, mask` - - A sequence of strings can be used to create binary cursor data for the - system cursor. This returns the binary data in the form of two tuples. - Those can be passed as the third and fourth arguments respectively of the - :func:`pygame.mouse.set_cursor()` function. - - If you are creating your own cursor strings, you can use any value represent - the black and white pixels. Some system allow you to set a special toggle - color for the system color, this is also called the xor color. If the system - does not support xor cursors, that color will simply be black. - - The height must be divisible by 8. The width of the strings must all be equal - and be divisible by 8. If these two conditions are not met, ``ValueError`` is - raised. - An example set of cursor strings looks like this - - :: - - thickarrow_strings = ( #sized 24x24 - "XX ", - "XXX ", - "XXXX ", - "XX.XX ", - "XX..XX ", - "XX...XX ", - "XX....XX ", - "XX.....XX ", - "XX......XX ", - "XX.......XX ", - "XX........XX ", - "XX........XXX ", - "XX......XXXXX ", - "XX.XXX..XX ", - "XXXX XX..XX ", - "XX XX..XX ", - " XX..XX ", - " XX..XX ", - " XX..XX ", - " XXXX ", - " XX ", - " ", - " ", - " ") - - .. ## pygame.cursors.compile ## - -.. function:: load_xbm - - | :sl:`load cursor data from an XBM file` - | :sg:`load_xbm(cursorfile) -> cursor_args` - | :sg:`load_xbm(cursorfile, maskfile) -> cursor_args` - - This loads cursors for a simple subset of ``XBM`` files. ``XBM`` files are - traditionally used to store cursors on UNIX systems, they are an ASCII - format used to represent simple images. - - Sometimes the black and white color values will be split into two separate - ``XBM`` files. You can pass a second maskfile argument to load the two - images into a single cursor. - - The cursorfile and maskfile arguments can either be filenames or file-like - object with the readlines method. - - The return value cursor_args can be passed directly to the - ``pygame.mouse.set_cursor()`` function. - - .. ## pygame.cursors.load_xbm ## - - - -.. class:: Cursor - - | :sl:`pygame object representing a cursor` - | :sg:`Cursor(size, hotspot, xormasks, andmasks) -> Cursor` - | :sg:`Cursor(hotspot, surface) -> Cursor` - | :sg:`Cursor(constant) -> Cursor` - | :sg:`Cursor(Cursor) -> Cursor` - | :sg:`Cursor() -> Cursor` - - In pygame 2, there are 3 types of cursors you can create to give your - game that little bit of extra polish. There's **bitmap** type cursors, - which existed in pygame 1.x, and are compiled from a string or load from an xbm file. - Then there are **system** type cursors, where you choose a preset that will - convey the same meaning but look native across different operating systems. - Finally you can create a **color** cursor, which displays a pygame surface as the cursor. - - **Creating a system cursor** - - Choose a constant from this list, pass it into ``pygame.cursors.Cursor(constant)``, - and you're good to go. Be advised that not all systems support every system - cursor, and you may get a substitution instead. For example, on macOS, - WAIT/WAITARROW should show up as an arrow, and SIZENWSE/SIZENESW/SIZEALL - should show up as a closed hand. And on Wayland, every SIZE cursor should - show up as a hand. - - :: - - Pygame Cursor Constant Description - -------------------------------------------- - pygame.SYSTEM_CURSOR_ARROW arrow - pygame.SYSTEM_CURSOR_IBEAM i-beam - pygame.SYSTEM_CURSOR_WAIT wait - pygame.SYSTEM_CURSOR_CROSSHAIR crosshair - pygame.SYSTEM_CURSOR_WAITARROW small wait cursor - (or wait if not available) - pygame.SYSTEM_CURSOR_SIZENWSE double arrow pointing - northwest and southeast - pygame.SYSTEM_CURSOR_SIZENESW double arrow pointing - northeast and southwest - pygame.SYSTEM_CURSOR_SIZEWE double arrow pointing - west and east - pygame.SYSTEM_CURSOR_SIZENS double arrow pointing - north and south - pygame.SYSTEM_CURSOR_SIZEALL four pointed arrow pointing - north, south, east, and west - pygame.SYSTEM_CURSOR_NO slashed circle or crossbones - pygame.SYSTEM_CURSOR_HAND hand - - **Creating a cursor without passing arguments** - - In addition to the cursor constants available and described above, - you can also call ``pygame.cursors.Cursor()``, and your cursor is ready (doing that is the same as - calling ``pygame.cursors.Cursor(pygame.SYSTEM_CURSOR_ARROW)``. - Doing one of those calls actually creates a system cursor using the default native image. - - **Creating a color cursor** - - To create a color cursor, create a ``Cursor`` from a ``hotspot`` and a ``surface``. - ``hotspot`` are (x,y) coordinates that determine where in the cursor the exact point is. - The hotspot position must be within the bounds of the ``surface``. - - **Creating a bitmap cursor** - - When the mouse cursor is visible, it will be displayed as a black and white - bitmap using the given bitmask arrays. The ``size`` is a sequence containing - the cursor width and height. ``hotspot`` is a sequence containing the cursor - hotspot position. - - A cursor has a width and height, but a mouse position is represented by a - set of point coordinates. So the value passed into the cursor ``hotspot`` - variable helps pygame to actually determine at what exact point the cursor - is at. - - ``xormasks`` is a sequence of bytes containing the cursor xor data masks. - Lastly ``andmasks``, a sequence of bytes containing the cursor bitmask data. - To create these variables, we can make use of the - :func:`pygame.cursors.compile()` function. - - Width and height must be a multiple of 8, and the mask arrays must be the - correct size for the given width and height. Otherwise an exception is raised. - - .. method:: copy - - | :sl:`copy the current cursor` - | :sg:`copy() -> Cursor` - - Returns a new Cursor object with the same data and hotspot as the original. - .. ## pygame.cursors.Cursor.copy ## - - - .. attribute:: type - - | :sl:`get the cursor type` - | :sg:`type -> string` - - The type will be ``"system"``, ``"bitmap"``, or ``"color"``. - - .. ## pygame.cursors.Cursor.type ## - - .. attribute:: data - - | :sl:`get the cursor data` - | :sg:`data -> tuple` - - Returns the data that was used to create this cursor object, wrapped up in a tuple. - - .. ## pygame.cursors.Cursor.data ## - - .. versionaddedold:: 2.0.1 - - .. ## pygame.cursors.Cursor ## - -.. ## pygame.cursors ## +.. autopgclass:: Cursor + :members: copy, type, data Example code for creating and settings cursors. (Click the mouse to switch cursor) diff --git a/src_c/doc/cursors_doc.h b/src_c/doc/cursors_doc.h index e1f4c8ce0e..4669674bec 100644 --- a/src_c/doc/cursors_doc.h +++ b/src_c/doc/cursors_doc.h @@ -1,8 +1,8 @@ /* Auto generated file: with make_docs.py . Docs go in docs/reST/ref/ . */ -#define DOC_CURSORS "pygame module for cursor resources" -#define DOC_CURSORS_COMPILE "compile(strings, black='X', white='.', xor='o') -> data, mask\ncreate binary cursor data from simple strings" -#define DOC_CURSORS_LOADXBM "load_xbm(cursorfile) -> cursor_args\nload_xbm(cursorfile, maskfile) -> cursor_args\nload cursor data from an XBM file" -#define DOC_CURSORS_CURSOR "Cursor(size, hotspot, xormasks, andmasks) -> Cursor\nCursor(hotspot, surface) -> Cursor\nCursor(constant) -> Cursor\nCursor(Cursor) -> Cursor\nCursor() -> Cursor\npygame object representing a cursor" -#define DOC_CURSORS_CURSOR_COPY "copy() -> Cursor\ncopy the current cursor" -#define DOC_CURSORS_CURSOR_TYPE "type -> string\nget the cursor type" -#define DOC_CURSORS_CURSOR_DATA "data -> tuple\nget the cursor data" +#define DOC_CURSORS "Pygame module for cursor resources." +#define DOC_CURSORS_COMPILE "compile(strings, black='X', white='.', xor='o') -> ...\nCreate binary cursor data from simple strings." +#define DOC_CURSORS_LOADXBM "load_xbm(curs, mask) -> ...\nLoad cursor data from an XBM file." +#define DOC_CURSORS_CURSOR "Cursor(constant=...) -> Cursor\nCursor(cursor) -> Cursor\nCursor(size, hotspot, xormasks, andmasks) -> Cursor\nCursor(hotspot, surface) -> Cursor\nPygame object representing a cursor." +#define DOC_CURSORS_CURSOR_COPY "copy() -> Cursor\nCopy the current cursor." +#define DOC_CURSORS_CURSOR_TYPE "type -> Literal['system', 'color', 'bitmap']\nGet the cursor type." +#define DOC_CURSORS_CURSOR_DATA "data -> ...\nGet the cursor data." diff --git a/src_py/cursors.py b/src_py/cursors.py index 342bce0313..24af5b0bc3 100644 --- a/src_py/cursors.py +++ b/src_py/cursors.py @@ -18,21 +18,57 @@ # Pete Shinners # pete@shinners.org -"""Set of cursor resources available for use. These cursors come -in a sequence of values that are needed as the arguments for -pygame.mouse.set_cursor(). To dereference the sequence in place -and create the cursor in one step, call like this: - pygame.mouse.set_cursor(*pygame.cursors.arrow). +"""Pygame module for cursor resources. -Here is a list of available cursors: - arrow, diamond, ball, broken_x, tri_left, tri_right +Pygame offers control over the system hardware cursor. Pygame supports +black and white cursors (bitmap cursors), as well as system variant cursors and color cursors. +You control the cursor with functions inside :mod:`pygame.mouse`. -There is also a sample string cursor named 'thickarrow_strings'. -The compile() function can convert these string cursors into cursor byte data that can be used to -create Cursor objects. +This cursors module contains functions for loading and decoding various +cursor formats. These allow you to easily store your cursors in external files +or directly as encoded python strings. -Alternately, you can also create Cursor objects using surfaces or cursors constants, -such as pygame.SYSTEM_CURSOR_ARROW. +The module includes several standard cursors. The :func:`pygame.mouse.set_cursor()` +function takes several arguments. All those arguments have been stored in a +single tuple you can call like this: + +:: + + >>> pygame.mouse.set_cursor(*pygame.cursors.arrow) + +The following variables can be passed to ``pygame.mouse.set_cursor`` function: + + * ``pygame.cursors.arrow`` + + * ``pygame.cursors.diamond`` + + * ``pygame.cursors.broken_x`` + + * ``pygame.cursors.tri_left`` + + * ``pygame.cursors.tri_right`` + +This module also contains a few cursors as formatted strings. You'll need to +pass these to ``pygame.cursors.compile()`` function before you can use them. +The example call would look like this: + +:: + + >>> cursor = pygame.cursors.compile(pygame.cursors.textmarker_strings) + >>> pygame.mouse.set_cursor((8, 16), (0, 0), *cursor) + +The following strings can be converted into cursor bitmaps with +``pygame.cursors.compile()`` : + + * ``pygame.cursors.thickarrow_strings`` + + * ``pygame.cursors.sizer_x_strings`` + + * ``pygame.cursors.sizer_y_strings`` + + * ``pygame.cursors.sizer_xy_strings`` + + * ``pygame.cursor.textmarker_strings`` """ import pygame @@ -54,21 +90,94 @@ class Cursor: - def __init__(self, *args): - """Cursor(size, hotspot, xormasks, andmasks) -> Cursor - Cursor(hotspot, Surface) -> Cursor - Cursor(constant) -> Cursor - Cursor(Cursor) -> copies the Cursor object passed as an argument - Cursor() -> Cursor + """Pygame object representing a cursor. + + In pygame 2, there are 3 types of cursors you can create to give your + game that little bit of extra polish. There's **bitmap** type cursors, + which existed in pygame 1.x, and are compiled from a string or load from an xbm file. + Then there are **system** type cursors, where you choose a preset that will + convey the same meaning but look native across different operating systems. + Finally you can create a **color** cursor, which displays a pygame surface as the cursor. + + **Creating a system cursor** + + Choose a constant from this list, pass it into ``pygame.cursors.Cursor(constant)``, + and you're good to go. Be advised that not all systems support every system + cursor, and you may get a substitution instead. For example, on macOS, + WAIT/WAITARROW should show up as an arrow, and SIZENWSE/SIZENESW/SIZEALL + should show up as a closed hand. And on Wayland, every SIZE cursor should + show up as a hand. + + :: + + Pygame Cursor Constant Description + -------------------------------------------- + pygame.SYSTEM_CURSOR_ARROW arrow + pygame.SYSTEM_CURSOR_IBEAM i-beam + pygame.SYSTEM_CURSOR_WAIT wait + pygame.SYSTEM_CURSOR_CROSSHAIR crosshair + pygame.SYSTEM_CURSOR_WAITARROW small wait cursor + (or wait if not available) + pygame.SYSTEM_CURSOR_SIZENWSE double arrow pointing + northwest and southeast + pygame.SYSTEM_CURSOR_SIZENESW double arrow pointing + northeast and southwest + pygame.SYSTEM_CURSOR_SIZEWE double arrow pointing + west and east + pygame.SYSTEM_CURSOR_SIZENS double arrow pointing + north and south + pygame.SYSTEM_CURSOR_SIZEALL four pointed arrow pointing + north, south, east, and west + pygame.SYSTEM_CURSOR_NO slashed circle or crossbones + pygame.SYSTEM_CURSOR_HAND hand + + **Creating a cursor without passing arguments** + + In addition to the cursor constants available and described above, + you can also call ``pygame.cursors.Cursor()``, and your cursor is ready (doing that is the same as + calling ``pygame.cursors.Cursor(pygame.SYSTEM_CURSOR_ARROW)``. + Doing one of those calls actually creates a system cursor using the default native image. + + **Creating a color cursor** + + To create a color cursor, create a ``Cursor`` from a ``hotspot`` and a ``surface``. + ``hotspot`` are (x,y) coordinates that determine where in the cursor the exact point is. + The hotspot position must be within the bounds of the ``surface``. + + **Creating a bitmap cursor** + + When the mouse cursor is visible, it will be displayed as a black and white + bitmap using the given bitmask arrays. The ``size`` is a sequence containing + the cursor width and height. ``hotspot`` is a sequence containing the cursor + hotspot position. + + A cursor has a width and height, but a mouse position is represented by a + set of point coordinates. So the value passed into the cursor ``hotspot`` + variable helps pygame to actually determine at what exact point the cursor + is at. + + ``xormasks`` is a sequence of bytes containing the cursor xor data masks. + Lastly ``andmasks``, a sequence of bytes containing the cursor bitmask data. + To create these variables, we can make use of the + :func:`pygame.cursors.compile()` function. + + Width and height must be a multiple of 8, and the mask arrays must be the + correct size for the given width and height. Otherwise an exception is raised. + + .. versionaddedold:: 2.0.1 + """ - pygame object for representing cursors + def __init__(self, *args): + self.type = "system" + """Get the cursor type. - You can initialize a cursor from a system cursor or use the - constructor on an existing Cursor object, which will copy it. - Providing a Surface instance will render the cursor displayed - as that Surface when used. + The type will be ``"system"``, ``"bitmap"``, or ``"color"``. + """ + self.data = tuple() + """Get the cursor data. - These Surfaces may use other colors than black and white.""" + Returns the data that was used to create this cursor object, wrapped up in a tuple. + """ if len(args) == 0: self.type = "system" self.data = (pygame.SYSTEM_CURSOR_ARROW,) @@ -107,8 +216,10 @@ def __ne__(self, other): return not self.__eq__(other) def copy(self): - """Clone the current Cursor object. - You can do the same thing by doing Cursor(Cursor).""" + """Copy the current cursor. + + Returns a new Cursor object with the same data and hotspot as the original. + """ return self.__class__(self) __copy__ = copy @@ -715,25 +826,51 @@ def get_cursor(): def compile(strings, black="X", white=".", xor="o"): - """pygame.cursors.compile(strings, black, white, xor) -> data, mask - compile cursor strings into cursor data - - This takes a set of strings with equal length and computes - the binary data for that cursor. The string widths must be - divisible by 8. + """Create binary cursor data from simple strings. - The black and white arguments are single letter strings that - tells which characters will represent black pixels, and which - characters represent white pixels. All other characters are - considered clear. + A sequence of strings can be used to create binary cursor data for the + system cursor. This returns the binary data in the form of two tuples. + Those can be passed as the third and fourth arguments respectively of the + :func:`pygame.mouse.set_cursor()` function. - Some systems allow you to set a special toggle color for the - system color, this is also called the xor color. If the system + If you are creating your own cursor strings, you can use any value represent + the black and white pixels. Some system allow you to set a special toggle + color for the system color, this is also called the xor color. If the system does not support xor cursors, that color will simply be black. - This returns a tuple containing the cursor data and cursor mask - data. Both these arguments are used when setting a cursor with - pygame.mouse.set_cursor(). + The height must be divisible by 8. The width of the strings must all be equal + and be divisible by 8. If these two conditions are not met, ``ValueError`` is + raised. + An example set of cursor strings looks like this + + :: + + thickarrow_strings = ( #sized 24x24 + "XX ", + "XXX ", + "XXXX ", + "XX.XX ", + "XX..XX ", + "XX...XX ", + "XX....XX ", + "XX.....XX ", + "XX......XX ", + "XX.......XX ", + "XX........XX ", + "XX........XXX ", + "XX......XXXXX ", + "XX.XXX..XX ", + "XXXX XX..XX ", + "XX XX..XX ", + " XX..XX ", + " XX..XX ", + " XX..XX ", + " XXXX ", + " XX ", + " ", + " ", + " ") + """ # first check for consistent lengths size = len(strings[0]), len(strings) @@ -773,12 +910,21 @@ def compile(strings, black="X", white=".", xor="o"): def load_xbm(curs, mask): - """pygame.cursors.load_xbm(cursorfile, maskfile) -> cursor_args - reads a pair of XBM files into set_cursor arguments + """Load cursor data from an XBM file. + + This loads cursors for a simple subset of ``XBM`` files. ``XBM`` files are + traditionally used to store cursors on UNIX systems, they are an ASCII + format used to represent simple images. + + Sometimes the black and white color values will be split into two separate + ``XBM`` files. You can pass a second maskfile argument to load the two + images into a single cursor. + + The cursorfile and maskfile arguments can either be filenames or file-like + object with the readlines method. - Arguments can either be filenames or filelike objects - with the readlines method. Not largely tested, but - should work with typical XBM files. + The return value cursor_args can be passed directly to the + ``pygame.mouse.set_cursor()`` function. """ def bitswap(num): From ba4bc00a38e83ecaea21364212dbfaaf6738fa09 Mon Sep 17 00:00:00 2001 From: zoldalma <46655437+zoldalma999@users.noreply.github.com> Date: Mon, 21 Oct 2024 23:12:00 +0200 Subject: [PATCH 3/8] Move time docs to stubs, minor fix --- buildconfig/stubs/pygame/time.pyi | 146 +++++++++++++++++++++++-- docs/reST/ext/documenters.py | 2 +- docs/reST/ref/time.rst | 174 +----------------------------- src_c/doc/time_doc.h | 22 ++-- 4 files changed, 153 insertions(+), 191 deletions(-) diff --git a/buildconfig/stubs/pygame/time.pyi b/buildconfig/stubs/pygame/time.pyi index 6be38fc22f..455629a1c4 100644 --- a/buildconfig/stubs/pygame/time.pyi +++ b/buildconfig/stubs/pygame/time.pyi @@ -1,15 +1,143 @@ +"""Pygame module for monitoring time. + +Times in pygame are represented in milliseconds (1/1000 seconds). Most +platforms have a limited time resolution of around 10 milliseconds. This +resolution, in milliseconds, is given in the ``TIMER_RESOLUTION`` constant. +""" + from typing import Union, final from pygame.event import Event -def get_ticks() -> int: ... -def wait(milliseconds: int, /) -> int: ... -def delay(milliseconds: int, /) -> int: ... -def set_timer(event: Union[int, Event], millis: int, loops: int = 0) -> None: ... +def get_ticks() -> int: + """Get the time in milliseconds. + + Return the number of milliseconds since ``pygame.init()`` was called. Before + pygame is initialized this will always be 0. + """ + +def wait(milliseconds: int, /) -> int: + """Pause the program for an amount of time. + + Will pause for a given number of milliseconds. This function sleeps the + process to share the processor with other programs. A program that waits for + even a few milliseconds will consume very little processor time. It is + slightly less accurate than the ``pygame.time.delay()`` function. + + This returns the actual number of milliseconds used. + """ + +def delay(milliseconds: int, /) -> int: + """Pause the program for an amount of time. + + Will pause for a given number of milliseconds. This function will use the + processor (rather than sleeping) in order to make the delay more accurate + than ``pygame.time.wait()``. + + This returns the actual number of milliseconds used. + """ + +def set_timer(event: Union[int, Event], millis: int, loops: int = 0) -> None: + """Repeatedly create an event on the event queue. + + Set an event to appear on the event queue every given number of milliseconds. + The first event will not appear until the amount of time has passed. + + The ``event`` attribute can be a ``pygame.event.Event`` object or an integer + type that denotes an event. + + ``loops`` is an integer that denotes the number of events posted. If 0 (default) + then the events will keep getting posted, unless explicitly stopped. + + To disable the timer for such an event, call the function again with the same + event argument with ``millis`` argument set to 0. + + It is also worth mentioning that a particular event type can only be put on a + timer once. In other words, there cannot be two timers for the same event type. + Setting an event timer for a particular event discards the old one for that + event type. + + When this function is called with an ``Event`` object, the event(s) received + on the event queue will be a shallow copy; the dict attribute of the event + object passed as an argument and the dict attributes of the event objects + received on timer will be references to the same dict object in memory. + Modifications on one dict can affect another, use deepcopy operations on the + dict object if you don't want this behaviour. + However, calling this function with an integer event type would place event objects + on the queue that don't have a common dict reference. + + ``loops`` replaces the ``once`` argument, and this does not break backward + compatibility. + + .. versionaddedold:: 2.0.0.dev3 once argument added. + .. versionchangedold:: 2.0.1 event argument supports ``pygame.event.Event`` object + .. versionaddedold:: 2.0.1 added loops argument to replace once argument + """ + @final class Clock: - def tick(self, framerate: float = 0, /) -> int: ... - def tick_busy_loop(self, framerate: float = 0, /) -> int: ... - def get_time(self) -> int: ... - def get_rawtime(self) -> int: ... - def get_fps(self) -> float: ... + """Create an object to help track time. + + Creates a new Clock object that can be used to track an amount of time. The + clock also provides several functions to help control a game's framerate. + + .. versionchanged:: 2.1.4 This class is also available through the ``pygame.Clock`` + alias. + """ + + def __new__(cls) -> Clock: ... + def tick(self, framerate: float = 0, /) -> int: + """Update the clock. + + This method should be called once per frame. It will compute how many + milliseconds have passed since the previous call. + + If you pass the optional framerate argument the function will delay to + keep the game running slower than the given ticks per second. This can be + used to help limit the runtime speed of a game. By calling + ``Clock.tick(40)`` once per frame, the program will never run at more + than 40 frames per second. + + Note that this function uses SDL_Delay function which is not accurate on + every platform, but does not use much CPU. Use tick_busy_loop if you want + an accurate timer, and don't mind chewing CPU. + """ + + def tick_busy_loop(self, framerate: float = 0, /) -> int: + """Update the clock. + + This method should be called once per frame. It will compute how many + milliseconds have passed since the previous call. + + If you pass the optional framerate argument the function will delay to + keep the game running slower than the given ticks per second. This can be + used to help limit the runtime speed of a game. By calling + ``Clock.tick_busy_loop(40)`` once per frame, the program will never run at + more than 40 frames per second. + + Note that this function uses :func:`pygame.time.delay`, which uses lots + of CPU in a busy loop to make sure that timing is more accurate. + + .. versionaddedold:: 1.8 + """ + + def get_time(self) -> int: + """Time used in the previous tick. + + The number of milliseconds that passed between the previous two calls to + ``Clock.tick()``. + """ + + def get_rawtime(self) -> int: + """Actual time used in the previous tick. + + Similar to ``Clock.get_time()``, but does not include any time used + while ``Clock.tick()`` was delaying to limit the framerate. + """ + + def get_fps(self) -> float: + """Compute the clock framerate. + + Compute your game's framerate (in frames per second). It is computed by + averaging the last ten calls to ``Clock.tick()``. + """ diff --git a/docs/reST/ext/documenters.py b/docs/reST/ext/documenters.py index 53514d112f..1e2057714c 100644 --- a/docs/reST/ext/documenters.py +++ b/docs/reST/ext/documenters.py @@ -20,7 +20,7 @@ def build_signatures(object): object = child break - if object is None: + if object is None or object.obj.get("args", None) is None: return sigs = [(object.obj["args"], object.obj["return_annotation"])] diff --git a/docs/reST/ref/time.rst b/docs/reST/ref/time.rst index d942bac845..4d57f613fc 100644 --- a/docs/reST/ref/time.rst +++ b/docs/reST/ref/time.rst @@ -3,175 +3,9 @@ :mod:`pygame.time` ================== -.. module:: pygame.time - :synopsis: pygame module for monitoring time +.. autopgmodule:: pygame.time + :members: get_ticks, wait, delay, set_timer -| :sl:`pygame module for monitoring time` +.. autopgclass:: Clock + :members: tick, tick_busy_loop, get_time, get_rawtime, get_fps -Times in pygame are represented in milliseconds (1/1000 seconds). Most -platforms have a limited time resolution of around 10 milliseconds. This -resolution, in milliseconds, is given in the ``TIMER_RESOLUTION`` constant. - -.. function:: get_ticks - - | :sl:`get the time in milliseconds` - | :sg:`get_ticks() -> milliseconds` - - Return the number of milliseconds since ``pygame.init()`` was called. Before - pygame is initialized this will always be 0. - - .. ## pygame.time.get_ticks ## - -.. function:: wait - - | :sl:`pause the program for an amount of time` - | :sg:`wait(milliseconds, /) -> time` - - Will pause for a given number of milliseconds. This function sleeps the - process to share the processor with other programs. A program that waits for - even a few milliseconds will consume very little processor time. It is - slightly less accurate than the ``pygame.time.delay()`` function. - - This returns the actual number of milliseconds used. - - .. ## pygame.time.wait ## - -.. function:: delay - - | :sl:`pause the program for an amount of time` - | :sg:`delay(milliseconds, /) -> time` - - Will pause for a given number of milliseconds. This function will use the - processor (rather than sleeping) in order to make the delay more accurate - than ``pygame.time.wait()``. - - This returns the actual number of milliseconds used. - - .. ## pygame.time.delay ## - -.. function:: set_timer - - | :sl:`repeatedly create an event on the event queue` - | :sg:`set_timer(event, millis) -> None` - | :sg:`set_timer(event, millis, loops=0) -> None` - - Set an event to appear on the event queue every given number of milliseconds. - The first event will not appear until the amount of time has passed. - - The ``event`` attribute can be a ``pygame.event.Event`` object or an integer - type that denotes an event. - - ``loops`` is an integer that denotes the number of events posted. If 0 (default) - then the events will keep getting posted, unless explicitly stopped. - - To disable the timer for such an event, call the function again with the same - event argument with ``millis`` argument set to 0. - - It is also worth mentioning that a particular event type can only be put on a - timer once. In other words, there cannot be two timers for the same event type. - Setting an event timer for a particular event discards the old one for that - event type. - - When this function is called with an ``Event`` object, the event(s) received - on the event queue will be a shallow copy; the dict attribute of the event - object passed as an argument and the dict attributes of the event objects - received on timer will be references to the same dict object in memory. - Modifications on one dict can affect another, use deepcopy operations on the - dict object if you don't want this behaviour. - However, calling this function with an integer event type would place event objects - on the queue that don't have a common dict reference. - - ``loops`` replaces the ``once`` argument, and this does not break backward - compatibility. - - .. versionaddedold:: 2.0.0.dev3 once argument added. - .. versionchangedold:: 2.0.1 event argument supports ``pygame.event.Event`` object - .. versionaddedold:: 2.0.1 added loops argument to replace once argument - - .. ## pygame.time.set_timer ## - -.. class:: Clock - - | :sl:`create an object to help track time` - | :sg:`Clock() -> Clock` - - Creates a new Clock object that can be used to track an amount of time. The - clock also provides several functions to help control a game's framerate. - - .. versionchanged:: 2.1.4 This class is also available through the ``pygame.Clock`` - alias. - - .. method:: tick - - | :sl:`update the clock` - | :sg:`tick(framerate=0, /) -> milliseconds` - - This method should be called once per frame. It will compute how many - milliseconds have passed since the previous call. - - If you pass the optional framerate argument the function will delay to - keep the game running slower than the given ticks per second. This can be - used to help limit the runtime speed of a game. By calling - ``Clock.tick(40)`` once per frame, the program will never run at more - than 40 frames per second. - - Note that this function uses SDL_Delay function which is not accurate on - every platform, but does not use much CPU. Use tick_busy_loop if you want - an accurate timer, and don't mind chewing CPU. - - .. ## Clock.tick ## - - .. method:: tick_busy_loop - - | :sl:`update the clock` - | :sg:`tick_busy_loop(framerate=0, /) -> milliseconds` - - This method should be called once per frame. It will compute how many - milliseconds have passed since the previous call. - - If you pass the optional framerate argument the function will delay to - keep the game running slower than the given ticks per second. This can be - used to help limit the runtime speed of a game. By calling - ``Clock.tick_busy_loop(40)`` once per frame, the program will never run at - more than 40 frames per second. - - Note that this function uses :func:`pygame.time.delay`, which uses lots - of CPU in a busy loop to make sure that timing is more accurate. - - .. versionaddedold:: 1.8 - - .. ## Clock.tick_busy_loop ## - - .. method:: get_time - - | :sl:`time used in the previous tick` - | :sg:`get_time() -> milliseconds` - - The number of milliseconds that passed between the previous two calls to - ``Clock.tick()``. - - .. ## Clock.get_time ## - - .. method:: get_rawtime - - | :sl:`actual time used in the previous tick` - | :sg:`get_rawtime() -> milliseconds` - - Similar to ``Clock.get_time()``, but does not include any time used - while ``Clock.tick()`` was delaying to limit the framerate. - - .. ## Clock.get_rawtime ## - - .. method:: get_fps - - | :sl:`compute the clock framerate` - | :sg:`get_fps() -> float` - - Compute your game's framerate (in frames per second). It is computed by - averaging the last ten calls to ``Clock.tick()``. - - .. ## Clock.get_fps ## - - .. ## pygame.time.Clock ## - -.. ## pygame.time ## diff --git a/src_c/doc/time_doc.h b/src_c/doc/time_doc.h index 0662fa40f9..8d695c0d23 100644 --- a/src_c/doc/time_doc.h +++ b/src_c/doc/time_doc.h @@ -1,12 +1,12 @@ /* Auto generated file: with make_docs.py . Docs go in docs/reST/ref/ . */ -#define DOC_TIME "pygame module for monitoring time" -#define DOC_TIME_GETTICKS "get_ticks() -> milliseconds\nget the time in milliseconds" -#define DOC_TIME_WAIT "wait(milliseconds, /) -> time\npause the program for an amount of time" -#define DOC_TIME_DELAY "delay(milliseconds, /) -> time\npause the program for an amount of time" -#define DOC_TIME_SETTIMER "set_timer(event, millis) -> None\nset_timer(event, millis, loops=0) -> None\nrepeatedly create an event on the event queue" -#define DOC_TIME_CLOCK "Clock() -> Clock\ncreate an object to help track time" -#define DOC_TIME_CLOCK_TICK "tick(framerate=0, /) -> milliseconds\nupdate the clock" -#define DOC_TIME_CLOCK_TICKBUSYLOOP "tick_busy_loop(framerate=0, /) -> milliseconds\nupdate the clock" -#define DOC_TIME_CLOCK_GETTIME "get_time() -> milliseconds\ntime used in the previous tick" -#define DOC_TIME_CLOCK_GETRAWTIME "get_rawtime() -> milliseconds\nactual time used in the previous tick" -#define DOC_TIME_CLOCK_GETFPS "get_fps() -> float\ncompute the clock framerate" +#define DOC_TIME "Pygame module for monitoring time." +#define DOC_TIME_GETTICKS "get_ticks() -> int\nGet the time in milliseconds." +#define DOC_TIME_WAIT "wait(milliseconds, /) -> int\nPause the program for an amount of time." +#define DOC_TIME_DELAY "delay(milliseconds, /) -> int\nPause the program for an amount of time." +#define DOC_TIME_SETTIMER "set_timer(event, millis, loops=0) -> None\nRepeatedly create an event on the event queue." +#define DOC_TIME_CLOCK "Clock() -> Clock\nCreate an object to help track time." +#define DOC_TIME_CLOCK_TICK "tick(framerate=0, /) -> int\nUpdate the clock." +#define DOC_TIME_CLOCK_TICKBUSYLOOP "tick_busy_loop(framerate=0, /) -> int\nUpdate the clock." +#define DOC_TIME_CLOCK_GETTIME "get_time() -> int\nTime used in the previous tick." +#define DOC_TIME_CLOCK_GETRAWTIME "get_rawtime() -> int\nActual time used in the previous tick." +#define DOC_TIME_CLOCK_GETFPS "get_fps() -> float\nCompute the clock framerate." From ae70cfafd8be97cee69f8b95776f562931b2f458 Mon Sep 17 00:00:00 2001 From: zoldalma <46655437+zoldalma999@users.noreply.github.com> Date: Tue, 22 Oct 2024 11:01:38 +0200 Subject: [PATCH 4/8] Fix minor formatting issues --- docs/reST/ext/documenters.py | 2 +- docs/reST/ref/time.rst | 1 - pyproject.toml | 2 +- src_py/cursors.py | 9 +++++---- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/reST/ext/documenters.py b/docs/reST/ext/documenters.py index 1e2057714c..491fa18966 100644 --- a/docs/reST/ext/documenters.py +++ b/docs/reST/ext/documenters.py @@ -64,7 +64,7 @@ def get_doc(self, encoding=None, ignore=1): return [""] - def process_doc(self, docstrings: list[str]): + def process_doc(self, docstrings): for docstring in docstrings: if not docstring: continue diff --git a/docs/reST/ref/time.rst b/docs/reST/ref/time.rst index 4d57f613fc..fa82e6a8d8 100644 --- a/docs/reST/ref/time.rst +++ b/docs/reST/ref/time.rst @@ -8,4 +8,3 @@ .. autopgclass:: Clock :members: tick, tick_busy_loop, get_time, get_rawtime, get_fps - diff --git a/pyproject.toml b/pyproject.toml index 8713c3d411..340ad52550 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -59,7 +59,7 @@ requires = [ "ninja<=1.11.1.1", "cython<=3.0.11", "sphinx<=7.2.6", - "autoapi<=3.3.2", + "sphinx-autoapi<=3.3.2", ] build-backend = 'mesonpy' diff --git a/src_py/cursors.py b/src_py/cursors.py index 24af5b0bc3..8431f18a0e 100644 --- a/src_py/cursors.py +++ b/src_py/cursors.py @@ -133,10 +133,11 @@ class Cursor: **Creating a cursor without passing arguments** - In addition to the cursor constants available and described above, - you can also call ``pygame.cursors.Cursor()``, and your cursor is ready (doing that is the same as - calling ``pygame.cursors.Cursor(pygame.SYSTEM_CURSOR_ARROW)``. - Doing one of those calls actually creates a system cursor using the default native image. + In addition to the cursor constants available and described above, you can + also call ``pygame.cursors.Cursor()``, and your cursor is ready (doing that + is the same as calling ``pygame.cursors.Cursor(pygame.SYSTEM_CURSOR_ARROW)``. + Doing one of those calls actually creates a system cursor using the default + native image. **Creating a color cursor** From f22ddbfdeb624c58ee84a4143ca453d062682095 Mon Sep 17 00:00:00 2001 From: zoldalma <46655437+zoldalma999@users.noreply.github.com> Date: Tue, 5 Nov 2024 08:36:05 +0100 Subject: [PATCH 5/8] Install autoapi in msys and debian CI --- .github/workflows/build-debian-multiarch.yml | 2 +- .github/workflows/build-on-msys2.yml | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build-debian-multiarch.yml b/.github/workflows/build-debian-multiarch.yml index 543486b8e7..1f1a76bb1c 100644 --- a/.github/workflows/build-debian-multiarch.yml +++ b/.github/workflows/build-debian-multiarch.yml @@ -44,7 +44,7 @@ env: apt-get install libsdl2-dev libsdl2-image-dev libsdl2-mixer-dev libsdl2-ttf-dev -y apt-get install libfreetype6-dev libportmidi-dev fontconfig -y apt-get install python3-dev python3-pip python3-wheel python3-sphinx -y - pip3 install meson-python --break-system-packages + pip3 install meson-python "sphinx-autoapi<=3.3.2" --break-system-packages jobs: build-multiarch: diff --git a/.github/workflows/build-on-msys2.yml b/.github/workflows/build-on-msys2.yml index 6ac74c15f4..e94dc9cc75 100644 --- a/.github/workflows/build-on-msys2.yml +++ b/.github/workflows/build-on-msys2.yml @@ -68,6 +68,10 @@ jobs: # mingw-w64-${{ matrix.env }}-freetype # mingw-w64-${{ matrix.env }}-portmidi + - name: Install additional dependencies + run: | + pip3 install "sphinx-autoapi<=3.3.2" + - name: Building pygame wheel run: | pip3 wheel . --wheel-dir /artifacts -vvv --no-build-isolation From 532da81fd1ba502d839adab7f0f9787a74861582 Mon Sep 17 00:00:00 2001 From: zoldalma <46655437+zoldalma999@users.noreply.github.com> Date: Wed, 13 Nov 2024 16:34:06 +0100 Subject: [PATCH 6/8] Improve member detection in autoapi directives --- docs/reST/conf.py | 4 ++-- docs/reST/ext/documenters.py | 36 ++++++++++++++++++++++++++---------- docs/reST/ref/cursors.rst | 6 +----- docs/reST/ref/time.rst | 5 +---- 4 files changed, 30 insertions(+), 21 deletions(-) diff --git a/docs/reST/conf.py b/docs/reST/conf.py index 25b927c8e9..dadf50e1df 100644 --- a/docs/reST/conf.py +++ b/docs/reST/conf.py @@ -28,8 +28,8 @@ autoapi_dirs = [ - pathlib.Path(os.path.abspath(".")).parent.parent / 'buildconfig' / 'stubs' / 'pygame' / '', - pathlib.Path(os.path.abspath(".")).parent.parent / 'src_py' / '', + pathlib.Path('.').resolve().parent.parent / 'buildconfig' / 'stubs' / 'pygame', + pathlib.Path('.').resolve().parent.parent / 'src_py', ] autoapi_options = ['members', 'undoc-members'] diff --git a/docs/reST/ext/documenters.py b/docs/reST/ext/documenters.py index 491fa18966..6a750247a3 100644 --- a/docs/reST/ext/documenters.py +++ b/docs/reST/ext/documenters.py @@ -46,23 +46,39 @@ def build_signatures(object): yield f"| :sg:`{name}({arg_string}) -> {ret}`" +def get_doc(env, obj): + if obj.docstring: + return obj.docstring + + # If we don't already have docs, check if a python implementation exists of this + # module and return its docstring if it does + python_object = env.autoapi_all_objects.get( + obj.id.replace("pygame", "src_py"), None + ) + if python_object is not None: + return python_object.docstring + + return "" + + class AutopgDocumenter(autoapi.documenters.AutoapiDocumenter): def format_signature(self, **kwargs): return "" def get_doc(self, encoding=None, ignore=1): - if self.object.docstring: - return super().get_doc(encoding, ignore) - - # If we don't already have docs, check if a python implementation exists of this - # module and return its docstring if it does - python_object = self.env.autoapi_all_objects.get( - self.object.id.replace("pygame", "src_py"), None + return [get_doc(self.env, self.object).splitlines()] + + def get_object_members(self, want_all): + members_check_module, members = super().get_object_members(want_all) + members = ( + member + for member in members + if not member.object.obj.get("hide", False) + and not member.object.imported + and get_doc(self.env, member.object) != "" ) - if python_object is not None: - return [python_object.docstring.splitlines()] - return [""] + return members_check_module, members def process_doc(self, docstrings): for docstring in docstrings: diff --git a/docs/reST/ref/cursors.rst b/docs/reST/ref/cursors.rst index ad90f09126..e8fcbbca47 100644 --- a/docs/reST/ref/cursors.rst +++ b/docs/reST/ref/cursors.rst @@ -4,11 +4,7 @@ ===================== .. autopgmodule:: pygame.cursors - :members: compile, load_xbm - - -.. autopgclass:: Cursor - :members: copy, type, data + :members: Example code for creating and settings cursors. (Click the mouse to switch cursor) diff --git a/docs/reST/ref/time.rst b/docs/reST/ref/time.rst index fa82e6a8d8..1f74178beb 100644 --- a/docs/reST/ref/time.rst +++ b/docs/reST/ref/time.rst @@ -4,7 +4,4 @@ ================== .. autopgmodule:: pygame.time - :members: get_ticks, wait, delay, set_timer - -.. autopgclass:: Clock - :members: tick, tick_busy_loop, get_time, get_rawtime, get_fps + :members: From 26339e39302cc15fd5552abf0a4fc2f4c026d23d Mon Sep 17 00:00:00 2001 From: zoldalma <46655437+zoldalma999@users.noreply.github.com> Date: Wed, 13 Nov 2024 16:42:39 +0100 Subject: [PATCH 7/8] Add synopsis to modules --- docs/reST/ext/documenters.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/reST/ext/documenters.py b/docs/reST/ext/documenters.py index 6a750247a3..81a10f74c2 100644 --- a/docs/reST/ext/documenters.py +++ b/docs/reST/ext/documenters.py @@ -68,6 +68,12 @@ def format_signature(self, **kwargs): def get_doc(self, encoding=None, ignore=1): return [get_doc(self.env, self.object).splitlines()] + def add_directive_header(self, sig: str) -> None: + super().add_directive_header(sig) + if "module" in self.objtype: + sourcename = self.get_sourcename() + self.add_line(f" :synopsis: {self.get_doc()[0][0]}", sourcename) + def get_object_members(self, want_all): members_check_module, members = super().get_object_members(want_all) members = ( From 2c36fc92cb6cf316f4fc70d56dc1f32af4d040ee Mon Sep 17 00:00:00 2001 From: zoldalma <46655437+zoldalma999@users.noreply.github.com> Date: Tue, 3 Dec 2024 18:19:17 +0100 Subject: [PATCH 8/8] Change displayed return type --- docs/reST/ext/documenters.py | 4 +++- src_c/doc/cursors_doc.h | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/docs/reST/ext/documenters.py b/docs/reST/ext/documenters.py index 81a10f74c2..0775a1f843 100644 --- a/docs/reST/ext/documenters.py +++ b/docs/reST/ext/documenters.py @@ -41,7 +41,9 @@ def build_signatures(object): arg_string = arg_string[2:] if ret.count("[") > 2 or ret.count(",") > 3: - ret = "..." + ret = ret.split("[")[0] + if ret in ("Optional", "Union"): + ret = "..." yield f"| :sg:`{name}({arg_string}) -> {ret}`" diff --git a/src_c/doc/cursors_doc.h b/src_c/doc/cursors_doc.h index 4669674bec..aa12f0c53b 100644 --- a/src_c/doc/cursors_doc.h +++ b/src_c/doc/cursors_doc.h @@ -1,7 +1,7 @@ /* Auto generated file: with make_docs.py . Docs go in docs/reST/ref/ . */ #define DOC_CURSORS "Pygame module for cursor resources." -#define DOC_CURSORS_COMPILE "compile(strings, black='X', white='.', xor='o') -> ...\nCreate binary cursor data from simple strings." -#define DOC_CURSORS_LOADXBM "load_xbm(curs, mask) -> ...\nLoad cursor data from an XBM file." +#define DOC_CURSORS_COMPILE "compile(strings, black='X', white='.', xor='o') -> tuple\nCreate binary cursor data from simple strings." +#define DOC_CURSORS_LOADXBM "load_xbm(curs, mask) -> tuple\nLoad cursor data from an XBM file." #define DOC_CURSORS_CURSOR "Cursor(constant=...) -> Cursor\nCursor(cursor) -> Cursor\nCursor(size, hotspot, xormasks, andmasks) -> Cursor\nCursor(hotspot, surface) -> Cursor\nPygame object representing a cursor." #define DOC_CURSORS_CURSOR_COPY "copy() -> Cursor\nCopy the current cursor." #define DOC_CURSORS_CURSOR_TYPE "type -> Literal['system', 'color', 'bitmap']\nGet the cursor type."