2019-04-19 02:13:34 +08:00
#!/usr/bin/env python
2019-04-25 18:21:25 +08:00
# -*- coding: utf-8 -*-
2019-04-19 02:13:34 +08:00
# Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma de
# Barcelona (UAB).
#
# This work is licensed under the terms of the MIT license.
# For a copy, see <https://opensource.org/licenses/MIT>.
import os
import yaml
2019-06-04 00:35:57 +08:00
import re
2020-10-15 22:48:48 +08:00
import doc_gen_snipets
2019-04-19 02:13:34 +08:00
2019-05-15 23:39:25 +08:00
COLOR_METHOD = ' #7fb800 '
COLOR_PARAM = ' #00a6ed '
COLOR_INSTANCE_VAR = ' #f8805a '
2019-06-07 18:58:00 +08:00
COLOR_NOTE = ' #8E8E8E '
COLOR_WARNING = ' #ED2F2F '
2019-05-15 23:39:25 +08:00
2019-06-04 18:13:12 +08:00
QUERY = re . compile ( r ' ([cC]arla( \ .[a-zA-Z0-9_]+)+) ' )
2019-06-04 00:35:57 +08:00
2019-08-15 01:44:55 +08:00
2019-06-04 00:35:57 +08:00
def create_hyperlinks ( text ) :
return re . sub ( QUERY , r ' [ \ 1](# \ 1) ' , text )
2020-04-18 00:14:51 +08:00
def create_getter_setter_hyperlinks ( text ) :
return re . sub ( QUERY , r ' [ \ 1](# \ 1) ' , text )
2019-08-15 01:44:55 +08:00
def join ( elem , separator = ' ' ) :
2019-04-25 18:21:25 +08:00
return separator . join ( elem )
2019-08-15 01:44:55 +08:00
2019-04-19 02:13:34 +08:00
class MarkdownFile :
def __init__ ( self ) :
self . _data = " "
self . _list_depth = 0
self . endl = ' \n '
2020-10-15 22:48:48 +08:00
2019-04-19 02:13:34 +08:00
def data ( self ) :
2019-04-25 18:21:25 +08:00
return self . _data
2019-04-19 02:13:34 +08:00
2019-04-25 18:21:25 +08:00
def list_push ( self , buf = ' ' ) :
if buf :
self . text ( join ( [
' ' * self . _list_depth if self . _list_depth != 0 else ' ' , ' - ' , buf ] ) )
2019-04-19 02:13:34 +08:00
self . _list_depth = ( self . _list_depth + 1 )
2019-04-25 18:21:25 +08:00
def list_pushn ( self , buf ) :
self . list_push ( join ( [ buf , self . endl ] ) )
def list_pop ( self ) :
2019-04-19 02:13:34 +08:00
self . _list_depth = max ( self . _list_depth - 1 , 0 )
2019-04-25 18:21:25 +08:00
def list_popn ( self ) :
self . list_pop ( )
2019-06-05 21:05:57 +08:00
self . _data = join ( [ self . _data , ' \n ' ] )
2019-04-25 18:21:25 +08:00
2019-04-19 02:13:34 +08:00
def list_depth ( self ) :
2019-05-03 18:00:40 +08:00
if self . _data . strip ( ) [ - 1 : ] != ' \n ' or self . _list_depth == 0 :
2019-04-19 02:13:34 +08:00
return ' '
2019-06-05 21:05:57 +08:00
return join ( [ ' ' * self . _list_depth ] )
2019-04-19 02:13:34 +08:00
2019-04-25 18:21:25 +08:00
def separator ( self ) :
2019-06-05 21:05:57 +08:00
self . _data = join ( [ self . _data , ' \n --- \n ' ] )
2019-04-25 18:21:25 +08:00
def new_line ( self ) :
2019-06-05 21:05:57 +08:00
self . _data = join ( [ self . _data , self . endl ] )
2019-04-25 18:21:25 +08:00
2019-04-19 02:13:34 +08:00
def text ( self , buf ) :
2019-06-05 21:05:57 +08:00
self . _data = join ( [ self . _data , buf ] )
2019-04-25 18:21:25 +08:00
def textn ( self , buf ) :
2019-06-05 21:05:57 +08:00
self . _data = join ( [ self . _data , self . list_depth ( ) , buf , self . endl ] )
2019-04-19 02:13:34 +08:00
2020-03-02 16:40:34 +08:00
def first_title ( self ) :
self . _data = join ( [
2020-04-18 00:14:51 +08:00
self . _data , ' #Python API reference \n ' ] )
2019-04-19 02:13:34 +08:00
def title ( self , strongness , buf ) :
2019-06-05 21:05:57 +08:00
self . _data = join ( [
2019-04-19 02:13:34 +08:00
self . _data , ' \n ' , self . list_depth ( ) , ' # ' * strongness , ' ' , buf , ' \n ' ] )
2019-06-05 21:05:57 +08:00
def title_html ( self , strongness , buf ) :
2020-04-18 00:14:51 +08:00
if strongness == 5 :
self . _data = join ( [
self . _data , ' \n ' , self . list_depth ( ) , ' <h ' , str ( strongness ) , ' style= " margin-top: -20px " > ' , buf , ' </h ' , str ( strongness ) , ' > \n ' , ' <div style= " padding-left:30px;margin-top:-25px " ></div> ' ] )
else :
self . _data = join ( [
self . _data , ' \n ' , self . list_depth ( ) , ' <h ' , str ( strongness ) , ' > ' , buf , ' </h ' , str ( strongness ) , ' > \n ' ] )
2020-02-11 17:15:18 +08:00
def inherit_join ( self , inh ) :
self . _data = join ( [
2021-04-26 17:05:38 +08:00
self . _data , ' <small style= " display:block;margin-top:-20px; " >Inherited from ' , inh , ' </small></br> \n ' ] )
2019-06-05 21:05:57 +08:00
def note ( self , buf ) :
self . _data = join ( [ self . _data , buf ] )
2019-04-25 18:21:25 +08:00
def code_block ( self , buf , language = ' ' ) :
2019-06-05 21:05:57 +08:00
return join ( [ ' ``` ' , language , ' \n ' , self . list_depth ( ) , buf , ' \n ' , self . list_depth ( ) , ' ``` \n ' ] )
2019-04-19 02:13:34 +08:00
2019-05-03 18:00:40 +08:00
def prettify_doc ( self , doc ) :
2019-08-15 01:44:55 +08:00
punctuation_marks = [ ' . ' , ' ! ' , ' ? ' ]
2019-05-03 18:00:40 +08:00
doc = doc . strip ( )
2019-08-15 01:44:55 +08:00
doc + = ' ' if doc [ - 1 : ] in punctuation_marks else ' . '
2019-05-03 18:00:40 +08:00
return doc
2019-04-19 02:13:34 +08:00
2019-08-15 01:44:55 +08:00
2019-04-25 18:21:25 +08:00
def italic ( buf ) :
2019-06-05 21:05:57 +08:00
return join ( [ ' _ ' , buf , ' _ ' ] )
2019-04-19 02:13:34 +08:00
2019-08-15 01:44:55 +08:00
2019-04-25 18:21:25 +08:00
def bold ( buf ) :
2019-06-05 21:05:57 +08:00
return join ( [ ' ** ' , buf , ' ** ' ] )
2019-04-25 18:21:25 +08:00
2020-10-15 22:48:48 +08:00
def snipet ( name , class_key ) :
2021-02-11 18:34:36 +08:00
return join ( [ " <button class= \" SnipetButton \" id= \" " , class_key , " . " , name , " -snipet_button \" > " , " snippet → " , ' </button> ' ] )
2019-08-15 01:44:55 +08:00
2019-04-25 18:21:25 +08:00
def code ( buf ) :
2019-06-05 21:05:57 +08:00
return join ( [ ' ` ' , buf , ' ` ' ] )
2019-04-19 02:13:34 +08:00
2019-08-15 01:44:55 +08:00
2019-04-25 18:21:25 +08:00
def brackets ( buf ) :
2019-06-05 21:05:57 +08:00
return join ( [ ' [ ' , buf , ' ] ' ] )
2019-04-19 02:13:34 +08:00
2019-08-15 01:44:55 +08:00
2019-04-25 18:21:25 +08:00
def parentheses ( buf ) :
2019-06-05 21:05:57 +08:00
return join ( [ ' ( ' , buf , ' ) ' ] )
2019-04-19 02:13:34 +08:00
2020-11-24 01:45:37 +08:00
2020-09-15 21:40:57 +08:00
def small_html ( buf ) :
2020-11-24 01:45:37 +08:00
return join ( [ ' <small> ' , buf , ' </small> ' ] )
2020-09-15 21:40:57 +08:00
2019-08-15 01:44:55 +08:00
2019-04-25 18:21:25 +08:00
def small ( buf ) :
2019-06-05 21:05:57 +08:00
return join ( [ ' <sub><sup> ' , buf , ' </sup></sub> ' ] )
2019-04-25 18:21:25 +08:00
2019-08-15 01:44:55 +08:00
2019-04-25 18:21:25 +08:00
def sub ( buf ) :
2019-06-05 21:05:57 +08:00
return join ( [ ' <sub> ' , buf , ' </sub> ' ] )
2019-04-25 18:21:25 +08:00
2019-08-15 01:44:55 +08:00
2019-04-25 18:21:25 +08:00
def html_key ( buf ) :
2019-06-05 21:05:57 +08:00
return join ( [ ' <a name= " ' , buf , ' " ></a> ' ] )
2019-04-25 18:21:25 +08:00
2019-08-15 01:44:55 +08:00
2019-04-25 18:21:25 +08:00
def color ( col , buf ) :
2019-06-05 21:05:57 +08:00
return join ( [ ' <font color= " ' , col , ' " > ' , buf , ' </font> ' ] )
2019-04-25 18:21:25 +08:00
2019-08-15 01:44:55 +08:00
2019-04-25 18:21:25 +08:00
def valid_dic_val ( dic , value ) :
return value in dic and dic [ value ]
2019-08-15 01:44:55 +08:00
2019-04-25 18:21:25 +08:00
class YamlFile :
""" Yaml file class """
2019-08-15 01:44:55 +08:00
2019-04-25 18:21:25 +08:00
def __init__ ( self , path ) :
self . _path = path
with open ( path ) as yaml_file :
2019-04-19 02:13:34 +08:00
self . data = yaml . safe_load ( yaml_file )
2019-05-03 18:00:40 +08:00
self . validate ( )
def validate ( self ) :
# print('Validating ' + str(self._path.replace('\\', '/').split('/')[-1:][0]))
if self . data is None :
2019-05-03 19:13:41 +08:00
print ( ' \n [ERROR] File: ' + self . _path )
print ( " This file has no data: " )
2019-05-03 18:00:40 +08:00
exit ( 0 )
for module in self . data :
if ' module_name ' in module and module [ ' module_name ' ] is None :
2019-05-03 19:13:41 +08:00
print ( ' \n [ERROR] File: ' + self . _path )
print ( " ' module_name ' is empty in: " )
2019-05-03 18:00:40 +08:00
exit ( 0 )
if ' classes ' in module :
2019-05-03 19:13:41 +08:00
if not module [ ' classes ' ] :
print ( ' \n [ERROR] File: ' + self . _path )
print ( " ' classes ' is empty in: " )
exit ( 0 )
2019-05-03 18:00:40 +08:00
for cl in module [ ' classes ' ] :
if ' class_name ' in cl and cl [ ' class_name ' ] is None :
2019-05-03 19:13:41 +08:00
print ( ' \n [ERROR] File: ' + self . _path )
print ( " ' class_name ' is empty in: " )
2019-05-03 18:00:40 +08:00
exit ( 0 )
if ' instance_variables ' in cl and cl [ ' instance_variables ' ] :
for iv in cl [ ' instance_variables ' ] :
2019-06-28 20:55:53 +08:00
if ' var_name ' not in iv :
print ( ' \n [ERROR] File: ' + self . _path )
print ( " ' var_name ' not found inside ' instance_variables ' of class: " + cl [ ' class_name ' ] )
exit ( 0 )
2019-05-03 18:00:40 +08:00
if ' var_name ' in iv and iv [ ' var_name ' ] is None :
2019-05-03 19:13:41 +08:00
print ( ' \n [ERROR] File: ' + self . _path )
print ( " ' var_name ' is empty in: " )
2019-05-03 18:00:40 +08:00
exit ( 0 )
if ' methods ' in cl and cl [ ' methods ' ] :
for met in cl [ ' methods ' ] :
2019-06-28 20:55:53 +08:00
if ' def_name ' not in met :
print ( ' \n [ERROR] File: ' + self . _path )
print ( " ' def_name ' not found inside ' methods ' of class: " + cl [ ' class_name ' ] )
exit ( 0 )
2019-05-03 18:00:40 +08:00
if ' def_name ' in met and met [ ' def_name ' ] is None :
2019-05-03 19:13:41 +08:00
print ( ' \n [ERROR] File: ' + self . _path )
print ( " ' def_name ' is empty in: " )
2019-05-03 18:00:40 +08:00
exit ( 0 )
2019-06-28 20:55:53 +08:00
if ' params ' in met and met [ ' params ' ] :
for param in met [ ' params ' ] :
2019-08-15 01:44:55 +08:00
if ' param_name ' not in param :
2019-06-28 20:55:53 +08:00
print ( ' \n [ERROR] File: ' + self . _path )
print ( " ' param_name ' not found inside ' params ' of class: " + cl [ ' class_name ' ] )
exit ( 0 )
2019-08-15 01:44:55 +08:00
if ' param_name ' in param and param [ ' param_name ' ] is None :
2019-06-28 20:55:53 +08:00
print ( ' \n [ERROR] File: ' + self . _path )
print ( " ' param_name ' is empty in: " )
exit ( 0 )
2019-08-15 01:44:55 +08:00
if ' type ' in param and param [ ' type ' ] is None :
2019-06-28 20:55:53 +08:00
print ( ' \n [ERROR] File: ' + self . _path )
print ( " ' type ' is empty in: " )
exit ( 0 )
2019-04-19 02:13:34 +08:00
2019-04-25 18:21:25 +08:00
def get_modules ( self ) :
return [ module for module in self . data ]
2020-10-15 22:48:48 +08:00
def append_snipet_button_script ( md ) :
md . textn ( " \n \n <script> \n " +
" function ButtonAction(container_name) { \n " +
" if(window_big) { \n " +
" snipet_name = container_name.replace( ' -snipet_button ' , ' -snipet ' ); \n " +
" document.getElementById( \" snipets-container \" ).innerHTML = document.getElementById(snipet_name).innerHTML; \n " +
" } \n " +
" else { \n " +
" document.getElementById( \" snipets-container \" ).innerHTML = null; " +
" code_name = container_name.replace( ' -snipet_button ' , ' -code ' ); \n " +
" var range = document.createRange(); \n " +
" range.selectNode(document.getElementById(code_name)); \n " +
" alert(range); \n " +
" } \n " +
" } \n " +
" function WindowResize() { \n " +
" if(window.innerWidth > 1200) { \n " +
" window_big = true; \n " +
" } \n " +
" else { \n " +
" window_big = false; \n " +
" } \n " +
" } \n " +
" var window_big; \n " +
" if(window.innerWidth > 1200) { \n " +
" window_big = true; \n " +
" } \n " +
" else { \n " +
" window_big = false; \n " +
" } \n " +
" buttons = document.getElementsByClassName( ' SnipetButton ' ) \n " +
" for (let i = 0; i < buttons.length; i++) { \n " +
" buttons[i].addEventListener( \" click \" ,function() { ButtonAction(buttons[i].id);},true); \n " +
" } \n " +
" window.onresize = WindowResize; \n " +
" </script> \n " )
def append_code_snipets ( md ) :
current_folder = os . path . dirname ( os . path . abspath ( __file__ ) )
snipets_path = os . path . join ( current_folder , ' ../../Docs/python_api_snipets.md ' )
snipets = open ( snipets_path , ' r ' )
md . text ( snipets . read ( ) )
2021-11-04 17:07:41 +08:00
snipets . close ( )
2020-10-15 22:48:48 +08:00
os . remove ( snipets_path )
2019-04-25 18:21:25 +08:00
def gen_stub_method_def ( method ) :
""" Return python def as it should be written in stub files """
param = ' '
method_name = method [ ' def_name ' ]
for p in method [ ' params ' ] :
2019-06-05 21:05:57 +08:00
p_type = join ( [ ' : ' , str ( p [ ' type ' ] ) ] ) if ' type ' in p else ' '
default = join ( [ ' = ' , str ( p [ ' default ' ] ) ] ) if ' default ' in p else ' '
param = join ( [ param , p [ ' param_name ' ] , p_type , default , ' , ' ] )
2019-08-15 01:44:55 +08:00
param = param [ : - 2 ] # delete the last ', '
2019-06-05 21:05:57 +08:00
return_type = join ( [ ' -> ' , method [ ' return ' ] ] ) if ' return ' in method else ' '
return join ( [ method_name , parentheses ( param ) , return_type ] )
2019-04-25 18:21:25 +08:00
2019-04-19 02:13:34 +08:00
2020-10-15 22:48:48 +08:00
def gen_doc_method_def ( method , class_key , is_indx = False , with_self = True ) :
2019-04-25 18:21:25 +08:00
""" Return python def as it should be written in docs """
param = ' '
2020-10-15 22:48:48 +08:00
snipet_link = ' '
2019-04-25 18:21:25 +08:00
method_name = method [ ' def_name ' ]
2020-10-15 22:48:48 +08:00
full_method_name = method_name
2019-06-07 18:58:00 +08:00
if valid_dic_val ( method , ' static ' ) :
with_self = False
2020-10-15 22:48:48 +08:00
# to correctly render methods like __init__ in md
2019-04-25 18:21:25 +08:00
if method_name [ 0 ] == ' _ ' :
method_name = ' \\ ' + method_name
2019-06-07 18:58:00 +08:00
if is_indx :
2019-04-25 18:21:25 +08:00
method_name = bold ( method_name )
else :
2019-05-15 23:39:25 +08:00
method_name = bold ( color ( COLOR_METHOD , method_name ) )
2019-06-07 18:58:00 +08:00
if with_self :
2019-08-15 01:44:55 +08:00
if not ' params ' in method or method [ ' params ' ] is None :
2019-06-07 18:58:00 +08:00
method [ ' params ' ] = [ ]
method [ ' params ' ] . insert ( 0 , { ' param_name ' : ' self ' } )
if valid_dic_val ( method , ' params ' ) :
for p in method [ ' params ' ] :
default = join ( [ ' = ' , str ( p [ ' default ' ] ) ] ) if ' default ' in p else ' '
if is_indx :
param = join ( [ param , bold ( p [ ' param_name ' ] ) , default , ' , ' ] )
else :
param = join ( [ param , color ( COLOR_PARAM , bold ( p [ ' param_name ' ] ) + create_hyperlinks ( default ) ) , ' , ' ] )
if with_self :
method [ ' params ' ] = method [ ' params ' ] [ 1 : ]
2019-08-15 01:44:55 +08:00
if not method [ ' params ' ] : # if is empty delete it
2019-06-07 18:58:00 +08:00
del method [ ' params ' ]
2019-08-15 01:44:55 +08:00
param = param [ : - 2 ] # delete the last ', '
2020-10-15 22:48:48 +08:00
# Add snipet
current_folder = os . path . dirname ( os . path . abspath ( __file__ ) )
snipets_path = os . path . join ( current_folder , ' ../../Docs/python_api_snipets.md ' )
snipets = open ( snipets_path , ' r ' )
if class_key + ' . ' + full_method_name + ' -snipet ' in snipets . read ( ) :
snipet_link = snipet ( full_method_name , class_key )
return join ( [ method_name , parentheses ( param ) , snipet_link ] )
2019-04-25 18:21:25 +08:00
2020-03-30 17:18:13 +08:00
def gen_doc_dunder_def ( dunder , is_indx = False , with_self = True ) :
""" Return python def as it should be written in docs """
param = ' '
dunder_name = dunder [ ' def_name ' ]
if valid_dic_val ( dunder , ' static ' ) :
with_self = False
2020-10-15 22:48:48 +08:00
# to correctly render methods like __init__ in md
2020-03-30 17:18:13 +08:00
if dunder_name [ 0 ] == ' _ ' :
dunder_name = ' \\ ' + dunder_name
if is_indx :
dunder_name = bold ( dunder_name )
else :
dunder_name = bold ( color ( COLOR_METHOD , dunder_name ) )
if with_self :
if not ' params ' in dunder or dunder [ ' params ' ] is None :
dunder [ ' params ' ] = [ ]
dunder [ ' params ' ] . insert ( 0 , { ' param_name ' : ' self ' } )
if valid_dic_val ( dunder , ' params ' ) :
for p in dunder [ ' params ' ] :
default = join ( [ ' = ' , str ( p [ ' type ' ] ) ] ) if ' type ' in p else ' '
if is_indx :
param = join ( [ param , bold ( p [ ' param_name ' ] ) , default , ' , ' ] )
else :
param = join ( [ param , color ( COLOR_PARAM , bold ( p [ ' param_name ' ] ) + create_hyperlinks ( default ) ) , ' , ' ] )
if with_self :
dunder [ ' params ' ] = dunder [ ' params ' ] [ 1 : ]
if not dunder [ ' params ' ] : # if is empty delete it
del dunder [ ' params ' ]
param = param [ : - 2 ] # delete the last ', '
return join ( [ dunder_name , parentheses ( param ) ] )
2019-04-25 18:21:25 +08:00
def gen_inst_var_indx ( inst_var , class_key ) :
inst_var_name = inst_var [ ' var_name ' ]
2019-06-05 21:05:57 +08:00
inst_var_key = join ( [ class_key , inst_var_name ] , ' . ' )
return join ( [
2019-04-25 18:21:25 +08:00
brackets ( bold ( inst_var_name ) ) ,
parentheses ( inst_var_key ) , ' ' ,
sub ( italic ( ' Instance variable ' ) ) ] )
def gen_method_indx ( method , class_key ) :
method_name = method [ ' def_name ' ]
2019-06-05 21:05:57 +08:00
method_key = join ( [ class_key , method_name ] , ' . ' )
2020-10-15 22:48:48 +08:00
method_def = gen_doc_method_def ( method , class_key , True )
2019-06-05 21:05:57 +08:00
return join ( [
2019-04-25 18:21:25 +08:00
brackets ( method_def ) ,
parentheses ( method_key ) , ' ' ,
sub ( italic ( ' Method ' ) ) ] )
def add_doc_method_param ( md , param ) :
param_name = param [ ' param_name ' ]
param_type = ' '
param_doc = ' '
2020-09-14 22:58:48 +08:00
param_units = ' '
2019-04-25 18:21:25 +08:00
if valid_dic_val ( param , ' type ' ) :
2019-06-04 00:35:57 +08:00
param_type = create_hyperlinks ( param [ ' type ' ] )
2019-04-25 18:21:25 +08:00
if valid_dic_val ( param , ' doc ' ) :
2019-06-04 00:35:57 +08:00
param_doc = create_hyperlinks ( md . prettify_doc ( param [ ' doc ' ] ) )
2020-09-14 22:58:48 +08:00
if valid_dic_val ( param , ' param_units ' ) :
2021-11-04 17:07:41 +08:00
param_units = small_html ( ' - ' + param [ ' param_units ' ] )
2020-09-14 22:58:48 +08:00
param_type = ' ' if not param_type else parentheses ( italic ( param_type + param_units ) )
2019-05-03 18:00:40 +08:00
md . list_push ( code ( param_name ) )
if param_type :
md . text ( ' ' + param_type )
2019-04-25 18:21:25 +08:00
if param_doc :
2021-11-04 17:07:41 +08:00
md . textn ( ' - ' + param_doc )
2019-05-03 18:00:40 +08:00
else :
md . new_line ( )
2019-04-25 18:21:25 +08:00
md . list_pop ( )
def add_doc_method ( md , method , class_key ) :
method_name = method [ ' def_name ' ]
2019-06-05 21:05:57 +08:00
method_key = join ( [ class_key , method_name ] , ' . ' )
2020-10-15 22:48:48 +08:00
method_def = gen_doc_method_def ( method , class_key , False )
2019-06-05 21:05:57 +08:00
md . list_pushn ( join ( [ html_key ( method_key ) , method_def ] ) )
2019-06-07 18:58:00 +08:00
# Method doc
if valid_dic_val ( method , ' doc ' ) :
2019-06-04 00:35:57 +08:00
md . textn ( create_hyperlinks ( md . prettify_doc ( method [ ' doc ' ] ) ) )
2019-06-07 18:58:00 +08:00
printed_title = False
if valid_dic_val ( method , ' params ' ) :
for param in method [ ' params ' ] :
# is_self = valid_dic_val(param, 'param_name') and param['param_name'] == 'self'
have_doc = valid_dic_val ( param , ' doc ' )
have_type = valid_dic_val ( param , ' type ' )
if not have_doc and not have_type :
2019-04-25 18:21:25 +08:00
continue
2019-06-05 21:05:57 +08:00
# Print the 'Parameters' title once
if not printed_title :
printed_title = True
md . list_push ( bold ( ' Parameters: ' ) + ' \n ' )
2019-06-07 18:58:00 +08:00
add_doc_method_param ( md , param )
if printed_title :
md . list_pop ( )
2019-06-05 21:05:57 +08:00
# Return doc
2019-05-23 17:50:16 +08:00
if valid_dic_val ( method , ' return ' ) :
md . list_push ( bold ( ' Return: ' ) + ' ' )
2020-09-14 22:58:48 +08:00
return_units = ' '
if valid_dic_val ( method , ' return_units ' ) :
2021-11-04 17:07:41 +08:00
return_units = small_html ( ' - ' + method [ ' return_units ' ] )
2020-09-14 22:58:48 +08:00
md . textn ( italic ( create_hyperlinks ( method [ ' return ' ] ) + return_units ) )
2019-05-23 17:50:16 +08:00
md . list_pop ( )
2019-06-05 21:05:57 +08:00
# Note doc
if valid_dic_val ( method , ' note ' ) :
md . list_push ( bold ( ' Note: ' ) + ' ' )
md . textn ( color ( COLOR_NOTE , italic ( create_hyperlinks ( method [ ' note ' ] ) ) ) )
md . list_pop ( )
2019-06-07 18:58:00 +08:00
# Warning doc
if valid_dic_val ( method , ' warning ' ) :
md . list_push ( bold ( ' Warning: ' ) + ' ' )
md . textn ( color ( COLOR_WARNING , italic ( create_hyperlinks ( method [ ' warning ' ] ) ) ) )
md . list_pop ( )
2019-06-05 21:05:57 +08:00
# Raises error doc
2019-04-25 18:21:25 +08:00
if valid_dic_val ( method , ' raises ' ) :
md . list_pushn ( bold ( ' Raises: ' ) + ' ' + method [ ' raises ' ] )
md . list_pop ( )
2019-06-05 21:05:57 +08:00
2019-04-25 18:21:25 +08:00
md . list_pop ( )
2020-10-15 22:48:48 +08:00
def add_doc_getter_setter ( md , method , class_key , is_getter , other_list ) :
2020-04-18 00:14:51 +08:00
method_name = method [ ' def_name ' ]
method_key = join ( [ class_key , method_name ] , ' . ' )
2020-10-15 22:48:48 +08:00
method_def = gen_doc_method_def ( method , class_key , False )
2020-04-18 00:14:51 +08:00
md . list_pushn ( join ( [ html_key ( method_key ) , method_def ] ) )
# Method doc
if valid_dic_val ( method , ' doc ' ) :
md . textn ( create_hyperlinks ( md . prettify_doc ( method [ ' doc ' ] ) ) )
printed_title = False
if valid_dic_val ( method , ' params ' ) :
for param in method [ ' params ' ] :
# is_self = valid_dic_val(param, 'param_name') and param['param_name'] == 'self'
have_doc = valid_dic_val ( param , ' doc ' )
have_type = valid_dic_val ( param , ' type ' )
if not have_doc and not have_type :
continue
# Print the 'Parameters' title once
if not printed_title :
printed_title = True
md . list_push ( bold ( ' Parameters: ' ) + ' \n ' )
add_doc_method_param ( md , param )
if printed_title :
md . list_pop ( )
# Return doc
if valid_dic_val ( method , ' return ' ) :
md . list_push ( bold ( ' Return: ' ) + ' ' )
2020-09-14 22:58:48 +08:00
return_units = ' '
if valid_dic_val ( method , ' return_units ' ) :
2021-11-04 17:07:41 +08:00
return_units = small_html ( ' - ' + method [ ' return_units ' ] )
2020-09-14 22:58:48 +08:00
md . textn ( italic ( create_hyperlinks ( method [ ' return ' ] ) + return_units ) )
2020-04-18 00:14:51 +08:00
md . list_pop ( )
# If setter/getter
for element in other_list :
el_name = element [ ' def_name ' ]
if el_name [ 4 : ] == method_name [ 4 : ] :
if is_getter :
md . list_push ( bold ( ' Setter: ' ) + ' ' )
else :
md . list_push ( bold ( ' Getter: ' ) + ' ' )
md . textn ( italic ( create_hyperlinks ( class_key + ' . ' + el_name ) ) )
md . list_pop ( )
# Note doc
if valid_dic_val ( method , ' note ' ) :
md . list_push ( bold ( ' Note: ' ) + ' ' )
md . textn ( color ( COLOR_NOTE , italic ( create_hyperlinks ( method [ ' note ' ] ) ) ) )
md . list_pop ( )
# Warning doc
if valid_dic_val ( method , ' warning ' ) :
md . list_push ( bold ( ' Warning: ' ) + ' ' )
md . textn ( color ( COLOR_WARNING , italic ( create_hyperlinks ( method [ ' warning ' ] ) ) ) )
md . list_pop ( )
# Raises error doc
if valid_dic_val ( method , ' raises ' ) :
md . list_pushn ( bold ( ' Raises: ' ) + ' ' + method [ ' raises ' ] )
md . list_pop ( )
md . list_pop ( )
2020-03-30 17:18:13 +08:00
def add_doc_dunder ( md , dunder , class_key ) :
dunder_name = dunder [ ' def_name ' ]
dunder_key = join ( [ class_key , dunder_name ] , ' . ' )
dunder_def = gen_doc_dunder_def ( dunder , False )
md . list_pushn ( join ( [ html_key ( dunder_key ) , dunder_def ] ) )
# Dunder doc
if valid_dic_val ( dunder , ' doc ' ) :
md . textn ( create_hyperlinks ( md . prettify_doc ( dunder [ ' doc ' ] ) ) )
# Return doc
if valid_dic_val ( dunder , ' return ' ) :
md . list_push ( bold ( ' Return: ' ) + ' ' )
md . textn ( italic ( create_hyperlinks ( dunder [ ' return ' ] ) ) )
md . list_pop ( )
md . list_pop ( )
def add_doc_dunder_param ( md , param ) :
param_name = param [ ' param_name ' ]
param_type = ' '
if valid_dic_val ( param , ' type ' ) :
param_type = create_hyperlinks ( param [ ' type ' ] )
param_type = ' ' if not param_type else parentheses ( italic ( param_type ) )
md . list_push ( code ( param_name ) )
if param_type :
md . text ( ' ' + param_type )
md . new_line ( )
else :
md . new_line ( )
md . list_pop ( )
2019-04-25 18:21:25 +08:00
def add_doc_inst_var ( md , inst_var , class_key ) :
var_name = inst_var [ ' var_name ' ]
2019-06-05 21:05:57 +08:00
var_key = join ( [ class_key , var_name ] , ' . ' )
2019-05-23 17:50:16 +08:00
var_type = ' '
2020-09-14 22:58:48 +08:00
var_units = ' '
2019-06-07 18:58:00 +08:00
# Instance variable type
2019-05-23 17:50:16 +08:00
if valid_dic_val ( inst_var , ' type ' ) :
2020-09-14 22:58:48 +08:00
if valid_dic_val ( inst_var , ' var_units ' ) :
2021-11-04 17:07:41 +08:00
var_units = small_html ( ' - ' + inst_var [ ' var_units ' ] )
2020-09-14 22:58:48 +08:00
var_type = ' ' + parentheses ( italic ( create_hyperlinks ( inst_var [ ' type ' ] + var_units ) ) )
2019-05-23 17:50:16 +08:00
md . list_pushn (
html_key ( var_key ) +
bold ( color ( COLOR_INSTANCE_VAR , var_name ) ) +
var_type )
2019-06-07 18:58:00 +08:00
# Instance variable doc
2019-05-03 18:00:40 +08:00
if valid_dic_val ( inst_var , ' doc ' ) :
2019-06-04 00:35:57 +08:00
md . textn ( create_hyperlinks ( md . prettify_doc ( inst_var [ ' doc ' ] ) ) )
2019-06-07 18:58:00 +08:00
# Note doc
if valid_dic_val ( inst_var , ' note ' ) :
md . list_push ( bold ( ' Note: ' ) + ' ' )
md . textn ( color ( COLOR_NOTE , italic ( create_hyperlinks ( inst_var [ ' note ' ] ) ) ) )
md . list_pop ( )
# Warning doc
if valid_dic_val ( inst_var , ' warning ' ) :
md . list_push ( bold ( ' Warning: ' ) + ' ' )
md . textn ( color ( COLOR_WARNING , italic ( create_hyperlinks ( inst_var [ ' warning ' ] ) ) ) )
md . list_pop ( )
2019-04-25 18:21:25 +08:00
md . list_pop ( )
class Documentation :
""" Main documentation class """
def __init__ ( self , path ) :
self . _path = path
self . _files = [ f for f in os . listdir ( path ) if f . endswith ( ' .yml ' ) ]
self . _yamls = list ( )
for yaml_file in self . _files :
self . _yamls . append ( YamlFile ( os . path . join ( path , yaml_file ) ) )
2019-06-07 18:58:00 +08:00
# Merge same modules of different files
2019-04-25 18:21:25 +08:00
self . master_dict = dict ( )
for yaml_file in self . _yamls :
for module in yaml_file . get_modules ( ) :
module_name = module [ ' module_name ' ]
if module_name not in self . master_dict :
self . master_dict [ module_name ] = module
2019-05-03 18:00:40 +08:00
elif valid_dic_val ( module , ' classes ' ) :
2019-04-25 18:21:25 +08:00
for new_module in module [ ' classes ' ] :
2019-05-03 18:00:40 +08:00
# Create the 'classes' key if does not exist already
if not valid_dic_val ( self . master_dict [ module_name ] , ' classes ' ) :
self . master_dict [ module_name ] [ ' classes ' ] = [ ]
2019-04-25 18:21:25 +08:00
self . master_dict [ module_name ] [ ' classes ' ] . append ( new_module )
def gen_overview ( self ) :
""" Generates a referenced index for markdown file """
md = MarkdownFile ( )
md . title ( 3 , ' Overview ' )
2019-05-03 20:53:40 +08:00
for module_name in sorted ( self . master_dict ) :
2019-04-25 18:21:25 +08:00
module = self . master_dict [ module_name ]
module_key = ' # ' + module_name
md . list_pushn (
brackets ( bold ( module_key [ 1 : ] ) ) +
parentheses ( module_key ) + ' ' +
sub ( italic ( ' Module ' ) ) )
# Generate class overview (if any)
if ' classes ' in module and module [ ' classes ' ] :
2019-05-03 20:53:40 +08:00
for cl in sorted ( module [ ' classes ' ] ) :
2019-04-25 18:21:25 +08:00
class_name = cl [ ' class_name ' ]
2019-06-05 21:05:57 +08:00
class_key = join ( [ module_key , class_name ] , ' . ' )
md . list_pushn ( join ( [
brackets ( bold ( class_name ) ) ,
parentheses ( class_key ) , ' ' ,
sub ( italic ( ' Class ' ) ) ] ) )
2019-04-25 18:21:25 +08:00
# Generate class instance variables overview (if any)
if ' instance_variables ' in cl and cl [ ' instance_variables ' ] :
for inst_var in cl [ ' instance_variables ' ] :
md . list_push ( gen_inst_var_indx ( inst_var , class_key ) )
md . list_popn ( )
# Generate class methods overview (if any)
if ' methods ' in cl and cl [ ' methods ' ] :
2020-10-16 15:59:54 +08:00
for method in sorted ( cl [ ' methods ' ] , key = lambda i : i [ ' def_name ' ] ) :
2019-04-25 18:21:25 +08:00
md . list_push ( gen_method_indx ( method , class_key ) )
md . list_popn ( )
md . list_pop ( )
md . list_pop ( )
return md . data ( )
def gen_body ( self ) :
2020-02-11 17:15:18 +08:00
""" Generates the documentation body """
2019-04-25 18:21:25 +08:00
md = MarkdownFile ( )
2020-03-02 16:40:34 +08:00
md . first_title ( )
2020-04-18 00:14:51 +08:00
md . textn (
2020-05-07 20:11:34 +08:00
" This reference contains all the details the Python API. To consult a previous reference for a specific CARLA release, change the documentation version using the panel in the bottom right corner.<br> "
2021-02-25 19:35:53 +08:00
+ " This will change the whole documentation to a previous state. Remember that the <i>latest</i> version is the `dev` branch and may show features not available in any packaged versions of CARLA.<hr> " )
2019-05-03 20:53:40 +08:00
for module_name in sorted ( self . master_dict ) :
2019-04-25 18:21:25 +08:00
module = self . master_dict [ module_name ]
module_key = module_name
# Generate class doc (if any)
if valid_dic_val ( module , ' classes ' ) :
2020-02-11 17:37:41 +08:00
for cl in sorted ( module [ ' classes ' ] , key = lambda i : i [ ' class_name ' ] ) :
2019-04-25 18:21:25 +08:00
class_name = cl [ ' class_name ' ]
2019-06-05 21:05:57 +08:00
class_key = join ( [ module_key , class_name ] , ' . ' )
2020-02-11 17:15:18 +08:00
current_title = module_name + ' . ' + class_name
2020-11-24 01:45:37 +08:00
md . title ( 2 , join ( [ current_title , ' <a name= " ' , current_title , ' " ></a> ' ] ) )
# Inheritance
2019-06-05 21:05:57 +08:00
if valid_dic_val ( cl , ' parent ' ) :
2020-02-11 17:15:18 +08:00
inherits = italic ( create_hyperlinks ( cl [ ' parent ' ] ) )
md . inherit_join ( inherits )
2019-05-22 00:42:25 +08:00
# Class main doc
if valid_dic_val ( cl , ' doc ' ) :
2019-06-04 00:35:57 +08:00
md . textn ( create_hyperlinks ( md . prettify_doc ( cl [ ' doc ' ] ) ) )
2019-04-25 18:21:25 +08:00
# Generate instance variable doc (if any)
if valid_dic_val ( cl , ' instance_variables ' ) :
2020-12-14 20:15:32 +08:00
md . title ( 3 , ' Instance Variables ' )
2019-04-25 18:21:25 +08:00
for inst_var in cl [ ' instance_variables ' ] :
add_doc_inst_var ( md , inst_var , class_key )
# Generate method doc (if any)
if valid_dic_val ( cl , ' methods ' ) :
2020-03-30 17:18:13 +08:00
method_list = list ( )
dunder_list = list ( )
2020-04-18 00:14:51 +08:00
get_list = list ( )
set_list = list ( )
2020-10-16 15:55:27 +08:00
for method in sorted ( cl [ ' methods ' ] , key = lambda i : i [ ' def_name ' ] ) :
2020-03-30 17:18:13 +08:00
method_name = method [ ' def_name ' ]
if method_name [ 0 ] == ' _ ' and method_name != ' __init__ ' :
dunder_list . append ( method )
2020-04-18 00:14:51 +08:00
elif method_name [ : 4 ] == ' get_ ' :
get_list . append ( method )
elif method_name [ : 4 ] == ' set_ ' :
set_list . append ( method )
2020-03-30 17:18:13 +08:00
else :
method_list . append ( method )
2020-12-14 20:15:32 +08:00
md . title ( 3 , ' Methods ' )
2020-03-30 17:18:13 +08:00
for method in method_list :
2019-04-25 18:21:25 +08:00
add_doc_method ( md , method , class_key )
2020-04-18 00:14:51 +08:00
if len ( get_list ) > 0 :
2020-12-14 20:15:32 +08:00
md . title ( 5 , ' Getters ' )
2020-04-18 00:14:51 +08:00
for method in get_list :
2020-10-15 22:48:48 +08:00
add_doc_getter_setter ( md , method , class_key , True , set_list )
2020-04-18 00:14:51 +08:00
if len ( set_list ) > 0 :
2020-12-14 20:15:32 +08:00
md . title ( 5 , ' Setters ' )
2020-04-18 00:14:51 +08:00
for method in set_list :
2020-10-15 22:48:48 +08:00
add_doc_getter_setter ( md , method , class_key , False , get_list )
2020-03-30 17:18:13 +08:00
if len ( dunder_list ) > 0 :
2020-12-14 20:15:32 +08:00
md . title ( 5 , ' Dunder methods ' )
2020-03-30 17:18:13 +08:00
for method in dunder_list :
add_doc_dunder ( md , method , class_key )
2019-04-25 18:21:25 +08:00
md . separator ( )
2020-10-15 22:48:48 +08:00
append_code_snipets ( md )
append_snipet_button_script ( md )
2019-04-25 18:21:25 +08:00
return md . data ( ) . strip ( )
def gen_markdown ( self ) :
""" Generates the whole markdown file """
2019-09-06 17:07:21 +08:00
return join ( [ self . gen_body ( ) ] , ' \n ' ) . strip ( )
2019-04-19 02:13:34 +08:00
2019-08-15 01:44:55 +08:00
2019-04-19 02:13:34 +08:00
def main ( ) :
""" Main function """
2019-05-22 00:42:25 +08:00
print ( " Generating PythonAPI documentation... " )
2019-04-19 02:13:34 +08:00
script_path = os . path . dirname ( os . path . abspath ( __file__ ) )
2020-10-15 22:48:48 +08:00
doc_gen_snipets . main ( )
2019-04-25 18:21:25 +08:00
docs = Documentation ( script_path )
with open ( os . path . join ( script_path , ' ../../Docs/python_api.md ' ) , ' w ' ) as md_file :
md_file . write ( docs . gen_markdown ( ) )
2019-05-22 00:42:25 +08:00
print ( " Done! " )
2019-04-19 02:13:34 +08:00
2019-08-15 01:44:55 +08:00
2019-04-19 02:13:34 +08:00
if __name__ == " __main__ " :
main ( )