Support for the C Macro system in Python.
[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 python files in "./source/blender/python/doc/bpy"
27 Generate html docs  by running...
28
29     epydoc source/blender/python/doc/bpy/ -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             # Collections/Arrays can have a srna type
198             rna_prop_srna_type = rna_prop.srna
199             if rna_prop_srna_type:
200                 print(rna_prop_srna_type.identifier)
201                 rna_prop_type_refine = "L{%s}" % rna_prop_srna_type.identifier
202             else:
203                 rna_prop_type_refine = rna_prop_type
204             
205             del rna_prop_srna_type
206
207
208         try:            length = rna_prop.array_length
209         except: length = 0
210
211         array_str = get_array_str(length)
212
213         if rna_prop.use_return:
214             kw_type_str= "@rtype: %s%s" % (rna_prop_type_refine, array_str)
215             kw_param_str= "@return: %s" % (rna_prop.description.strip())
216         else:
217             kw_type_str= "@type %s: %s%s" % (rna_prop_identifier, rna_prop_type_refine, array_str)
218             kw_param_str= "@param %s: %s" % (rna_prop_identifier, rna_prop.description.strip())
219
220         kw_param_set = False
221
222         if func_type=='OPERATOR':
223             try:
224                 val = getattr(rna, rna_prop_identifier)
225                 val_error = False
226             except:
227                 val = "'<UNDEFINED>'"
228                 val_error = True
229
230
231             if val_error:
232                 val_str = val
233             elif rna_prop_type=='float':
234                 if length==0:
235                     val_str= '%g' % val
236                     if '.' not in val_str and '-' not in val_str: # value could be 1e-05
237                         val_str += '.0'
238                 else:
239                     # array
240                     val_str = str(tuple(val))
241
242                 kw_param_str += (' in (%s, %s)' % (range_str(rna_prop.hard_min), range_str(rna_prop.hard_max)))
243                 kw_param_set= True
244
245             elif rna_prop_type=='int':
246                 if length==0:
247                     val_str='%d' % val
248                 else:
249                     val_str = str(tuple(val))
250
251                 # print(dir(rna_prop))
252                 kw_param_str += (' in (%s, %s)' % (range_str(rna_prop.hard_min), range_str(rna_prop.hard_max)))
253                 # These strings dont have a max length???
254                 #kw_param_str += ' (maximum length of %s)' %  (rna_prop.max_length)
255                 kw_param_set= True
256
257             elif rna_prop_type=='boolean':
258                 if length==0:
259                     if val:     val_str='True'
260                     else:       val_str='False'
261                 else:
262                     val_str = str(tuple(val))
263
264             elif rna_prop_type=='enum':
265                 # no array here?
266                 val_str="'%s'" % val
267                 # Too cramped
268                 kw_param_str += (' in (%s)' % ', '.join(rna_prop.items.keys()))
269
270                 kw_param_set= True
271
272             elif rna_prop_type=='string':
273                 # no array here?
274                 val_str='"%s"' % val
275
276             # todo - collection - array
277             # print (rna_prop.type)
278
279             kw_args.append('%s = %s' % (rna_prop_identifier, val_str))
280
281             # stora
282         else:
283             # currently functions dont have a default value
284             if not rna_prop.use_return:
285                 kw_args.append('%s' % (rna_prop_identifier))
286             else:
287                 kw_param_set = True
288
289
290         # Same for operators and functions
291         kw_arg_attrs.append(kw_type_str)
292         if kw_param_set:
293             kw_arg_attrs.append(kw_param_str)
294
295
296
297     out.write(ident+'def %s(%s):\n' % (rna_func_name, ', '.join(kw_args)))
298     out.write(ident+'\t"""\n')
299     
300     # Descriptions could be multiline
301     for rna_func_desc_line in rna_func_desc.split('\n'):
302         out.write(ident+'\t%s\n' % rna_func_desc_line.strip())
303     
304     for desc in kw_arg_attrs:
305         out.write(ident+'\t%s\n' % desc)
306
307     # out.write(ident+'\t@rtype: None\n') # implicit
308     out.write(ident+'\t"""\n')
309
310
311
312 def rna2epy(BASEPATH):
313
314     # Use for faster lookups
315     # use rna_struct.identifier as the key for each dict
316     rna_struct_dict =           {}  # store identifier:rna lookups
317     rna_full_path_dict =        {}      # store the result of full_rna_struct_path(rna_struct)
318     rna_children_dict =         {}      # store all rna_structs nested from here
319     rna_references_dict =       {}      # store a list of rna path strings that reference this type
320     rna_functions_dict =        {}      # store all functions directly in this type (not inherited)
321     rna_words = set()
322
323     # def write_func(rna_func, ident):
324
325
326     def write_struct(rna_struct, ident):
327         identifier = rna_struct.identifier
328
329         rna_base = rna_struct.base
330
331         if rna_base:
332             out.write(ident+ 'class %s(%s):\n' % (identifier, rna_base.identifier))
333             rna_base_prop_keys = rna_base.properties.keys() # could be cached
334             rna_base_func_keys = [f.identifier for f in rna_base.functions]
335         else:
336             out.write(ident+ 'class %s:\n' % identifier)
337             rna_base_prop_keys = []
338             rna_base_func_keys = []
339
340         out.write(ident+ '\t"""\n')
341
342         title = 'The %s Object' % rna_struct.name
343         description = rna_struct.description.strip()
344         out.write(ident+ '\t%s\n' %  title)
345         out.write(ident+ '\t%s\n' %  ('=' * len(title)))
346         out.write(ident+ '\t\t%s\n' %  description)
347         rna_words.update(description.split())
348
349
350         # For convenience, give a list of all places were used.
351         rna_refs= rna_references_dict[identifier]
352
353         if rna_refs:
354             out.write(ident+ '\t\t\n')
355             out.write(ident+ '\t\tReferences\n')
356             out.write(ident+ '\t\t==========\n')
357
358             for rna_ref_string in rna_refs:
359                 out.write(ident+ '\t\t\t- L{%s}\n' % rna_ref_string)
360
361             out.write(ident+ '\t\t\n')
362
363         else:
364             out.write(ident+ '\t\t\n')
365             out.write(ident+ '\t\t(no references to this struct found)\n')
366             out.write(ident+ '\t\t\n')
367
368         for rna_prop_identifier, rna_prop in rna_struct.properties.items():
369
370             if rna_prop_identifier=='RNA':                                      continue
371             if rna_id_ignore(rna_prop_identifier):                      continue
372             if rna_prop_identifier in rna_base_prop_keys:       continue # does this prop exist in our parent class, if so skip
373
374             rna_desc = rna_prop.description.strip()
375
376             if rna_desc: rna_words.update(rna_desc.split())
377             if not rna_desc: rna_desc = rna_prop.name
378             if not rna_desc: rna_desc = 'Note - No documentation for this property!'
379
380             rna_prop_type = rna_prop.type.lower()
381
382             if rna_prop_type=='collection':     collection_str = 'Collection of '
383             else:                                                       collection_str = ''
384             
385             # some collections have a srna for their own properties
386             # TODO - arrays, however this isnt used yet
387             rna_prop_srna_type = rna_prop.srna
388             if rna_prop_srna_type:
389                 collection_str =  "L{%s} %s" % (rna_prop_srna_type.identifier, collection_str)
390             del rna_prop_srna_type
391
392             try:                rna_prop_ptr = rna_prop.fixed_type
393             except:     rna_prop_ptr = None
394
395             try:                length = rna_prop.array_length
396             except:     length = 0
397
398             array_str = get_array_str(length)
399
400             if rna_prop.editable:       readonly_str = ''
401             else:                               readonly_str = ' (readonly)'
402
403             if rna_prop_ptr: # Use the pointer type
404                 out.write(ident+ '\t@ivar %s: %s\n' %  (rna_prop_identifier, rna_desc))
405                 out.write(ident+ '\t@type %s: %sL{%s}%s%s\n' %  (rna_prop_identifier, collection_str, rna_prop_ptr.identifier, array_str, readonly_str))
406             else:
407                 if rna_prop_type == 'enum':
408                     if 0:
409                         out.write(ident+ '\t@ivar %s: %s in (%s)\n' %  (rna_prop_identifier, rna_desc, ', '.join(rna_prop.items.keys())))
410                     else:
411                         out.write(ident+ '\t@ivar %s: %s in...\n' %  (rna_prop_identifier, rna_desc))
412                         for e, e_rna_prop in rna_prop.items.items():
413                             #out.write(ident+ '\t\t- %s: %s\n' % (e, e_rna_prop.description)) # XXX - segfaults, FIXME
414                             out.write(ident+ '\t\t- %s\n' % e)
415
416                     out.write(ident+ '\t@type %s: %s%s%s\n' %  (rna_prop_identifier, rna_prop_type,  array_str, readonly_str))
417                 elif rna_prop_type == 'int' or rna_prop_type == 'float':
418                     out.write(ident+ '\t@ivar %s: %s\n' %  (rna_prop_identifier, rna_desc))
419                     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) ))
420                 elif rna_prop_type == 'string':
421                     out.write(ident+ '\t@ivar %s: %s (maximum length of %s)\n' %  (rna_prop_identifier, rna_desc, rna_prop.max_length))
422                     out.write(ident+ '\t@type %s: %s%s%s\n' %  (rna_prop_identifier, rna_prop_type, array_str, readonly_str))
423                 else:
424                     out.write(ident+ '\t@ivar %s: %s\n' %  (rna_prop_identifier, rna_desc))
425                     out.write(ident+ '\t@type %s: %s%s%s\n' %  (rna_prop_identifier, rna_prop_type, array_str, readonly_str))
426
427
428         out.write(ident+ '\t"""\n\n')
429
430
431         # Write functions
432         # for rna_func in rna_struct.functions: # Better ignore inherited (line below)
433         for rna_func in rna_functions_dict[identifier]:
434             if rna_func not in rna_base_func_keys:
435                 write_func(rna_func, ident+'\t', out, 'FUNCTION')
436
437         out.write('\n')
438
439         # Now write children recursively
440         for child in rna_children_dict[identifier]:
441             write_struct(child, ident + '\t')
442
443
444
445     # out = open(target_path, 'w')
446     out = open_submodule("types.py", BASEPATH) # bpy.types
447
448     def base_id(rna_struct):
449         try:            return rna_struct.base.identifier
450         except: return '' # invalid id
451
452     #structs = [(base_id(rna_struct), rna_struct.identifier, rna_struct) for rna_struct in bpy.doc.structs.values()]
453     '''
454     structs = []
455     for rna_struct in bpy.doc.structs.values():
456         structs.append( (base_id(rna_struct), rna_struct.identifier, rna_struct) )
457     '''
458     structs = []
459     for rna_type_name in dir(bpy.types):
460         rna_type = getattr(bpy.types, rna_type_name)
461
462         try:            rna_struct = rna_type.bl_rna
463         except: rna_struct = None
464
465         if rna_struct:
466             #if not rna_type_name.startswith('__'):
467
468             identifier = rna_struct.identifier
469
470             if not rna_id_ignore(identifier):
471                 structs.append( (base_id(rna_struct), identifier, rna_struct) )
472
473                 # Simple lookup
474                 rna_struct_dict[identifier] = rna_struct
475
476                 # Store full rna path 'GameObjectSettings' -> 'Object.GameObjectSettings'
477                 rna_full_path_dict[identifier] = full_rna_struct_path(rna_struct)
478
479                 # Store a list of functions, remove inherited later
480                 rna_functions_dict[identifier]= list(rna_struct.functions)
481
482
483                 # fill in these later
484                 rna_children_dict[identifier]= []
485                 rna_references_dict[identifier]= []
486
487
488         else:
489             print("Ignoring", rna_type_name)
490
491
492     # Sucks but we need to copy this so we can check original parent functions
493     rna_functions_dict__copy = {}
494     for key, val in rna_functions_dict.items():
495         rna_functions_dict__copy[key] = val[:]
496
497
498     structs.sort() # not needed but speeds up sort below, setting items without an inheritance first
499
500     # Arrange so classes are always defined in the correct order
501     deps_ok = False
502     while deps_ok == False:
503         deps_ok = True
504         rna_done = set()
505
506         for i, (rna_base, identifier, rna_struct) in enumerate(structs):
507
508             rna_done.add(identifier)
509
510             if rna_base and rna_base not in rna_done:
511                 deps_ok = False
512                 data = structs.pop(i)
513                 ok = False
514                 while i < len(structs):
515                     if structs[i][1]==rna_base:
516                         structs.insert(i+1, data) # insert after the item we depend on.
517                         ok = True
518                         break
519                     i+=1
520
521                 if not ok:
522                     print('Dependancy "%s" could not be found for "%s"' % (identifier, rna_base))
523
524                 break
525
526     # Done ordering structs
527
528
529     # precalc vars to avoid a lot of looping
530     for (rna_base, identifier, rna_struct) in structs:
531
532         if rna_base:
533             rna_base_prop_keys = rna_struct_dict[rna_base].properties.keys() # could cache
534             rna_base_func_keys = [f.identifier for f in rna_struct_dict[rna_base].functions]
535         else:
536             rna_base_prop_keys = []
537             rna_base_func_keys= []
538
539         # rna_struct_path = full_rna_struct_path(rna_struct)
540         rna_struct_path = rna_full_path_dict[identifier]
541
542         for rna_prop_identifier, rna_prop in rna_struct.properties.items():
543
544             if rna_prop_identifier=='RNA':                                      continue
545             if rna_id_ignore(rna_prop_identifier):                      continue
546             if rna_prop_identifier in rna_base_prop_keys:       continue
547
548             
549             for rna_prop_ptr in (getattr(rna_prop, "fixed_type", None), getattr(rna_prop, "srna", None)):
550                 # Does this property point to me?
551                 if rna_prop_ptr:
552                     rna_references_dict[rna_prop_ptr.identifier].append( "%s.%s" % (rna_struct_path, rna_prop_identifier) )
553
554         for rna_func in rna_struct.functions:
555             for rna_prop_identifier, rna_prop in rna_func.parameters.items():
556
557                 if rna_prop_identifier=='RNA':                                  continue
558                 if rna_id_ignore(rna_prop_identifier):                  continue
559                 if rna_prop_identifier in rna_base_func_keys:   continue
560
561
562                 try:            rna_prop_ptr = rna_prop.fixed_type
563                 except: rna_prop_ptr = None
564
565                 # Does this property point to me?
566                 if rna_prop_ptr:
567                     rna_references_dict[rna_prop_ptr.identifier].append( "%s.%s" % (rna_struct_path, rna_func.identifier) )
568
569
570         # Store nested children
571         nested = rna_struct.nested
572         if nested:
573             rna_children_dict[nested.identifier].append(rna_struct)
574
575
576         if rna_base:
577             rna_funcs =                 rna_functions_dict[identifier]
578             if rna_funcs:
579                 # Remove inherited functions if we have any
580                 rna_base_funcs =        rna_functions_dict__copy[rna_base]
581                 rna_funcs[:] =          [f for f in rna_funcs if f not in rna_base_funcs]
582
583     rna_functions_dict__copy.clear()
584     del rna_functions_dict__copy
585
586     # Sort the refs, just reads nicer
587     for rna_refs in rna_references_dict.values():
588         rna_refs.sort()
589
590     for (rna_base, identifier, rna_struct) in structs:
591         if rna_struct.nested:
592             continue
593
594         write_struct(rna_struct, '')
595
596
597     out.write('\n')
598     out.close()
599
600     # # We could also just run....
601     # os.system('epydoc source/blender/python/doc/rna.py -o ./source/blender/python/doc/html -v')
602
603     target_path = os.path.join(BASEPATH, "dump.py") # XXX - used for other funcs
604
605     # Write graphviz
606     out= open(target_path.replace('.py', '.dot'), 'w')
607     out.write('digraph "rna data api" {\n')
608     out.write('\tnode [style=filled, shape = "box"];\n')
609     out.write('\toverlap=false;\n')
610     out.write('\trankdir = LR;\n')
611     out.write('\tsplines=true;\n')
612     out.write('\tratio=auto;\n')
613
614
615
616     out.write('\tsize="10,10"\n')
617     #out.write('\tpage="8.5,11"\n')
618     #out.write('\tcenter=""\n')
619
620     def isop(rna_struct):
621         return '_OT_' in rna_struct.identifier
622
623
624     for (rna_base, identifier, rna_struct) in structs:
625         if isop(rna_struct):
626             continue
627
628         base = rna_struct.base
629
630
631         out.write('\t"%s";\n' % identifier)
632
633     for (rna_base, identifier, rna_struct) in structs:
634
635         if isop(rna_struct):
636             continue
637
638         base = rna_struct.base
639
640         if base and not isop(base):
641             out.write('\t"%s" -> "%s" [label="(base)" weight=1.0];\n' % (base.identifier, identifier))
642
643         nested = rna_struct.nested
644         if nested and not isop(nested):
645             out.write('\t"%s" -> "%s" [label="(nested)"  weight=1.0];\n' % (nested.identifier, identifier))
646
647
648
649         rna_refs= rna_references_dict[identifier]
650
651         for rna_ref_string in rna_refs:
652
653             if '_OT_' in rna_ref_string:
654                 continue
655
656             ref = rna_ref_string.split('.')[-2]
657             out.write('\t"%s" -> "%s" [label="%s" weight=0.01];\n' % (ref, identifier, rna_ref_string))
658
659
660     out.write('}\n')
661     out.close()
662
663     # # We could also just run....
664     # os.system('dot source/blender/python/doc/rna.dot -Tsvg -o ./source/blender/python/doc/rna.svg')
665
666
667     out= open(target_path.replace('.py', '.words'), 'w')
668     rna_words = list(rna_words)
669     rna_words.sort()
670     for w in rna_words:
671         out.write('%s\n' % w)
672
673
674 def op2epy(BASEPATH):
675     # out = open(target_path, 'w')
676
677     op_mods = dir(bpy.ops)
678     op_mods.remove('add')
679     op_mods.remove('remove')
680
681     for op_mod_name in sorted(op_mods):
682         if op_mod_name.startswith('__'):
683             continue
684
685         # open the submodule
686         mod_path = os.path.join("ops", op_mod_name + ".py")
687         out = open_submodule(mod_path, BASEPATH)
688
689
690         op_mod = getattr(bpy.ops, op_mod_name)
691         operators = dir(op_mod)
692         for op in sorted(operators):
693             # rna = getattr(bpy.types, op).bl_rna
694             rna = getattr(op_mod, op).get_rna()
695             write_func(rna, '', out, 'OPERATOR')
696
697         out.write('\n')
698         out.close()
699
700 def misc2epy(BASEPATH):
701     '''
702     Hard coded modules, try to avoid adding stuff here
703     '''
704
705     f = append_package(os.path.join(BASEPATH, ""), ""); # add a slash on the end of the base path
706     f.write('''
707 """
708 @type data: L{bpy.types.Main}
709 @var  data: blender data is accessed from here
710 """
711 ''')
712
713     f = open_submodule("props.py", BASEPATH)
714     f.write('''
715 MAX_INT= 2**31
716 MAX_FLOAT= 1e+37
717 def BoolProperty(attr, name="", description="", default=False):
718     """
719     return a new bool property
720     """
721 def IntProperty(attr, name="", description="", min=-MAX_INT, max=MAX_INT, soft_min=-MAX_INT, soft_max=MAX_INT, default=0):
722     """
723     return a new int property
724     """
725 def FloatProperty(attr, name="", description="", min=-MAX_FLOAT, max=MAX_FLOAT, soft_min=-MAX_FLOAT, soft_max=MAX_FLOAT, default=0.0):
726     """
727     return a new float property
728     """
729 def StringProperty(attr, name="", description="", maxlen=0, default=""):
730     """
731     return a new string property
732     """
733 def EnumProperty(attr, items, name="", description="", default=""):
734     """
735     return a new enum property
736     """
737 ''')
738
739
740 if __name__ == '__main__':
741     if 'bpy' not in dir():
742         print("\nError, this script must run from inside blender2.5")
743         print(script_help_msg)
744     else:
745         misc2epy('source/blender/python/doc/bpy') # first to write in info in some of the modules.
746         rna2epy('source/blender/python/doc/bpy')
747         op2epy('source/blender/python/doc/bpy')
748
749
750     close_all()
751
752     import sys
753     sys.exit()