33
44Generate quick API indexes in Restructured Text Format for Sphinx documentation.
55"""
6+ import math
67import sys
8+ from collections import defaultdict
9+ from functools import lru_cache
710from pathlib import Path
811from typing import List
12+ import logging
13+
14+ log = logging .getLogger (__name__ )
915
1016# Ensure we get utility and Arcade imports first
1117sys .path .insert (0 , str (Path (__file__ ).parent .resolve ()))
1420import arcade
1521from doc_helpers .vfs import Vfs
1622
23+
24+ def announce_templating (var_name ):
25+ _v = globals ()[var_name ]
26+ log .warning (f"Templated { var_name } as { _v !r} " )
27+
28+ # The following are provided via runpy.run_path's init_globals keyword
29+ # in conf.py. Uncomment for easy debugger run without IDE config.
30+ try :
31+ _ = GIT_REF # noqa
32+ except Exception as _ :
33+ GIT_REF = "development"
34+ announce_templating ("GIT_REF" )
35+ try :
36+ _URL_BASE = "https://github.com/pythonarcade/arcade"
37+ _ = FMT_URL_REF_PAGE # noqa
38+ except Exception as _ :
39+ FMT_URL_REF_PAGE = f"{ _URL_BASE } /blob/{ GIT_REF } /{{}}"
40+ announce_templating ("FMT_URL_REF_PAGE" )
41+ try :
42+ _ = FMT_URL_REF_EMBED # noqa
43+ except Exception as _ :
44+ FMT_URL_REF_EMBED = f"{ _URL_BASE } /blob/{ GIT_REF } /{{}}?raw=true"
45+ announce_templating ("FMT_URL_REF_EMBED" )
46+
47+
1748MODULE_DIR = Path (__file__ ).parent .resolve ()
1849ARCADE_ROOT = MODULE_DIR .parent
1950RESOURCE_DIR = ARCADE_ROOT / "arcade" / "resources"
2051OUT_FILE = ARCADE_ROOT / "doc" / "api_docs" / "resources.rst"
21- RESOURCE_URL = "https://github.com/pythonarcade/arcade/blob/development/{}?raw=true"
2252
23- COLUMNS = 3
53+
2454# Metadata for the resource list: utils\create_resource_list.py
2555skip_extensions = [
2656 ".glsl" ,
@@ -39,6 +69,22 @@ def skipped_file(file_path: Path):
3969 return file_path .suffix in skip_extensions
4070
4171
72+ MAX_COLS : dict [str , int ] = defaultdict (lambda : 3 )
73+ MAX_COLS [":resources:sounds/" ] = 2
74+
75+
76+ @lru_cache (maxsize = None )
77+ def get_header_num_cols (resource_stub : str , n_files = math .inf ) -> int :
78+ return int (min (MAX_COLS [resource_stub ], n_files ))
79+
80+
81+ @lru_cache (maxsize = None )
82+ def get_column_widths_for_n (n : int ) -> str :
83+ width = str (100 // n )
84+ return ' ' .join ((width for _ in range (n )))
85+
86+
87+ @lru_cache (maxsize = None ) # Cache b/c re-using elsewhere
4288def create_resource_path (
4389 path : Path ,
4490 prefix : str = "" ,
@@ -71,18 +117,25 @@ def process_resource_directory(out, dir: Path):
71117 # out.write("-" * len(cur_node.name) + "\n\n")
72118
73119 file_list = [item for item in path .iterdir () if not (item .is_dir () or skipped_file (item ))]
74- if len (file_list ) > 0 :
120+ num_files = len (file_list )
121+ if num_files > 0 :
122+
75123 # header_title = f":resources:{path.relative_to(RESOURCE_DIR).as_posix()}/"
76- header_title = create_resource_path (path , suffix = "/" )
77- if header_title == ":resources:images/" :
124+ raw_header = create_resource_path (path , suffix = "/" )
125+ header_title = raw_header [:- 2 ] if raw_header .endswith ("./" ) else raw_header
126+
127+ if raw_header == ":resources:images/" :
78128 for f in file_list :
79129 print (f .name )
80130 # out.write(f"\n{header_title}\n")
81131 # out.write("-" * (len(header_title)) + "\n\n")
82132
133+ n_cols = get_header_num_cols (raw_header , num_files )
134+ widths = get_column_widths_for_n (n_cols )
135+
83136 out .write (f"\n " )
84- out .write (f".. list-table:: { header_title } \n " )
85- out .write (f" :widths: 33 33 33 \n " )
137+ out .write (f".. list-table:: \" { header_title } \" \n " )
138+ out .write (f" :widths: { widths } \n " )
86139 out .write (f" :header-rows: 0\n " )
87140 out .write (f" :class: resource-table\n \n " )
88141
@@ -92,46 +145,65 @@ def process_resource_directory(out, dir: Path):
92145 process_resource_directory (out , path )
93146
94147
148+ SUFFIX_TO_AUDIO_TYPE = {
149+ '.wav' : 'x-wav' ,
150+ '.ogg' : 'ogg' ,
151+ '.mp3' : 'mpeg' ,
152+ }
153+ SUFFIX_TO_VIDEO_TYPE = {
154+ '.mp4' : 'mp4' ,
155+ '.webm' : 'webm' ,
156+ '.avi' : 'avi'
157+ }
158+
95159def process_resource_files (out , file_list : List [Path ]):
96- start_row = True
97160 cell_count = 0
98161
162+ prefix = create_resource_path (file_list [0 ].parent , suffix = "/" )
163+
164+ COLUMNS = get_header_num_cols (prefix , len (file_list ))
165+
166+ log .info (f"Processing { prefix = !r} with { COLUMNS = !r} " )
99167 for path in file_list :
100168 resource_path = path .relative_to (ARCADE_ROOT ).as_posix ()
169+ suffix = path .suffix
101170
102171 if cell_count % COLUMNS == 0 :
103172 start_row = "*"
104- if path .suffix in [".png" , ".jpg" , ".gif" , ".svg" ]:
173+ else :
174+ start_row = " "
175+ name = path .name
176+ resource_copyable = f"{ create_resource_path (path )} "
177+ if suffix in [".png" , ".jpg" , ".gif" , ".svg" ]:
105178 out .write (f" { start_row } - .. image:: ../../{ resource_path } \n \n " )
106- out .write (f" { path . name } \n " )
107- cell_count += 1
108- elif path . suffix == ".wav" :
109- file_path = RESOURCE_URL . format ( resource_path )
179+ out .write (f" { name } \n " )
180+ elif suffix in SUFFIX_TO_AUDIO_TYPE :
181+ file_path = FMT_URL_REF_EMBED . format ( resource_path )
182+ src_type = SUFFIX_TO_AUDIO_TYPE [ suffix ]
110183 out .write (f" { start_row } - .. raw:: html\n \n " )
111- out .write (f" <audio controls><source src='{ file_path } ' type='audio/x-wav'></audio><br />{ path .name } \n " )
112- cell_count += 1
113- elif path .suffix == ".mp3" :
114- file_path = RESOURCE_URL .format (resource_path )
184+ out .write (f" <audio controls><source src='{ file_path } ' type='audio/{ src_type } '></audio>\n " )
185+ out .write (f" <br /><code class='literal'>"{ resource_copyable } "</code>\n " )
186+ # out.write(f" <br /><a href={FMT_URL_REF_PAGE.format(resource_path)}>{path.name} on GitHub</a>\n")
187+ elif suffix in SUFFIX_TO_VIDEO_TYPE :
188+ file_path = FMT_URL_REF_EMBED .format (resource_path )
189+ src_type = SUFFIX_TO_VIDEO_TYPE [suffix ]
115190 out .write (f" { start_row } - .. raw:: html\n \n " )
116- out .write (f" <audio controls><source src='{ file_path } ' type='audio/mpeg'></audio><br />{ path .name } \n " )
117- cell_count += 1
118- elif path .suffix == ".ogg" :
119- file_path = RESOURCE_URL .format (resource_path )
120- out .write (f" { start_row } - .. raw:: html\n \n " )
121- out .write (f" <audio controls><source src='{ file_path } ' type='audio/ogg'></audio><br />{ path .name } \n " )
122- cell_count += 1
123- elif path .suffix == ".glsl" :
124- file_path = RESOURCE_URL .format (resource_path )
125- out .write (f" { start_row } - `{ path .name } <{ file_path } >`_\n " )
126- # out.write(f" {start_row} - .. raw:: html\n\n")
127- # out.write(f" <audio controls><source src='{file_path}' type='audio/ogg'></audio><br />{path.name}\n")
128- cell_count += 1
191+ out .write (f" <video style=\" max-width: 100%\" controls><source src='{ file_path } ' type='video/{ src_type } '></video>\n " )
192+ out .write (f" <br /><code class='literal'>"{ resource_copyable } "</code>\n " )
193+ elif suffix == ".glsl" :
194+ file_path = FMT_URL_REF_PAGE .format (resource_path )
195+ out .write (f" { start_row } - `{ path } <{ file_path } >`_\n " )
196+ # Link Tiled maps
197+ elif suffix == ".json" :
198+ file_path = FMT_URL_REF_PAGE .format (resource_path )
199+ out .write (f" { start_row } - `{ name } <{ file_path } >`_\n " )
129200 else :
130- out .write (f" { start_row } - { path . name } \n " )
131- cell_count += 1
132-
133- start_row = " "
201+ out .write (f" { start_row } - { name } \n " )
202+ # The below doesn't work because of how raw HTML / Sphinx images interact:
203+ # out.write(f" <br /><code class='literal'>{resource_copyable}</code>\n")
204+ cell_count += 1
134205
206+ # Finish any remaining columns with empty cells
135207 while cell_count % COLUMNS > 0 :
136208 out .write (f" -\n " )
137209 cell_count += 1
@@ -161,8 +233,10 @@ def resources():
161233 out .close ()
162234 print ("Done creating resources.rst" )
163235
236+
164237vfs = Vfs ()
165238
239+
166240def main ():
167241 resources ()
168242 vfs .write ()
0 commit comments