Merge with -r 22620:23107.
[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 script_help_msg = '''
22 Usage,
23 run this script from blenders root path once you have compiled blender
24         ./blender.bin -P source/blender/python/epy_doc_gen.py
25
26 This will generate rna.py and bpyoperator.py in "./source/blender/python/doc/"
27 Generate html docs  by running...
28
29         epydoc source/blender/python/doc/*.py -v \\
30                         -o source/blender/python/doc/html \\
31                         --inheritance=included \\
32                         --no-sourcecode \\
33                         --graph=classtree \\
34                         --graph-font-size=8
35
36 '''
37
38 # if you dont have graphvis installed ommit the --graph arg.
39
40 # GLOBALS['BASEDIR'] = './source/blender/python/doc'
41
42 import os
43
44 SUBMODULES = {}
45 INIT_SUBMODULES = {}                    # store initialized files
46
47 INIT_SUBMODULES_IMPORTS = {}    # dont import the same module twice
48
49 def append_package(package_path, mod_name):
50         
51         init_path =     os.path.join(os.path.dirname(package_path), "__init__.py")
52         
53         # avoid double ups
54         if mod_name:
55                 imports = INIT_SUBMODULES_IMPORTS.setdefault(init_path, [])
56                 if mod_name in imports:
57                         return
58                 imports.append(mod_name)
59                 
60         try:
61                 os.makedirs(os.path.dirname(init_path)) # make the dirs if they are not there
62         except:
63                 pass
64         
65         # Open the new file for the first time, otherwise keep it open.
66         f = INIT_SUBMODULES.get(init_path)
67         if f == None:
68                 f = INIT_SUBMODULES[init_path] = open(init_path, 'w')
69         
70         if mod_name:
71                 f.write("import %s\n" % mod_name)
72                 
73         return f
74
75 def append_package_recursive(package_path, BASEPATH):
76         '''
77         assume the last item of package_path will be a file (not a dir thats created)
78         '''
79         
80         package_path = os.path.splitext(package_path)[0] # incase of .py
81         
82         try:
83                 os.makedirs(os.path.join(BASEPATH, os.path.dirname(package_path))) # make the dirs if they are not there
84         except:
85                 pass
86         
87         new_path = BASEPATH
88         
89         for mod_name in package_path.split(os.sep):
90                 init_path =     os.path.join(new_path, "__init__.py")
91                 new_path = os.path.join(new_path, mod_name)
92                 append_package(init_path, mod_name)
93
94
95 def open_submodule(subpath, BASEPATH):
96         '''
97         This is a utility function that lets us quickly add submodules
98         '''
99         
100         # create all the package paths leading up to this module
101         append_package_recursive(subpath, BASEPATH)
102         
103         module_name =           os.path.basename( os.path.splitext(subpath)[0] )
104         mod_path =      os.path.join(BASEPATH, subpath)
105         
106         # Open the new file for the first time, otherwise keep it open.
107         f = SUBMODULES.get(mod_path)
108         if f == None:
109                 f = SUBMODULES[mod_path] = open(mod_path, 'w')
110
111         f = open(mod_path, 'w')
112         return f
113
114 def close_all():
115         for files in (INIT_SUBMODULES.values(), SUBMODULES.values()):
116                 for f in files:
117                         if f.name.endswith('.py'):
118                                 f_name = f.name 
119                                 f.close()
120                                 
121                                 f = open(f_name, 'a')
122                                 f.write("\ndel __package__\n") # annoying, no need do show this
123                         
124                         
125                         f.close()
126
127
128 def range_str(val):
129         if val < -10000000:     return '-inf'
130         if val >  10000000:     return 'inf'
131         if type(val)==float:
132                 return '%g'  % val
133         else:
134                 return str(val) 
135
136 def get_array_str(length):
137         if length > 0:  return ' array of %d items' % length
138         else:           return ''
139
140 def full_rna_struct_path(rna_struct):
141         '''
142         Needed when referencing one struct from another
143         '''
144         nested = rna_struct.nested
145         if nested:
146                 return "%s.%s" % (full_rna_struct_path(nested), rna_struct.identifier)
147         else:
148                 return rna_struct.identifier
149
150 def rna_id_ignore(rna_id):
151         if rna_id == "rna_type":
152                 return True
153         
154         if "_OT_" in rna_id:
155                 return True
156         if "_MT_" in rna_id:
157                 return True
158         if "_PT_" in rna_id:
159                 return True
160         
161         return False
162
163 def write_func(rna, ident, out, func_type):
164         # Keyword attributes
165         kw_args = [] # "foo = 1", "bar=0.5", "spam='ENUM'"
166         kw_arg_attrs = [] # "@type mode: int"
167         
168         rna_struct= rna.rna_type
169         
170         # Operators and functions work differently
171         if func_type=='OPERATOR':
172                 rna_func_name = rna_struct.identifier.split("_OT_")[-1]
173                 rna_func_desc = rna_struct.description.strip()
174                 items = rna_struct.properties.items()
175         else:
176                 rna_func_name = rna.identifier
177                 rna_func_desc = rna.description.strip()
178                 items = rna.parameters.items()
179         
180         
181         for rna_prop_identifier, rna_prop in items:
182                 if rna_id_ignore(rna_prop_identifier):
183                         continue
184                 
185                 # clear vars                    
186                 val = val_error = val_str = rna_prop_type = None
187                 
188                 # ['rna_type', 'name', 'array_length', 'description', 'hard_max', 'hard_min', 'identifier', 'precision', 'readonly', 'soft_max', 'soft_min', 'step', 'subtype', 'type']
189                 #rna_prop=  op_rna.rna_type.properties[attr]
190                 rna_prop_type = rna_prop.type.lower() # enum, float, int, boolean
191                 
192                 
193                 # only for rna functions, operators should not get pointers as args
194                 if rna_prop_type=='pointer':
195                         rna_prop_type_refine = "L{%s}" % rna_prop.fixed_type.identifier
196                 else:
197                         rna_prop_type_refine = rna_prop_type
198                 
199                 
200                 try:            length = rna_prop.array_length
201                 except: length = 0
202                 
203                 array_str = get_array_str(length)
204                 
205                 if rna_prop.use_return:
206                         kw_type_str= "@rtype: %s%s" % (rna_prop_type_refine, array_str)
207                         kw_param_str= "@return: %s" % (rna_prop.description.strip())
208                 else:
209                         kw_type_str= "@type %s: %s%s" % (rna_prop_identifier, rna_prop_type_refine, array_str)
210                         kw_param_str= "@param %s: %s" % (rna_prop_identifier, rna_prop.description.strip())
211                 
212                 kw_param_set = False
213                 
214                 if func_type=='OPERATOR':
215                         try:
216                                 val = getattr(rna, rna_prop_identifier)
217                                 val_error = False
218                         except:
219                                 val = "'<UNDEFINED>'"
220                                 val_error = True
221                         
222                                 
223                         if val_error:
224                                 val_str = val
225                         elif rna_prop_type=='float':
226                                 if length==0:
227                                         val_str= '%g' % val
228                                         if '.' not in val_str:
229                                                 val_str += '.0'
230                                 else:
231                                         # array
232                                         val_str = str(tuple(val))
233                                 
234                                 kw_param_str += (' in (%s, %s)' % (range_str(rna_prop.hard_min), range_str(rna_prop.hard_max)))
235                                 kw_param_set= True
236                                 
237                         elif rna_prop_type=='int':
238                                 if length==0:
239                                         val_str='%d' % val
240                                 else:
241                                         val_str = str(tuple(val))
242                                 
243                                 # print(dir(rna_prop))
244                                 kw_param_str += (' in (%s, %s)' % (range_str(rna_prop.hard_min), range_str(rna_prop.hard_max)))
245                                 # These strings dont have a max length???
246                                 #kw_param_str += ' (maximum length of %s)' %  (rna_prop.max_length)
247                                 kw_param_set= True
248                                 
249                         elif rna_prop_type=='boolean':
250                                 if length==0:
251                                         if val: val_str='True'
252                                         else:   val_str='False'
253                                 else:
254                                         val_str = str(tuple(val))
255                         
256                         elif rna_prop_type=='enum':
257                                 # no array here?
258                                 val_str="'%s'" % val
259                                 # Too cramped
260                                 kw_param_str += (' in (%s)' % ', '.join(rna_prop.items.keys()))
261                                 
262                                 kw_param_set= True
263                                 
264                         elif rna_prop_type=='string':
265                                 # no array here?
266                                 val_str='"%s"' % val
267                         
268                         # todo - collection - array
269                         # print (rna_prop.type)
270                         
271                         kw_args.append('%s = %s' % (rna_prop_identifier, val_str))
272                         
273                         # stora 
274                 else:
275                         # currently functions dont have a default value
276                         if not rna_prop.use_return:
277                                 kw_args.append('%s' % (rna_prop_identifier))
278                         else:
279                                 kw_param_set = True
280
281                 
282                 # Same for operators and functions
283                 kw_arg_attrs.append(kw_type_str)
284                 if kw_param_set:
285                         kw_arg_attrs.append(kw_param_str)
286                 
287         
288         
289         out.write(ident+'def %s(%s):\n' % (rna_func_name, ', '.join(kw_args)))
290         out.write(ident+'\t"""\n')
291         out.write(ident+'\t%s\n' % rna_func_desc)
292         for desc in kw_arg_attrs:
293                 out.write(ident+'\t%s\n' % desc)
294                 
295         # out.write(ident+'\t@rtype: None\n') # implicit
296         out.write(ident+'\t"""\n')
297         
298
299
300 def rna2epy(BASEPATH):
301         
302         # Use for faster lookups
303         # use rna_struct.identifier as the key for each dict
304         rna_struct_dict =               {}  # store identifier:rna lookups
305         rna_full_path_dict =    {}      # store the result of full_rna_struct_path(rna_struct)
306         rna_children_dict =             {}      # store all rna_structs nested from here
307         rna_references_dict =   {}      # store a list of rna path strings that reference this type
308         rna_functions_dict =    {}      # store all functions directly in this type (not inherited)
309         rna_words = set()
310         
311         # def write_func(rna_func, ident):
312         
313         
314         def write_struct(rna_struct, ident):
315                 identifier = rna_struct.identifier
316                 
317                 rna_base = rna_struct.base
318                 
319                 if rna_base:
320                         out.write(ident+ 'class %s(%s):\n' % (identifier, rna_base.identifier))
321                         rna_base_prop_keys = rna_base.properties.keys() # could be cached
322                         rna_base_func_keys = [f.identifier for f in rna_base.functions]
323                 else:
324                         out.write(ident+ 'class %s:\n' % identifier)
325                         rna_base_prop_keys = []
326                         rna_base_func_keys = []
327                 
328                 out.write(ident+ '\t"""\n')
329                 
330                 title = 'The %s Object' % rna_struct.name
331                 description = rna_struct.description.strip()
332                 out.write(ident+ '\t%s\n' %  title)
333                 out.write(ident+ '\t%s\n' %  ('=' * len(title)))
334                 out.write(ident+ '\t\t%s\n' %  description)
335                 rna_words.update(description.split())
336                 
337                 
338                 # For convenience, give a list of all places were used.
339                 rna_refs= rna_references_dict[identifier]
340                 
341                 if rna_refs:
342                         out.write(ident+ '\t\t\n')
343                         out.write(ident+ '\t\tReferences\n')
344                         out.write(ident+ '\t\t==========\n')
345                         
346                         for rna_ref_string in rna_refs:
347                                 out.write(ident+ '\t\t\t- L{%s}\n' % rna_ref_string)
348                         
349                         out.write(ident+ '\t\t\n')
350                 
351                 else:
352                         out.write(ident+ '\t\t\n')
353                         out.write(ident+ '\t\t(no references to this struct found)\n')
354                         out.write(ident+ '\t\t\n')
355                 
356                 for rna_prop_identifier, rna_prop in rna_struct.properties.items():
357                         
358                         if rna_prop_identifier=='RNA':                                  continue
359                         if rna_id_ignore(rna_prop_identifier):                  continue
360                         if rna_prop_identifier in rna_base_prop_keys:   continue # does this prop exist in our parent class, if so skip
361                         
362                         rna_desc = rna_prop.description.strip()
363                         
364                         if rna_desc: rna_words.update(rna_desc.split())
365                         if not rna_desc: rna_desc = rna_prop.name
366                         if not rna_desc: rna_desc = 'Note - No documentation for this property!'
367                         
368                         rna_prop_type = rna_prop.type.lower()
369                         
370                         if rna_prop_type=='collection': collection_str = 'Collection of '
371                         else:                                                   collection_str = ''
372                         
373                         try:            rna_prop_ptr = rna_prop.fixed_type
374                         except: rna_prop_ptr = None
375                         
376                         try:            length = rna_prop.array_length
377                         except: length = 0
378                         
379                         array_str = get_array_str(length)
380                         
381                         if rna_prop.editable:   readonly_str = ''
382                         else:                           readonly_str = ' (readonly)'
383                         
384                         if rna_prop_ptr: # Use the pointer type
385                                 out.write(ident+ '\t@ivar %s: %s\n' %  (rna_prop_identifier, rna_desc))
386                                 out.write(ident+ '\t@type %s: %sL{%s}%s%s\n' %  (rna_prop_identifier, collection_str, rna_prop_ptr.identifier, array_str, readonly_str))
387                         else:
388                                 if rna_prop_type == 'enum':
389                                         if 0:
390                                                 out.write(ident+ '\t@ivar %s: %s in (%s)\n' %  (rna_prop_identifier, rna_desc, ', '.join(rna_prop.items.keys())))
391                                         else:
392                                                 out.write(ident+ '\t@ivar %s: %s in...\n' %  (rna_prop_identifier, rna_desc))
393                                                 for e, e_rna_prop in rna_prop.items.items():
394                                                         #out.write(ident+ '\t\t- %s: %s\n' % (e, e_rna_prop.description)) # XXX - segfaults, FIXME
395                                                         out.write(ident+ '\t\t- %s\n' % e)
396                                                 
397                                         out.write(ident+ '\t@type %s: %s%s%s\n' %  (rna_prop_identifier, rna_prop_type,  array_str, readonly_str))
398                                 elif rna_prop_type == 'int' or rna_prop_type == 'float':
399                                         out.write(ident+ '\t@ivar %s: %s\n' %  (rna_prop_identifier, rna_desc))
400                                         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) ))
401                                 elif rna_prop_type == 'string':
402                                         out.write(ident+ '\t@ivar %s: %s (maximum length of %s)\n' %  (rna_prop_identifier, rna_desc, rna_prop.max_length))
403                                         out.write(ident+ '\t@type %s: %s%s%s\n' %  (rna_prop_identifier, rna_prop_type, array_str, readonly_str))
404                                 else:
405                                         out.write(ident+ '\t@ivar %s: %s\n' %  (rna_prop_identifier, rna_desc))
406                                         out.write(ident+ '\t@type %s: %s%s%s\n' %  (rna_prop_identifier, rna_prop_type, array_str, readonly_str))
407                                 
408                         
409                 out.write(ident+ '\t"""\n\n')
410                 
411                 
412                 # Write functions 
413                 # for rna_func in rna_struct.functions: # Better ignore inherited (line below)
414                 for rna_func in rna_functions_dict[identifier]:
415                         if rna_func not in rna_base_func_keys:
416                                 write_func(rna_func, ident+'\t', out, 'FUNCTION')
417                 
418                 out.write('\n')
419                 
420                 # Now write children recursively
421                 for child in rna_children_dict[identifier]:
422                         write_struct(child, ident + '\t')
423         
424         
425         
426         # out = open(target_path, 'w')
427         out = open_submodule("types.py", BASEPATH) # bpy.types
428
429         def base_id(rna_struct):
430                 try:            return rna_struct.base.identifier
431                 except: return '' # invalid id
432
433         #structs = [(base_id(rna_struct), rna_struct.identifier, rna_struct) for rna_struct in bpy.doc.structs.values()]
434         '''
435         structs = []
436         for rna_struct in bpy.doc.structs.values():
437                 structs.append( (base_id(rna_struct), rna_struct.identifier, rna_struct) )
438         '''
439         structs = []
440         for rna_type_name in dir(bpy.types):
441                 rna_type = getattr(bpy.types, rna_type_name)
442                 
443                 try:            rna_struct = rna_type.__rna__
444                 except: rna_struct = None
445                 
446                 if rna_struct:
447                         #if not rna_type_name.startswith('__'):
448                         
449                         identifier = rna_struct.identifier
450                         
451                         if not rna_id_ignore(identifier):
452                                 structs.append( (base_id(rna_struct), identifier, rna_struct) ) 
453                                 
454                                 # Simple lookup
455                                 rna_struct_dict[identifier] = rna_struct
456                                 
457                                 # Store full rna path 'GameObjectSettings' -> 'Object.GameObjectSettings'
458                                 rna_full_path_dict[identifier] = full_rna_struct_path(rna_struct)
459                                 
460                                 # Store a list of functions, remove inherited later
461                                 rna_functions_dict[identifier]= list(rna_struct.functions)
462                                 
463                                 
464                                 # fill in these later
465                                 rna_children_dict[identifier]= []
466                                 rna_references_dict[identifier]= []
467                         
468                         
469                 else:
470                         print("Ignoring", rna_type_name)
471         
472         
473         # Sucks but we need to copy this so we can check original parent functions
474         rna_functions_dict__copy = {}
475         for key, val in rna_functions_dict.items():
476                 rna_functions_dict__copy[key] = val[:]
477         
478         
479         structs.sort() # not needed but speeds up sort below, setting items without an inheritance first
480         
481         # Arrange so classes are always defined in the correct order
482         deps_ok = False
483         while deps_ok == False:
484                 deps_ok = True
485                 rna_done = set()
486                 
487                 for i, (rna_base, identifier, rna_struct) in enumerate(structs):
488                         
489                         rna_done.add(identifier)
490                         
491                         if rna_base and rna_base not in rna_done:
492                                 deps_ok = False
493                                 data = structs.pop(i)
494                                 ok = False
495                                 while i < len(structs):
496                                         if structs[i][1]==rna_base:
497                                                 structs.insert(i+1, data) # insert after the item we depend on.
498                                                 ok = True
499                                                 break
500                                         i+=1
501                                         
502                                 if not ok:
503                                         print('Dependancy "%s" could not be found for "%s"' % (identifier, rna_base))
504                                 
505                                 break
506         
507         # Done ordering structs
508         
509         
510         # precalc vars to avoid a lot of looping
511         for (rna_base, identifier, rna_struct) in structs:
512                 
513                 if rna_base:
514                         rna_base_prop_keys = rna_struct_dict[rna_base].properties.keys() # could cache
515                         rna_base_func_keys = [f.identifier for f in rna_struct_dict[rna_base].functions]
516                 else:
517                         rna_base_prop_keys = []
518                         rna_base_func_keys= []
519                 
520                 # rna_struct_path = full_rna_struct_path(rna_struct)
521                 rna_struct_path = rna_full_path_dict[identifier]
522                 
523                 for rna_prop_identifier, rna_prop in rna_struct.properties.items():
524                         
525                         if rna_prop_identifier=='RNA':                                  continue
526                         if rna_id_ignore(rna_prop_identifier):                  continue
527                         if rna_prop_identifier in rna_base_prop_keys:   continue
528                         
529                         try:            rna_prop_ptr = rna_prop.fixed_type
530                         except: rna_prop_ptr = None
531                         
532                         # Does this property point to me?
533                         if rna_prop_ptr:
534                                 rna_references_dict[rna_prop_ptr.identifier].append( "%s.%s" % (rna_struct_path, rna_prop_identifier) )
535                 
536                 for rna_func in rna_struct.functions:
537                         for rna_prop_identifier, rna_prop in rna_func.parameters.items():
538                                 
539                                 if rna_prop_identifier=='RNA':                                  continue
540                                 if rna_id_ignore(rna_prop_identifier):                  continue
541                                 if rna_prop_identifier in rna_base_func_keys:   continue
542                                         
543                                 
544                                 try:            rna_prop_ptr = rna_prop.fixed_type
545                                 except: rna_prop_ptr = None
546                                 
547                                 # Does this property point to me?
548                                 if rna_prop_ptr:
549                                         rna_references_dict[rna_prop_ptr.identifier].append( "%s.%s" % (rna_struct_path, rna_func.identifier) )
550                         
551                 
552                 # Store nested children
553                 nested = rna_struct.nested
554                 if nested:
555                         rna_children_dict[nested.identifier].append(rna_struct)
556                 
557                 
558                 if rna_base:
559                         rna_funcs =                     rna_functions_dict[identifier]
560                         if rna_funcs:
561                                 # Remove inherited functions if we have any
562                                 rna_base_funcs =        rna_functions_dict__copy[rna_base]
563                                 rna_funcs[:] =          [f for f in rna_funcs if f not in rna_base_funcs]
564         
565         rna_functions_dict__copy.clear()
566         del rna_functions_dict__copy
567         
568         # Sort the refs, just reads nicer
569         for rna_refs in rna_references_dict.values():
570                 rna_refs.sort()
571         
572         for (rna_base, identifier, rna_struct) in structs:
573                 if rna_struct.nested:
574                         continue
575                 
576                 write_struct(rna_struct, '')
577                 
578                 
579         out.write('\n')
580         out.close()
581         
582         # # We could also just run....
583         # os.system('epydoc source/blender/python/doc/rna.py -o ./source/blender/python/doc/html -v')
584         
585         target_path = os.path.join(BASEPATH, "dump.py") # XXX - used for other funcs
586         
587         # Write graphviz
588         out= open(target_path.replace('.py', '.dot'), 'w')
589         out.write('digraph "rna data api" {\n')
590         out.write('\tnode [style=filled, shape = "box"];\n')
591         out.write('\toverlap=false;\n')
592         out.write('\trankdir = LR;\n')
593         out.write('\tsplines=true;\n')
594         out.write('\tratio=auto;\n')
595         
596         
597         
598         out.write('\tsize="10,10"\n')
599         #out.write('\tpage="8.5,11"\n')
600         #out.write('\tcenter=""\n')
601         
602         def isop(rna_struct):
603                 return '_OT_' in rna_struct.identifier
604         
605         
606         for (rna_base, identifier, rna_struct) in structs:
607                 if isop(rna_struct):
608                         continue
609                 
610                 base = rna_struct.base
611                 
612                 
613                 out.write('\t"%s";\n' % identifier)
614         
615         for (rna_base, identifier, rna_struct) in structs:
616                 
617                 if isop(rna_struct):
618                         continue
619                         
620                 base = rna_struct.base
621                 
622                 if base and not isop(base):
623                         out.write('\t"%s" -> "%s" [label="(base)" weight=1.0];\n' % (base.identifier, identifier))
624                 
625                 nested = rna_struct.nested
626                 if nested and not isop(nested):
627                         out.write('\t"%s" -> "%s" [label="(nested)"  weight=1.0];\n' % (nested.identifier, identifier))
628                 
629                 
630                 
631                 rna_refs= rna_references_dict[identifier]
632                 
633                 for rna_ref_string in rna_refs:
634                         
635                         if '_OT_' in rna_ref_string:
636                                 continue
637                         
638                         ref = rna_ref_string.split('.')[-2]
639                         out.write('\t"%s" -> "%s" [label="%s" weight=0.01];\n' % (ref, identifier, rna_ref_string))
640         
641         
642         out.write('}\n')
643         out.close()
644         
645         # # We could also just run....
646         # os.system('dot source/blender/python/doc/rna.dot -Tsvg -o ./source/blender/python/doc/rna.svg')
647         
648         
649         out= open(target_path.replace('.py', '.words'), 'w')
650         rna_words = list(rna_words)
651         rna_words.sort()
652         for w in rna_words:
653                 out.write('%s\n' % w)
654         
655
656 def op2epy(BASEPATH):
657         # out = open(target_path, 'w')
658         
659         op_mods = dir(bpy.ops)
660         op_mods.remove('add')
661         op_mods.remove('remove')
662         
663         for op_mod_name in sorted(op_mods):
664                 if op_mod_name.startswith('__'):
665                         continue
666                 
667                 # open the submodule
668                 mod_path = os.path.join("ops", op_mod_name + ".py")
669                 out = open_submodule(mod_path, BASEPATH)
670
671
672                 op_mod = getattr(bpy.ops, op_mod_name)
673                 operators = dir(op_mod)
674                 for op in sorted(operators):
675                         # rna = getattr(bpy.types, op).__rna__
676                         rna = getattr(op_mod, op).get_rna()
677                         write_func(rna, '', out, 'OPERATOR')
678                 
679                 out.write('\n')
680                 out.close()
681
682 def misc2epy(BASEPATH):
683         '''
684         Hard coded modules, try to avoid adding stuff here
685         '''
686         
687         f = append_package(os.path.join(BASEPATH, ""), ""); # add a slash on the end of the base path
688         f.write('''
689 """
690 @type data: L{bpy.types.Main}
691 @var  data: blender data is accessed from here
692 """
693 ''')
694
695         f = open_submodule("props.py", BASEPATH)
696         f.write('''
697 MAX_INT= 2**31
698 MAX_FLOAT= 1e+37
699 def BoolProperty(attr, name="", description="", default=False):
700         """
701         return a new bool property
702         """
703 def IntProperty(attr, name="", description="", min=-MAX_INT, max=MAX_INT, soft_min=-MAX_INT, soft_max=MAX_INT, default=0):
704         """
705         return a new int property
706         """
707 def FloatProperty(attr, name="", description="", min=-MAX_FLOAT, max=MAX_FLOAT, soft_min=-MAX_FLOAT, soft_max=MAX_FLOAT, default=0.0):
708         """
709         return a new float property
710         """
711 def StringProperty(attr, name="", description="", maxlen=0, default=""):
712         """
713         return a new string property
714         """
715 def EnumProperty(attr, items, name="", description="", default=""):
716         """
717         return a new enum property
718         """     
719 ''')
720
721
722 if __name__ == '__main__':
723         if 'bpy' not in dir():
724                 print("\nError, this script must run from inside blender2.5")
725                 print(script_help_msg)
726         else:
727                 misc2epy('source/blender/python/doc/bpy') # first to write in info in some of the modules.
728                 rna2epy('source/blender/python/doc/bpy')
729                 op2epy('source/blender/python/doc/bpy')
730         
731         
732         close_all()
733         
734         import sys
735         sys.exit()