6281cc66f4782154507bc1d7c7d9adc2b3541a94
[blender.git] / source / blender / python / epy_doc_gen.py
1  # ***** BEGIN GPL LICENSE BLOCK *****
2  #
3  # This program is free software; you can redistribute it and/or
4  # modify it under the terms of the GNU General Public License
5  # as published by the Free Software Foundation; either version 2
6  # of the License, or (at your option) any later version.
7  #
8  # This program is distributed in the hope that it will be useful,
9  # but WITHOUT ANY WARRANTY; without even the implied warranty of
10  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  # GNU General Public License for more details.
12  #
13  # You should have received a copy of the GNU General Public License
14  # along with this program; if not, write to the Free Software Foundation,
15  # Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
16  #
17  # Contributor(s): Campbell Barton
18  #
19  # #**** END GPL LICENSE BLOCK #****
20
21 # Usage,
22 # run this script from blenders root path once you have compiled blender
23 # ./blender.bin -b -P source/blender/python/epy_doc_gen.py
24
25 # This will generate rna.py, generate html docs  by running...
26 # epydoc source/blender/python/doc/rna.py -o source/blender/python/doc/html -v --no-sourcecode --name="RNA API" --url="http://brechtvanlommelfanclub.com" --graph=classtree
27
28 # if you dont have graphvis installed ommit the --graph arg.
29
30 def range_str(val):
31         if val < -10000000:     return '-inf'
32         if val >  10000000:     return 'inf'
33         if type(val)==float:
34                 return '%g'  % val
35         else:
36                 return str(val) 
37
38 def get_array_str(length):
39         if length > 0:  return ' array of %d items' % length
40         else:           return ''
41
42 def rna2epy(target_path):
43         
44
45         
46         def write_struct(rna_struct, structs, ident):
47                 identifier = rna_struct.identifier
48                 
49                 rna_base = rna_struct.base
50                 
51                 if rna_base:
52                         out.write(ident+ 'class %s(%s):\n' % (identifier, rna_base.identifier))
53                 else:
54                         out.write(ident+ 'class %s:\n' % identifier)
55                 
56                 out.write(ident+ '\t"""\n')
57                 
58                 title = 'The %s Object' % rna_struct.name
59                 
60                 out.write(ident+ '\t%s\n' %  title)
61                 out.write(ident+ '\t%s\n' %  ('=' * len(title)))
62                 out.write(ident+ '\t\t%s\n' %  rna_struct.description)
63                 
64                 for rna_prop_identifier, rna_prop in rna_struct.properties.items():
65                         
66                         if rna_prop_identifier=='RNA':
67                                 continue
68                         
69                         if rna_prop_identifier=='rna_type':
70                                 continue
71                         
72                         rna_desc = rna_prop.description
73                         if not rna_desc: rna_desc = rna_prop.name
74                         if not rna_desc: rna_desc = 'Note - No documentation for this property!'
75                         
76                         rna_prop_type = rna_prop.type.lower()
77                         
78                         if rna_prop_type=='collection': collection_str = 'Collection of '
79                         else:                                                   collection_str = ''
80                         
81                         try:            rna_prop_ptr = rna_prop.fixed_type
82                         except: rna_prop_ptr = None
83                         
84                         try:            length = rna_prop.array_length
85                         except: length = 0
86                         
87                         array_str = get_array_str(length)
88                         
89                         if rna_prop.editable:   readonly_str = ''
90                         else:                           readonly_str = ' (readonly)'
91                         
92                         if rna_prop_ptr: # Use the pointer type
93                                 out.write(ident+ '\t@ivar %s: %s\n' %  (rna_prop_identifier, rna_desc))
94                                 out.write(ident+ '\t@type %s: %sL{%s}%s%s\n' %  (rna_prop_identifier, collection_str, rna_prop_ptr.identifier, array_str, readonly_str))
95                         else:
96                                 if rna_prop_type == 'enum':
97                                         out.write(ident+ '\t@ivar %s: %s in (%s)\n' %  (rna_prop_identifier, rna_desc, ', '.join(rna_prop.items.keys())))
98                                         out.write(ident+ '\t@type %s: %s%s%s\n' %  (rna_prop_identifier, rna_prop_type,  array_str, readonly_str))
99                                 elif rna_prop_type == 'int' or rna_prop_type == 'float':
100                                         out.write(ident+ '\t@ivar %s: %s\n' %  (rna_prop_identifier, rna_desc))
101                                         out.write(ident+ '\t@type %s: %s%s%s in [%s, %s]\n' %  (rna_prop_identifier, rna_prop_type, array_str, readonly_str, range_str(rna_prop.hard_min), range_str(rna_prop.hard_max) ))
102                                 elif rna_prop_type == 'string':
103                                         out.write(ident+ '\t@ivar %s: %s (maximum length of %s)\n' %  (rna_prop_identifier, rna_desc, rna_prop.max_length))
104                                         out.write(ident+ '\t@type %s: %s%s%s\n' %  (rna_prop_identifier, rna_prop_type, array_str, readonly_str))
105                                 else:
106                                         out.write(ident+ '\t@ivar %s: %s\n' %  (rna_prop_identifier, rna_desc))
107                                         out.write(ident+ '\t@type %s: %s%s%s\n' %  (rna_prop_identifier, rna_prop_type, array_str, readonly_str))
108                                 
109                         
110                 out.write(ident+ '\t"""\n\n')
111                 
112                 # Now write children recursively
113                 for child in structs:
114                         if rna_struct == child.nested:
115                                 write_struct(child, structs, ident + '\t')
116                 
117         
118         out = open(target_path, 'w')
119
120         def base_id(rna_struct):
121                 try:            return rna_struct.base.identifier
122                 except: return '' # invalid id
123
124         #structs = [(base_id(rna_struct), rna_struct.identifier, rna_struct) for rna_struct in bpydoc.structs.values()]
125         
126         structs = []
127         for rna_struct in bpydoc.structs.values():
128                 structs.append( (base_id(rna_struct), rna_struct.identifier, rna_struct) )
129                 
130         
131         
132         structs.sort() # not needed but speeds up sort below, setting items without an inheritance first
133         
134         # Arrange so classes are always defined in the correct order
135         deps_ok = False
136         while deps_ok == False:
137                 deps_ok = True
138                 rna_done = set()
139                 
140                 for i, (rna_base, identifier, rna_struct) in enumerate(structs):
141                         
142                         rna_done.add(identifier)
143                         
144                         if rna_base and rna_base not in rna_done:
145                                 deps_ok = False
146                                 data = structs.pop(i)
147                                 ok = False
148                                 while i < len(structs):
149                                         if structs[i][1]==rna_base:
150                                                 structs.insert(i+1, data) # insert after the item we depend on.
151                                                 ok = True
152                                                 break
153                                         i+=1
154                                         
155                                 if not ok:
156                                         print('Dependancy "%s"could not be found for "%s"' % (identifier, rna_base))
157                                 
158                                 break
159         
160         structs = [data[2] for data in structs]
161         # Done ordering structs
162         
163         
164         for rna_struct in structs:
165                 # print(type(rna_struct))
166                 if rna_struct.nested:
167                         continue
168                 
169                 write_struct(rna_struct, structs, '')
170                 
171                 
172         out.write('\n')
173         out.close()
174         
175         # # We could also just run....
176         # os.system('epydoc source/blender/python/doc/rna.py -o ./source/blender/python/doc/html -v')
177
178 def op2epy(target_path):
179         out = open(target_path, 'w')
180         
181         operators = dir(bpyoperator)
182         operators.remove('add')
183         operators.remove('remove')
184         operators.sort()
185         
186         
187         for op in operators:
188                 
189                 if op.startswith('__'):
190                         continue
191                 
192                 # Keyword attributes
193                 kw_args = [] # "foo = 1", "bar=0.5", "spam='ENUM'"
194                 kw_arg_attrs = [] # "@type mode: int"
195                 
196                 rna = getattr(bpyoperator, op).rna
197                 rna_struct = rna.rna_type
198                 # print (dir(rna))
199                 # print (dir(rna_struct))
200                 for rna_prop_identifier, rna_prop in rna_struct.properties.items():
201                         if rna_prop_identifier=='rna_type':
202                                 continue
203                         # ['rna_type', 'name', 'array_length', 'description', 'hard_max', 'hard_min', 'identifier', 'precision', 'readonly', 'soft_max', 'soft_min', 'step', 'subtype', 'type']
204                         #rna_prop=  op_rna.rna_type.properties[attr]
205                         rna_prop_type = rna_prop.type.lower() # enum, float, int, boolean
206                         
207                         try:            length = rna_prop.array_length
208                         except: length = 0
209                         
210                         array_str = get_array_str(length)
211                         
212                         try:
213                                 val = getattr(rna, rna_prop_identifier)
214                         except:
215                                 val = '<UNDEFINED>'
216                         
217                         kw_type_str= "@type %s: %s%s" % (rna_prop_identifier, rna_prop_type, array_str)
218                         kw_param_str= "@param %s: %s" % (rna_prop_identifier, rna_prop.description)
219                         kw_param_set = False
220                         
221                         if rna_prop_type=='float':
222                                 if length==0:
223                                         val_str= '%g' % val
224                                         if '.' not in val_str:
225                                                 val_str += '.0'
226                                 else:
227                                         # array
228                                         val_str = str(tuple(val))
229                                 
230                                 kw_param_str += (' in (%s, %s)' % (range_str(rna_prop.hard_min), range_str(rna_prop.hard_max)))
231                                 kw_param_set= True
232                                 
233                         elif rna_prop_type=='int':
234                                 if length==0:
235                                         val_str='%d' % val
236                                 else:
237                                         val_str = str(tuple(val))
238                                 
239                                 # print(dir(rna_prop))
240                                 kw_param_str += (' in (%s, %s)' % (range_str(rna_prop.hard_min), range_str(rna_prop.hard_max)))
241                                 # These strings dont have a max length???
242                                 #kw_param_str += ' (maximum length of %s)' %  (rna_prop.max_length)
243                                 kw_param_set= True
244                                 
245                         elif rna_prop_type=='boolean':
246                                 if length==0:
247                                         if val: val_str='True'
248                                         else:   val_str='False'
249                                 else:
250                                         val_str = str(tuple(val))
251                         
252                         elif rna_prop_type=='enum':
253                                 # no array here?
254                                 val_str="'%s'" % val
255                                 kw_param_str += (' in (%s)' % ', '.join(rna_prop.items.keys()))
256                                 kw_param_set= True
257                                 
258                         elif rna_prop_type=='string':
259                                 # no array here?
260                                 val_str='"%s"' % val
261                         
262                         # todo - collection - array
263                         # print (rna_prop.type)
264                         
265                         kw_args.append('%s = %s' % (rna_prop_identifier, val_str))
266                         
267                         # stora 
268                         
269                         kw_arg_attrs.append(kw_type_str)
270                         if kw_param_set:
271                                 kw_arg_attrs.append(kw_param_str)
272                         
273                 
274                 
275                 out.write('def %s(%s):\n' % (op, ', '.join(kw_args)))
276                 out.write('\t"""\n')
277                 out.write('\t%s\n' % rna_struct.description)
278                 for desc in kw_arg_attrs:
279                         out.write('\t%s\n' % desc)
280                 out.write('\t@rtype: None\n')
281                 out.write('\t"""\n')
282         
283         
284         out.write('\n')
285         out.close()
286
287 if __name__ == '__main__':
288         rna2epy('source/blender/python/doc/rna.py')
289         op2epy('source/blender/python/doc/bpyoperator.py')
290