2.5 Python api
[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 bpy.doc.structs.values()]
125         '''
126         structs = []
127         for rna_struct in bpy.doc.structs.values():
128                 structs.append( (base_id(rna_struct), rna_struct.identifier, rna_struct) )
129         '''
130         structs = []
131         for rna_type_name in dir(bpy.types):
132                 rna_type = getattr(bpy.types, rna_type_name)
133                 if hasattr(rna_type, '__rna__'):
134                         rna_struct = rna_type.__rna__
135                         structs.append( (base_id(rna_struct), rna_struct.identifier, rna_struct) )      
136         
137         
138         
139         structs.sort() # not needed but speeds up sort below, setting items without an inheritance first
140         
141         # Arrange so classes are always defined in the correct order
142         deps_ok = False
143         while deps_ok == False:
144                 deps_ok = True
145                 rna_done = set()
146                 
147                 for i, (rna_base, identifier, rna_struct) in enumerate(structs):
148                         
149                         rna_done.add(identifier)
150                         
151                         if rna_base and rna_base not in rna_done:
152                                 deps_ok = False
153                                 data = structs.pop(i)
154                                 ok = False
155                                 while i < len(structs):
156                                         if structs[i][1]==rna_base:
157                                                 structs.insert(i+1, data) # insert after the item we depend on.
158                                                 ok = True
159                                                 break
160                                         i+=1
161                                         
162                                 if not ok:
163                                         print('Dependancy "%s"could not be found for "%s"' % (identifier, rna_base))
164                                 
165                                 break
166         
167         structs = [data[2] for data in structs]
168         # Done ordering structs
169         
170         
171         for rna_struct in structs:
172                 # print(type(rna_struct))
173                 if rna_struct.nested:
174                         continue
175                 
176                 write_struct(rna_struct, structs, '')
177                 
178                 
179         out.write('\n')
180         out.close()
181         
182         # # We could also just run....
183         # os.system('epydoc source/blender/python/doc/rna.py -o ./source/blender/python/doc/html -v')
184
185 def op2epy(target_path):
186         out = open(target_path, 'w')
187         
188         operators = dir(bpy.ops)
189         operators.remove('add')
190         operators.remove('remove')
191         operators.sort()
192         
193         
194         for op in operators:
195                 
196                 if op.startswith('__'):
197                         continue
198                 
199                 # Keyword attributes
200                 kw_args = [] # "foo = 1", "bar=0.5", "spam='ENUM'"
201                 kw_arg_attrs = [] # "@type mode: int"
202                 
203                 rna = getattr(bpy.ops, op).rna
204                 rna_struct = rna.rna_type
205                 # print (dir(rna))
206                 # print (dir(rna_struct))
207                 for rna_prop_identifier, rna_prop in rna_struct.properties.items():
208                         if rna_prop_identifier=='rna_type':
209                                 continue
210                         # ['rna_type', 'name', 'array_length', 'description', 'hard_max', 'hard_min', 'identifier', 'precision', 'readonly', 'soft_max', 'soft_min', 'step', 'subtype', 'type']
211                         #rna_prop=  op_rna.rna_type.properties[attr]
212                         rna_prop_type = rna_prop.type.lower() # enum, float, int, boolean
213                         
214                         try:            length = rna_prop.array_length
215                         except: length = 0
216                         
217                         array_str = get_array_str(length)
218                         
219                         try:
220                                 val = getattr(rna, rna_prop_identifier)
221                         except:
222                                 val = '<UNDEFINED>'
223                         
224                         kw_type_str= "@type %s: %s%s" % (rna_prop_identifier, rna_prop_type, array_str)
225                         kw_param_str= "@param %s: %s" % (rna_prop_identifier, rna_prop.description)
226                         kw_param_set = False
227                         
228                         if rna_prop_type=='float':
229                                 if length==0:
230                                         val_str= '%g' % val
231                                         if '.' not in val_str:
232                                                 val_str += '.0'
233                                 else:
234                                         # array
235                                         val_str = str(tuple(val))
236                                 
237                                 kw_param_str += (' in (%s, %s)' % (range_str(rna_prop.hard_min), range_str(rna_prop.hard_max)))
238                                 kw_param_set= True
239                                 
240                         elif rna_prop_type=='int':
241                                 if length==0:
242                                         val_str='%d' % val
243                                 else:
244                                         val_str = str(tuple(val))
245                                 
246                                 # print(dir(rna_prop))
247                                 kw_param_str += (' in (%s, %s)' % (range_str(rna_prop.hard_min), range_str(rna_prop.hard_max)))
248                                 # These strings dont have a max length???
249                                 #kw_param_str += ' (maximum length of %s)' %  (rna_prop.max_length)
250                                 kw_param_set= True
251                                 
252                         elif rna_prop_type=='boolean':
253                                 if length==0:
254                                         if val: val_str='True'
255                                         else:   val_str='False'
256                                 else:
257                                         val_str = str(tuple(val))
258                         
259                         elif rna_prop_type=='enum':
260                                 # no array here?
261                                 val_str="'%s'" % val
262                                 kw_param_str += (' in (%s)' % ', '.join(rna_prop.items.keys()))
263                                 kw_param_set= True
264                                 
265                         elif rna_prop_type=='string':
266                                 # no array here?
267                                 val_str='"%s"' % val
268                         
269                         # todo - collection - array
270                         # print (rna_prop.type)
271                         
272                         kw_args.append('%s = %s' % (rna_prop_identifier, val_str))
273                         
274                         # stora 
275                         
276                         kw_arg_attrs.append(kw_type_str)
277                         if kw_param_set:
278                                 kw_arg_attrs.append(kw_param_str)
279                         
280                 
281                 
282                 out.write('def %s(%s):\n' % (op, ', '.join(kw_args)))
283                 out.write('\t"""\n')
284                 out.write('\t%s\n' % rna_struct.description)
285                 for desc in kw_arg_attrs:
286                         out.write('\t%s\n' % desc)
287                 out.write('\t@rtype: None\n')
288                 out.write('\t"""\n')
289         
290         
291         out.write('\n')
292         out.close()
293
294 if __name__ == '__main__':
295         rna2epy('source/blender/python/doc/rna.py')
296         op2epy('source/blender/python/doc/bpyoperator.py')
297