#!/usr/bin/env python
# system
### Twisted Preamble
# This makes sure that users don't have to set up their environment
# specially in order to run these programs from bin/.
import sys, os, string
if string.find(os.path.abspath(sys.argv[0]), os.sep+'Twisted') != -1:
    sys.path.insert(0, os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]
), os.pardir, os.pardir)))
sys.path.insert(0, os.curdir)
### end of preamble

import os, sys

# HACK: Don't import stuff that we don't like

def myimport(*args):
    try: 
        return im(*args)
    except:
        mod = FakeModule(args[0], 4)
        i = args[0].rfind('.')
        if i != -1:
            setattr(sys.modules[args[0][:i]], args[0][i+1:], mod)
        return mod

class FakeModule:

    def __init__(self, name, level):
        self.__level = level
        self.__name__ = name

    def __repr__(self):
        return '<Fake %s>' % self.__name__
    __str__ = __repr__

    def __nonzero__(self):
        return 1

    def __call__(self, *args, **kw):
        pass #print 'Called:', args

    def __getattr__(self, attr):
        if self.__level == 0:
            raise AttributeError
        return FakeModule(self.__name__+'.'+attr, self.__level-1)

    def __cmp__(self, other):
        if not hasattr(other, '___name__'):
            return -1
        return cmp(self.__name__, other.__name__)

def fakeOut(modname):
    modpath = modname.split('.')
    prevmod = None
    for m in range(len(modpath)):
        mp = '.'.join(modpath[:m+1])
        nm = FakeModule(mp, 4)
        if prevmod:
            setattr(prevmod, modpath[m], nm)
        sys.modules[mp] = nm
        prevmod = nm
        print mp

fakeOut("gnome.ui")
fakeOut("pygtk")
fakeOut("gtk")
fakeOut("wxPython.wx")

# HACK: make Twisted Interfaces not use __metaclass__ =
# MetaInterface. Epydoc barfs on any classes whose type isn't
# TypeType.

from twisted.python import components

class Interface:
    pass

Interface.__module__ = 'twisted.python.components'
Interface.__doc__ = components.Interface.__doc__
components.Interface = Interface

# initial twisted
from twisted.python import reflect
from twisted.internet import reactor
# epydoc
import epydoc
assert epydoc.__version__[0] == '2', "You need epydoc 2.x!"
from epydoc.cli import cli
from epydoc.html import HTMLFormatter
from epydoc import uid
import epydoc.html

# HACK: Force everything to be public.

def is_private(self):
    return False
def is_public(self):
    return True

uid.UID.is_private = is_private
uid.UID.is_public = is_public

# HACK: Don't append -module and -class to the filenames, and generate
# redirecty-files for all methods.

class TwistedHTMLFormatter(HTMLFormatter):
    def _uid_to_filename(self, uid):
        # Enforce same restrictions as HTMLFormatter._uid_to_filename for sanity
        # checking
        assert uid.is_module() or uid.is_class(), 'Bad UID type: %r' % (uid,)
        return uid.name() + '.html'
        
    def _uid_to_uri(self, uid):
        if uid.is_module() or uid.is_class():
            return uid.name() + '.html'

        parent = uid.parent()
        if parent is None:
            return uid.name() + '.html'

        return parent.name() + '.html#' + uid.shortname()

    def _method_to_html(self, uid):
        """
        Dodgy redirect hack.
        """
        str = ('<html><head>\n'
               '<meta http-equiv=refresh content="0; url=%s#%s">\n'
               '</head></html>\n')
        str = str % (self._uid_to_uri(uid.parent()), uid.shortname())
        return str

    def write(self, directory=None, progress_callback=None):
        HTMLFormatter.write(self, directory, progress_callback)
        
        # Write method redirectors
        self._write_method_redirects(directory)

    def _write_method_redirects(self, directory):
        import os.path
        seen = {}
        for uid, doc in self._docmap.data.iteritems():
            if uid.is_method() or uid.is_function():
                if uid.name() in seen: continue
                seen[uid.name()] = 1
                filename = os.path.join(directory, uid.name() + '.html')
                #assert not os.path.exists(filename), filename
                s = self._method_to_html(uid)
                open(filename, 'w').write(s)

epydoc.html.HTMLFormatter = TwistedHTMLFormatter

# HACK: Only document stuff that we _tell_ you to document, you stupid
# &#@&!#@

from epydoc import objdoc

orig_add = objdoc.DocMap._add

def _add(self, objID):
    m = objID.module()
    if m and m.name() not in modnames: # see below for where modnames is defined
        return
    return orig_add(self, objID)

objdoc.DocMap._add = _add

# Now, set up the list of modules for epydoc to document

modnames = []
def addMod(arg, path, files):
    for fn in files:
        file = os.path.join(path, fn).replace('%s__init__'%os.sep, '')
        if file[-3:] == '.py' and not file.count('%stest%s' % (os.sep,os.sep)):
            modName = file[2:-3].replace(os.sep,'.')
            try:
                #print 'pre-loading', modName
                reflect.namedModule(modName)
            except ImportError:
                print 'import error:', modName
            except:
                print 'other error:', modName
            else:
                modnames.append(modName)
osrv = sys.argv
sys.argv=["IGNORE"]
im = __import__
__builtins__.__import__ = myimport
os.path.walk('./twisted', addMod, None)
__builtins__.__import__ = im
sys.argv = osrv

from twisted import copyright

sys.argv.extend(['-n', 'Twisted %s' % copyright.version, '-u', 'http://twistedmatrix.com/', '--no-private'])

sys.argv.extend(modnames)              # list of modules
# Make it easy to profile epyrun
if 0:
    import profile
    profile.run('cli()', 'epyrun.prof')
else:
    cli()
print 'Done!'
