Take the 2-minute tour ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

pydoc allows you to view documentation of python modules and packages in directories added to your pythonpath in a browser. But is there a way to browse the complete code of those files?

Edit:

converted Edoardo Ivanec's code using 3to2:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from __future__ import with_statement
import CGIHTTPServer, SimpleHTTPServer, BaseHTTPServer
import os  
from pygments import highlight
from pygments.lexers import PythonLexer
from pygments.formatters import HtmlFormatter
from io import open

class SourceViewer(SimpleHTTPServer.SimpleHTTPRequestHandler):
    def do_GET(self):
        path = os.path.join(os.getcwdu(), self.path[1:])
        if os.path.exists(path) and path.endswith(u'.py'):
            with open(path) as file:
                code = file.read()
                hl = highlight(code, PythonLexer(), HtmlFormatter(noclasses=True, linenos=u'table'))
                self.send_response(200)
                self.end_headers()
                self.wfile.write(str(hl).encode('UTF-8'))
                return
        else:       
            super(self.__class__, self).do_GET()


if __name__ == u"__main__":
    server = BaseHTTPServer.HTTPServer((u'localhost', 8080), SourceViewer)
    server.serve_forever()

Going to localhost:8080 shows a no data received message. How should I feed it data?

share|improve this question

1 Answer 1

up vote 2 down vote accepted

You can extend the HTTP server in the standard library with the help of pygments to serve a highlighted & line-numbered version of the Python source files in a directory. Example (Python 3):

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import http.server
import os  
from pygments import highlight
from pygments.lexers import PythonLexer
from pygments.formatters import HtmlFormatter

class SourceViewer(http.server.SimpleHTTPRequestHandler):
    def do_GET(self):
        path = os.path.join(os.getcwd(), self.path[1:])
        if os.path.exists(path) and path.endswith('.py'):
            with open(path) as file:
                code = file.read()
                hl = highlight(code, PythonLexer(), HtmlFormatter(noclasses=True, linenos='table'))
                self.send_response(200)
                self.end_headers()
                self.wfile.write(bytes(hl, 'UTF-8'))
                return
        else:       
            super().do_GET()


if __name__ == "__main__":
    server = http.server.HTTPServer(('localhost', 8080), SourceViewer)
    server.serve_forever()

Python 2, based in your 3to2 conversion:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from __future__ import with_statement
import SimpleHTTPServer, BaseHTTPServer
import os  
from pygments import highlight
from pygments.lexers import PythonLexer
from pygments.formatters import HtmlFormatter

class SourceViewer(SimpleHTTPServer.SimpleHTTPRequestHandler):
    def do_GET(self):
        path = os.path.join(os.getcwdu(), self.path[1:])
        if os.path.exists(path) and path.endswith(u'.py'):
            with open(path) as file:
                code = file.read()
                hl = highlight(code, PythonLexer(), HtmlFormatter(noclasses=True, linenos=u'table'))
                self.send_response(200)
                self.end_headers()
                self.wfile.write(hl)
                return
        else:    
            SimpleHTTPServer.SimpleHTTPRequestHandler.do_GET(self)

if __name__ == u"__main__":
    server = BaseHTTPServer.HTTPServer((u'localhost', 8080), SourceViewer)
    server.serve_forever()

Example result:

Example result

share|improve this answer
    
Hey Eduardo! I converted the code using 3to2.(see edited original post.) However, I get a no data received message, how should I pass the data? –  Bentley4 Jun 16 '12 at 22:51
    
That's too bad - I'll try it when I get home in a couple of minutes. –  Eduardo Ivanec Jun 16 '12 at 23:23
    
It seems the super() call to SimpleHTTPRequestHandler was failing - it may be because it's an old-style class, although that seems strange and I didn't really check. Please see the new version in the edit, it works with the explicit call to the parent class. –  Eduardo Ivanec Jun 16 '12 at 23:30
1  
If on a pinch I would just create a new directory full of symlinks to all interesting source locations. It should work. –  Eduardo Ivanec Jun 17 '12 at 0:28
1  
You could also add an 'elif' that tries to import the required name as a module (using __import__). If it works you can then use modulename.__file__ to find out the filename you have to open to show its source. But that wouldn't help with actually listing the available modules. You would have to use something like pkgutil (docs.python.org/library/pkgutil.html#pkgutil.iter_modules) for that. –  Eduardo Ivanec Jun 17 '12 at 0:59

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.