<s> """<STR_LIT>""" <EOL> import os <EOL> import re <EOL> from types import BuiltinFunctionType , FunctionType <EOL> DEBUG = True <EOL> class ApiDocWriter ( object ) : <EOL> '''<STR_LIT>''' <EOL> rst_section_levels = [ '<STR_LIT:*>' , '<STR_LIT:=>' , '<STR_LIT:->' , '<STR_LIT>' , '<STR_LIT>' ] <EOL> def __init__ ( self , <EOL> package_name , <EOL> rst_extension = '<STR_LIT>' , <EOL> skip_patterns = [ '<STR_LIT>' , '<STR_LIT>' ] , <EOL> ) : <EOL> '''<STR_LIT>''' <EOL> self . package_name = package_name <EOL> self . skip_patterns = skip_patterns <EOL> self . rst_extension = rst_extension <EOL> root_module = self . _import ( package_name ) <EOL> self . root_path = root_module . __path__ [ - <NUM_LIT:1> ] <EOL> def _import ( self , name ) : <EOL> '''<STR_LIT>''' <EOL> mod = __import__ ( name ) <EOL> components = name . split ( '<STR_LIT:.>' ) <EOL> for comp in components [ <NUM_LIT:1> : ] : <EOL> mod = getattr ( mod , comp ) <EOL> return mod <EOL> def _get_object_name ( self , line ) : <EOL> '''<STR_LIT>''' <EOL> name = line . split ( ) [ <NUM_LIT:1> ] . split ( '<STR_LIT:(>' ) [ <NUM_LIT:0> ] . strip ( ) <EOL> return name . rstrip ( '<STR_LIT::>' ) <EOL> def _parse_module_with_import ( self , uri ) : <EOL> """<STR_LIT>""" <EOL> mod = __import__ ( uri , fromlist = [ uri . split ( '<STR_LIT:.>' ) [ - <NUM_LIT:1> ] ] ) <EOL> obj_strs = [ obj for obj in dir ( mod ) if not obj . startswith ( '<STR_LIT:_>' ) ] <EOL> functions = [ ] <EOL> classes = [ ] <EOL> for obj_str in obj_strs : <EOL> if obj_str not in mod . __dict__ : <EOL> continue <EOL> obj = mod . __dict__ [ obj_str ] <EOL> if ( hasattr ( obj , '<STR_LIT>' ) <EOL> and self . package_name not in obj . __module__ ) : <EOL> continue <EOL> if isinstance ( obj , ( FunctionType , BuiltinFunctionType ) ) : <EOL> functions . append ( obj_str ) <EOL> else : <EOL> try : <EOL> issubclass ( obj , object ) <EOL> classes . append ( obj_str ) <EOL> except TypeError : <EOL> pass <EOL> return functions , classes <EOL> def generate_api_doc ( self , uri ) : <EOL> '''<STR_LIT>''' <EOL> functions , classes = self . _parse_module_with_import ( uri ) <EOL> if not len ( functions ) and not len ( classes ) and DEBUG : <EOL> print ( '<STR_LIT>' , uri ) <EOL> return '<STR_LIT>' <EOL> uri_short = re . sub ( r'<STR_LIT>' % self . package_name , '<STR_LIT>' , uri ) <EOL> ad = '<STR_LIT>' <EOL> if '<STR_LIT:.>' in uri : <EOL> title = '<STR_LIT>' + uri_short + '<STR_LIT>' <EOL> else : <EOL> title = '<STR_LIT>' + uri_short + '<STR_LIT>' <EOL> ad += title + '<STR_LIT:\n>' + self . rst_section_levels [ <NUM_LIT:1> ] * len ( title ) <EOL> ad += '<STR_LIT>' + uri + '<STR_LIT:\n>' <EOL> ad += '<STR_LIT>' + uri + '<STR_LIT:\n>' <EOL> ad += '<STR_LIT>' <EOL> for f in functions : <EOL> ad += '<STR_LIT:U+0020>' + uri + '<STR_LIT:.>' + f + '<STR_LIT:\n>' <EOL> ad += '<STR_LIT:\n>' <EOL> for c in classes : <EOL> ad += '<STR_LIT:U+0020>' + uri + '<STR_LIT:.>' + c + '<STR_LIT:\n>' <EOL> ad += '<STR_LIT:\n>' <EOL> for f in functions : <EOL> full_f = uri + '<STR_LIT:.>' + f <EOL> ad += f + '<STR_LIT:\n>' <EOL> ad += self . rst_section_levels [ <NUM_LIT:2> ] * len ( f ) + '<STR_LIT:\n>' <EOL> ad += '<STR_LIT>' + full_f + '<STR_LIT>' <EOL> for c in classes : <EOL> ad += '<STR_LIT>' + c + '<STR_LIT>' + self . rst_section_levels [ <NUM_LIT:2> ] * ( len ( c ) + <NUM_LIT:9> ) + '<STR_LIT>' <EOL> ad += '<STR_LIT>' + c + '<STR_LIT:\n>' <EOL> ad += '<STR_LIT>' '<STR_LIT>' '<STR_LIT>' '<STR_LIT:\n>' '<STR_LIT>' <EOL> return ad <EOL> def _survives_exclude ( self , matchstr ) : <EOL> '''<STR_LIT>''' <EOL> for pat in self . skip_patterns : <EOL> if re . compile ( pat ) . search ( matchstr ) : <EOL> return False <EOL> return True <EOL> def _uri2path ( self , uri ) : <EOL> '''<STR_LIT>''' <EOL> if uri == self . package_name : <EOL> return os . path . join ( self . root_path , '<STR_LIT>' ) <EOL> path = uri . replace ( self . package_name + '<STR_LIT:.>' , '<STR_LIT>' ) <EOL> path = path . replace ( '<STR_LIT:.>' , os . path . sep ) <EOL> path = os . path . join ( self . root_path , path ) <EOL> if os . path . exists ( path + '<STR_LIT>' ) : <EOL> path += '<STR_LIT>' <EOL> elif os . path . exists ( os . path . join ( path , '<STR_LIT>' ) ) : <EOL> path = os . path . join ( path , '<STR_LIT>' ) <EOL> else : <EOL> return None <EOL> return path <EOL> def _path2uri ( self , dirpath ) : <EOL> '''<STR_LIT>''' <EOL> package_dir = self . package_name . replace ( '<STR_LIT:.>' , os . path . sep ) <EOL> relpath = dirpath . replace ( self . root_path , package_dir ) <EOL> if relpath . startswith ( os . path . sep ) : <EOL> relpath = relpath [ <NUM_LIT:1> : ] <EOL> return relpath . replace ( os . path . sep , '<STR_LIT:.>' ) <EOL> def discover_modules ( self ) : <EOL> '''<STR_LIT>''' <EOL> modules = [ self . package_name ] <EOL> for dirpath , dirnames , filenames in os . walk ( self . root_path , <EOL> topdown = False ) : <EOL> root_uri = self . _path2uri ( os . path . join ( self . root_path , <EOL> dirpath ) ) <EOL> filenames = [ f for f in filenames if f . endswith ( '<STR_LIT>' ) ] <EOL> uris = [ u . strip ( '<STR_LIT>' ) for u in dirnames + filenames ] <EOL> for uri in uris : <EOL> package_uri = '<STR_LIT:.>' . join ( ( root_uri , uri ) ) <EOL> if ( self . _uri2path ( package_uri ) and <EOL> self . _survives_exclude ( package_uri ) ) : <EOL> try : <EOL> mod = __import__ ( package_uri , fromlist = [ '<STR_LIT>' ] ) <EOL> mod . __all__ <EOL> modules . append ( package_uri ) <EOL> except ( ImportError , AttributeError ) : <EOL> pass <EOL> return sorted ( modules ) <EOL> def write_modules_api ( self , modules , outdir ) : <EOL> written_modules = [ ] <EOL> for m in modules : <EOL> api_str = self . generate_api_doc ( m ) <EOL> if not api_str : <EOL> continue <EOL> outfile = os . path . join ( outdir , <EOL> m + self . rst_extension ) <EOL> fileobj = open ( outfile , '<STR_LIT>' ) <EOL> fileobj . write ( api_str ) <EOL> fileobj . close ( ) <EOL> written_modules . append ( m ) <EOL> self . written_modules = written_modules <EOL> def write_api_docs ( self , outdir ) : <EOL> """<STR_LIT>""" <EOL> if not os . path . exists ( outdir ) : <EOL> os . mkdir ( outdir ) <EOL> modules = self . discover_modules ( ) <EOL> self . write_modules_api ( modules , outdir ) <EOL> def write_index ( self , outdir , froot = '<STR_LIT>' , relative_to = None ) : <EOL> """<STR_LIT>""" <EOL> if self . written_modules is None : <EOL> raise ValueError ( '<STR_LIT>' ) <EOL> path = os . path . join ( outdir , froot + self . rst_extension ) <EOL> if relative_to is not None : <EOL> relpath = ( outdir + os . path . sep ) . replace ( relative_to + os . path . sep , '<STR_LIT>' ) <EOL> else : <EOL> relpath = outdir <EOL> print ( "<STR_LIT>" , relpath ) <EOL> idx = open ( path , '<STR_LIT>' ) <EOL> w = idx . write <EOL> w ( '<STR_LIT>' ) <EOL> title = "<STR_LIT>" <EOL> w ( title + "<STR_LIT:\n>" ) <EOL> w ( "<STR_LIT:=>" * len ( title ) + "<STR_LIT>" ) <EOL> w ( '<STR_LIT>' ) <EOL> for f in self . written_modules : <EOL> w ( '<STR_LIT>' % os . path . join ( relpath , f ) ) <EOL> idx . close ( ) </s>
