6262 "fontio" : "CIRCUITPY_DISPLAYIO" ,
6363 "terminalio" : "CIRCUITPY_DISPLAYIO" ,
6464 "adafruit_bus_device" : "CIRCUITPY_BUSDEVICE" ,
65- "adafruit_pixelbuf" : "CIRCUITPY_PIXELBUF"
65+ "adafruit_pixelbuf" : "CIRCUITPY_PIXELBUF" ,
66+ "usb" : "CIRCUITPY_USB_HOST" ,
6667}
6768
69+ frozen_excludes = ["examples" , "docs" , "tests" , "utils" , "conf.py" , "setup.py" ]
70+ """Files and dirs at the root of a frozen directory that should be ignored.
71+ This is the same list as in the preprocess_frozen_modules script."""
72+
73+ repository_urls = {}
74+ """Cache of repository URLs for frozen modules."""
75+
6876def get_circuitpython_root_dir ():
6977 """ The path to the root './circuitpython' directory
7078 """
@@ -162,6 +170,63 @@ def get_settings_from_makefile(port_dir, board_name):
162170
163171 return settings
164172
173+ def get_repository_url (directory ):
174+ if directory in repository_urls :
175+ return repository_urls [directory ]
176+ readme = None
177+ for readme_path in (
178+ os .path .join (directory , "README.rst" ),
179+ os .path .join (os .path .dirname (directory ), "README.rst" )
180+ ):
181+ if os .path .exists (readme_path ):
182+ readme = readme_path
183+ break
184+ path = None
185+ if readme :
186+ with open (readme , "r" ) as fp :
187+ for line in fp .readlines ():
188+ if m := re .match ("\s+:target:\s+(http\S+(docs.circuitpython|readthedocs)\S+)\s*" , line ):
189+ path = m .group (1 )
190+ break
191+ if m := re .search ("<(http[^>]+)>" , line ):
192+ path = m .group (1 )
193+ break
194+ if path is None :
195+ contents = subprocess .run (
196+ ["git" , "remote" , "get-url" , "origin" ],
197+ encoding = "utf-8" ,
198+ errors = "replace" ,
199+ stdout = subprocess .PIPE ,
200+ stderr = subprocess .PIPE ,
201+ cwd = directory
202+ )
203+ path = contents .stdout .strip ()
204+ repository_urls [directory ] = path
205+ return path
206+
207+ def frozen_modules_from_dirs (frozen_mpy_dirs ):
208+ """
209+ Go through the list of frozen directories and extract the python modules.
210+ Paths are of the type:
211+ $(TOP)/frozen/Adafruit_CircuitPython_CircuitPlayground
212+ $(TOP)/frozen/circuitpython-stage/meowbit
213+ Python modules are at the root of the path, and are python files or directories
214+ containing python files. Except the ones in the frozen_excludes list.
215+ """
216+ frozen_modules = []
217+ for frozen_path in filter (lambda x : x , frozen_mpy_dirs .split (" " )):
218+ source_dir = get_circuitpython_root_dir () / frozen_path [7 :]
219+ url_repository = get_repository_url (source_dir )
220+ for sub in source_dir .glob ("*" ):
221+ if sub .name in frozen_excludes :
222+ continue
223+ if sub .name .endswith (".py" ):
224+ frozen_modules .append ((sub .name [:- 3 ], url_repository ))
225+ continue
226+ if next (sub .glob ("**/*.py" ), None ): # tests if not empty
227+ frozen_modules .append ((sub .name , url_repository ))
228+ return frozen_modules
229+
165230def lookup_setting (settings , key , default = '' ):
166231 while True :
167232 value = settings .get (key , default )
@@ -207,16 +272,22 @@ def support_matrix(arg):
207272 board_modules .append (base [module ]['name' ])
208273 board_modules .sort ()
209274
275+ frozen_modules = []
276+ if "FROZEN_MPY_DIRS" in settings :
277+ frozen_modules = frozen_modules_from_dirs (settings ["FROZEN_MPY_DIRS" ])
278+ if frozen_modules :
279+ frozen_modules .sort ()
280+
210281 # generate alias boards too
211- board_matrix = [(board_name , board_modules )]
282+ board_matrix = [(board_name , ( board_modules , frozen_modules ) )]
212283 if entry .name in aliases_by_board :
213284 for alias in aliases_by_board [entry .name ]:
214285 if use_branded_name :
215286 if alias in aliases_brand_names :
216287 alias = aliases_brand_names [alias ]
217288 else :
218289 alias = alias .replace ("_" ," " ).title ()
219- board_matrix .append ( (alias , board_modules ) )
290+ board_matrix .append ( (alias , ( board_modules , frozen_modules ) ) )
220291
221292 return board_matrix # this is now a list of (board,modules)
222293
@@ -225,7 +296,6 @@ def support_matrix(arg):
225296 # flatmap with comprehensions
226297 boards = dict (sorted ([board for matrix in mapped_exec for board in matrix ]))
227298
228- # print(json.dumps(boards, indent=2))
229299 return boards
230300
231301if __name__ == '__main__' :
0 commit comments