11# Copyright (c) 2023 Intel Corporation 
22# SPDX-License-Identifier: Apache-2.0 
33
4- import  doxmlparser 
4+ import  os 
5+ from  pathlib  import  Path 
6+ from  typing  import  Any 
57
8+ import  doxmlparser 
69from  docutils  import  nodes 
710from  doxmlparser .compound  import  DoxCompoundKind 
8- from  pathlib  import  Path 
9- from  sphinx .application  import  Sphinx 
1011from  sphinx .util .docutils  import  SphinxDirective 
11- from  typing  import  Any , Dict 
12+ 
13+ 
14+ def  get_group (innergroup , all_groups ):
15+     try :
16+         return  [
17+             g 
18+             for  g  in  all_groups 
19+             if  g .get_compounddef ()[0 ].get_id () ==  innergroup .get_refid ()
20+         ][0 ]
21+     except  IndexError  as  e :
22+         raise  Exception (f"Unexpected group { innergroup .get_refid ()}  " ) from  e 
23+ 
24+ 
25+ def  parse_xml_dir (dir_name ):
26+     groups  =  []
27+     root  =  doxmlparser .index .parse (Path (dir_name ) /  "index.xml" , True )
28+     for  compound  in  root .get_compound ():
29+         if  compound .get_kind () ==  DoxCompoundKind .GROUP :
30+             file_name  =  Path (dir_name ) /  f"{ compound .get_refid ()}  .xml" 
31+             groups .append (doxmlparser .compound .parse (file_name , True ))
32+ 
33+     return  groups 
1234
1335
1436class  ApiOverview (SphinxDirective ):
@@ -21,154 +43,121 @@ class ApiOverview(SphinxDirective):
2143
2244    Configuration options: 
2345
24-     api_overview_doxygen_xml_dir: Doxygen xml output directory 
25-     api_overview_doxygen_base_url: Doxygen base html directory 
46+     api_overview_doxygen_out_dir: Doxygen output directory 
2647    """ 
2748
2849    def  run (self ):
29-         return  [ self .env . api_overview_table ] 
50+         groups   =   parse_xml_dir ( self .config . api_overview_doxygen_out_dir   +   "/xml" ) 
3051
31- 
32- def  get_group (innergroup , all_groups ):
33-     try :
34-         return  [
52+         toplevel  =  [
3553            g 
36-             for  g  in  all_groups 
37-             if  g .get_compounddef ()[0 ].get_id () ==  innergroup .get_refid ()
38-         ][0 ]
39-     except  IndexError  as  e :
40-         raise  Exception (f"Unexpected group { innergroup .get_refid ()}  " ) from  e 
41- 
42- 
43- def  visit_group (app , group , all_groups , rows , indent = 0 ):
44-     version  =  since  =  "" 
45-     github_uri  =  "https://github.com/zephyrproject-rtos/zephyr/releases/tag/" 
46-     cdef  =  group .get_compounddef ()[0 ]
54+             for  g  in  groups 
55+             if  g .get_compounddef ()[0 ].get_id ()
56+             not  in   [
57+                 i .get_refid ()
58+                 for  h  in  [j .get_compounddef ()[0 ].get_innergroup () for  j  in  groups ]
59+                 for  i  in  h 
60+             ]
61+         ]
4762
48-     ssects  =  [
49-         s  for  p  in  cdef .get_detaileddescription ().get_para () for  s  in  p .get_simplesect ()
50-     ]
51-     for  sect  in  ssects :
52-         if  sect .get_kind () ==  "since" :
53-             since  =  sect .get_para ()[0 ].get_valueOf_ ()
54-         elif  sect .get_kind () ==  "version" :
55-             version  =  sect .get_para ()[0 ].get_valueOf_ ()
63+         return  [self .generate_table (toplevel , groups )]
5664
57-     if  since :
58-         since_url  =  nodes .inline ()
59-         reference  =  nodes .reference (text = f"v{ since .strip ()}  .0" , refuri = f"{ github_uri }  /v{ since .strip ()}  .0" )
60-         reference .attributes ["internal" ] =  True 
61-         since_url  +=  reference 
62-     else :
63-         since_url  =  nodes .Text ("" )
65+     def  generate_table (self , toplevel , groups ):
66+         table  =  nodes .table ()
67+         tgroup  =  nodes .tgroup ()
6468
65-     url_base  =  Path (app .config .api_overview_doxygen_base_url )
66-     url  =  url_base  /  f"{ cdef .get_id ()}  .html" 
69+         thead  =  nodes .thead ()
70+         thead_row  =  nodes .row ()
71+         for  header_name  in  ["API" , "Version" , "Available in Zephyr Since" ]:
72+             colspec  =  nodes .colspec ()
73+             tgroup  +=  colspec 
6774
68-     title  =  cdef .get_title ()
75+             entry  =  nodes .entry ()
76+             entry  +=  nodes .Text (header_name )
77+             thead_row  +=  entry 
78+         thead  +=  thead_row 
79+         tgroup  +=  thead 
6980
70-     row_node  =  nodes .row ()
81+         rows  =  []
82+         tbody  =  nodes .tbody ()
83+         for  t  in  toplevel :
84+             self .visit_group (t , groups , rows )
85+         tbody .extend (rows )
86+         tgroup  +=  tbody 
7187
72-     # Next entry will contain the spacer and the link with API name 
73-     entry  =  nodes .entry ()
74-     span  =  nodes .Text ("" .join (["\U000000A0 " ] *  indent ))
75-     entry  +=  span 
88+         table  +=  tgroup 
7689
77-     # API name with link 
78-     inline  =  nodes .inline ()
79-     reference  =  nodes .reference (text = title , refuri = str (url ))
80-     reference .attributes ["internal" ] =  True 
81-     inline  +=  reference 
82-     entry  +=  inline 
83-     row_node  +=  entry 
90+         return  table 
8491
85-     version_node  =  nodes .Text (version )
86-     # Finally, add version and since 
87-     for  cell  in  [version_node , since_url ]:
88-         entry  =  nodes .entry ()
89-         entry  +=  cell 
90-         row_node  +=  entry 
91-     rows .append (row_node )
92+     def  visit_group (self , group , all_groups , rows , indent = 0 ):
93+         version  =  since  =  "" 
94+         github_uri  =  "https://github.com/zephyrproject-rtos/zephyr/releases/tag/" 
95+         cdef  =  group .get_compounddef ()[0 ]
9296
93-     for  innergroup  in  cdef .get_innergroup ():
94-         visit_group (
95-             app , get_group (innergroup , all_groups ), all_groups , rows , indent  +  6 
97+         ssects  =  [
98+             s  for  p  in  cdef .get_detaileddescription ().get_para () for  s  in  p .get_simplesect ()
99+         ]
100+         for  sect  in  ssects :
101+             if  sect .get_kind () ==  "since" :
102+                 since  =  sect .get_para ()[0 ].get_valueOf_ ()
103+             elif  sect .get_kind () ==  "version" :
104+                 version  =  sect .get_para ()[0 ].get_valueOf_ ()
105+ 
106+         if  since :
107+             since_url  =  nodes .inline ()
108+             reference  =  nodes .reference (
109+                 text = f"v{ since .strip ()}  .0" , refuri = f"{ github_uri }  /v{ since .strip ()}  .0" 
110+             )
111+             reference .attributes ["internal" ] =  True 
112+             since_url  +=  reference 
113+         else :
114+             since_url  =  nodes .Text ("" )
115+ 
116+         url_base  =  Path (self .config .api_overview_doxygen_out_dir  +  "/html" )
117+         abs_url  =  url_base  /  f"{ cdef .get_id ()}  .html" 
118+         doc_dir  =  os .path .dirname (self .get_source_info ()[0 ])
119+         doc_dest  =  os .path .join (
120+             self .env .app .outdir ,
121+             os .path .relpath (doc_dir , self .env .app .srcdir ),
96122        )
123+         url  =  os .path .relpath (abs_url , doc_dest )
97124
125+         title  =  cdef .get_title ()
98126
99- def  parse_xml_dir (dir_name ):
100-     groups  =  []
101-     root  =  doxmlparser .index .parse (Path (dir_name ) /  "index.xml" , True )
102-     for  compound  in  root .get_compound ():
103-         if  compound .get_kind () ==  DoxCompoundKind .GROUP :
104-             file_name  =  Path (dir_name ) /  f"{ compound .get_refid ()}  .xml" 
105-             groups .append (doxmlparser .compound .parse (file_name , True ))
106- 
107-     return  groups 
127+         row_node  =  nodes .row ()
108128
129+         # Next entry will contain the spacer and the link with API name 
130+         entry  =  nodes .entry ()
131+         span  =  nodes .Text ("" .join (["\U000000A0 " ] *  indent ))
132+         entry  +=  span 
109133
110- def  generate_table (app , toplevel , groups ):
111-     table  =  nodes .table ()
112-     tgroup  =  nodes .tgroup ()
134+         # API name with link 
135+         inline  =  nodes .inline ()
136+         reference  =  nodes .reference (text = title , refuri = str (url ))
137+         reference .attributes ["internal" ] =  True 
138+         inline  +=  reference 
139+         entry  +=  inline 
140+         row_node  +=  entry 
113141
114-     thead  =  nodes .thead ()
115-     thead_row  =  nodes .row ()
116-     for  header_name  in  ["API" , "Version" , "Available in Zephyr Since" ]:
117-         colspec  =  nodes .colspec ()
118-         tgroup  +=  colspec 
142+         version_node  =  nodes .Text (version )
143+         # Finally, add version and since 
144+         for  cell  in  [version_node , since_url ]:
145+             entry  =  nodes .entry ()
146+             entry  +=  cell 
147+             row_node  +=  entry 
148+         rows .append (row_node )
119149
120-         entry  =  nodes .entry ()
121-         entry  +=  nodes .Text (header_name )
122-         thead_row  +=  entry 
123-     thead  +=  thead_row 
124-     tgroup  +=  thead 
125- 
126-     rows  =  []
127-     tbody  =  nodes .tbody ()
128-     for  t  in  toplevel :
129-         visit_group (app , t , groups , rows )
130-     tbody .extend (rows )
131-     tgroup  +=  tbody 
132- 
133-     table  +=  tgroup 
134- 
135-     return  table 
136- 
137- 
138- def  sync_contents (app : Sphinx ) ->  None :
139-     if  app .config .doxyrunner_outdir :
140-         doxygen_out_dir  =  Path (app .config .doxyrunner_outdir )
141-     else :
142-         doxygen_out_dir  =  Path (app .outdir ) /  "_doxygen" 
143- 
144-     if  not  app .env .doxygen_input_changed :
145-         return 
146- 
147-     doxygen_xml_dir  =  doxygen_out_dir  /  "xml" 
148-     groups  =  parse_xml_dir (doxygen_xml_dir )
149- 
150-     toplevel  =  [
151-         g 
152-         for  g  in  groups 
153-         if  g .get_compounddef ()[0 ].get_id ()
154-         not  in   [
155-             i .get_refid ()
156-             for  h  in  [j .get_compounddef ()[0 ].get_innergroup () for  j  in  groups ]
157-             for  i  in  h 
158-         ]
159-     ]
160- 
161-     app .builder .env .api_overview_table  =  generate_table (app , toplevel , groups )
150+         for  innergroup  in  cdef .get_innergroup ():
151+             self .visit_group (
152+                 get_group (innergroup , all_groups ), all_groups , rows , indent  +  6 
153+             )
162154
163155
164- def  setup (app ) ->  Dict [str , Any ]:
165-     app .add_config_value ("api_overview_doxygen_xml_dir" , "html/doxygen/xml" , "env" )
166-     app .add_config_value ("api_overview_doxygen_base_url" , "../../doxygen/html" , "env" )
156+ def  setup (app ) ->  dict [str , Any ]:
157+     app .add_config_value ("api_overview_doxygen_out_dir" , "" , "env" )
167158
168159    app .add_directive ("api-overview-table" , ApiOverview )
169160
170-     app .connect ("builder-inited" , sync_contents )
171- 
172161    return  {
173162        "version" : "0.1" ,
174163        "parallel_read_safe" : True ,
0 commit comments