changeset 85:3262010f7f79

add command line serving
author Jeff Hammel <jhammel@mozilla.com>
date Sat, 28 Dec 2013 21:56:06 -0800
parents 95820b36d7e3
children a9f5b60006ba
files decoupage/cli.py decoupage/formatters.py decoupage/web.py setup.py
diffstat 4 files changed, 57 insertions(+), 34 deletions(-) [+]
line wrap: on
line diff
--- a/decoupage/cli.py	Sat Dec 28 18:12:16 2013 -0800
+++ b/decoupage/cli.py	Sat Dec 28 21:56:06 2013 -0800
@@ -10,17 +10,27 @@
 
 import optparse
 import os
+import socket
 import sys
 
+from .formatters import Sort, Up
 from .web import Decoupage
 from wsgiref import simple_server
 
 here = os.path.dirname(os.path.realpath(__file__))
 
-def DecoupageServer(object):
+class DecoupageServer(Decoupage):
     """serve locally with decoupage"""
-    def __init__(self):
-        raise NotImplementedError("Do I need this?")
+    # TODO: deprecate; move Decoupage to a few classes
+    # with more flexible formatters
+    def __init__(self, *args, **kwargs):
+        Decoupage.__init__(self, **kwargs)
+        # default formatters
+        # TODO: make configurable
+        self._formatters = [Sort(), Up('..')]
+    def get_formatters(self, path):
+        return self._formatters
+
 
 def main(args=sys.argv[1:]):
 
@@ -30,9 +40,15 @@
     parser.add_option('-p', '--port', dest='port',
                       type='int', default=1977,
                       help="port to serve on [DEFAULT: %default]")
+    parser.add_option('-a', '--address', dest='address',
+                      default='0.0.0.0',
+                      help="address to serve on [DEFAULT: %default]")
     parser.add_option('--no-reload', dest='auto_reload',
                       action='store_false', default=True,
                       help="do not dynamically refresh indices")
+    parser.add_option('--no-print-ip', dest='print_ip',
+                      action='store_false', default=True,
+                      help="do not print resolvable IP address")
     options, args = parser.parse_args(args)
     if not args:
         directory = os.getcwd()
@@ -47,28 +63,35 @@
 
         parser.print_help()
         parser.exit(1)
+    if not os.path.isdir(directory):
+        raise OSError("'%s' is not a directory" % directory)
 
-    if not os.path.isdir(directory):
-        raise ("'%s' is not a directory" % directory)
-
+    # create WSGI app
     # TODO:
     # - allow CLI specification of formatters
     # - template specification
-
-    # create WSGI app
-    app = Decoupage(directory=directory,
-                    auto_reload=options.auto_reload)
+    app = DecoupageServer(directory=directory,
+                          auto_reload=options.auto_reload)
 
 
     # create server
     # TODO: allow choice amongst server classes
-    address = '127.0.0.1'
-    server = simple_server.make_server(address, options.port, app)
+    printable_address = '127.0.0.1' if options.address == '0.0.0.0' else options.address
+    server = simple_server.make_server(options.address, options.port, app)
     print 'serving directory %s ( %s ) at \nhttp://%s:%d/' % (directory,
                                                               'file://' + directory, # XXX
-                                                              address,
+                                                              printable_address,
                                                               options.port)
+    if options.print_ip:
+        # from http://stackoverflow.com/questions/166506/finding-local-ip-addresses-using-pythons-stdlib
+        hostname = "google.com"
+        s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
+        s.connect((hostname,80))
+        hostname = s.getsockname()[0]
+        print "http://%s:%s/" % (hostname, options.port)
+        s.close()
 
+    # serve directory contents via decoupage
     try:
         server.serve_forever()
     except KeyboardInterrupt:
--- a/decoupage/formatters.py	Sat Dec 28 18:12:16 2013 -0800
+++ b/decoupage/formatters.py	Sat Dec 28 21:56:06 2013 -0800
@@ -91,7 +91,7 @@
     """
     defaults = {'order': 'name'}
 
-    def __init__(self, pattern):
+    def __init__(self, pattern=''):
         FormatterBase.__init__(self, pattern)
         self.orders = {'name': self.name,
                        'random': self.random,
--- a/decoupage/web.py	Sat Dec 28 18:12:16 2013 -0800
+++ b/decoupage/web.py	Sat Dec 28 21:56:06 2013 -0800
@@ -189,20 +189,8 @@
         data['scripts'] = ()
 
         # apply formatters
-        # XXX this should be cached if not self.auto_reload
-        if '/formatters' in conf:
-            # ordered list of formatters to be applied first
-            formatters = [ i for i in conf['/formatters'].split()
-                           if i in self.formatters ]
-        else:
-            formatters = []
-        for key in conf:
-            if key.startswith('/'):
-                key = key[1:]
-                if key in self.formatters and key not in formatters:
-                    formatters.append(key)
-        for name in formatters:
-            formatter = self.formatters[name](conf.get('/%s' % name, ''))
+        formatters = self.get_formatters(path)
+        for formatter in formatters:
             formatter(request, data)
 
         # return an alternate format if specified
@@ -352,11 +340,23 @@
 
         return conf
 
-    def fmtrs(self, path):
-        formatters = []
-        for key, value in self.conf(path).items():
+    def get_formatters(self, path):
+        """return formatters for a path"""
+        retval = []
+        conf = self.conf(path)
+        # apply formatters
+        # XXX this should be cached if not self.auto_reload
+        if '/formatters' in conf:
+            # ordered list of formatters to be applied first
+            formatters = [ i for i in conf['/formatters'].split()
+                           if i in self.formatters ]
+        else:
+            formatters = []
+        for key in conf:
             if key.startswith('/'):
                 key = key[1:]
-                if key in self.formatters:
-                    formatter = self.formatters[key](value)
+                if key in self.formatters and key not in formatters:
+                    formatters.append(key)
+        for name in formatters:
+            retval.append(self.formatters[name](conf.get('/%s' % name, '')))
 
--- a/setup.py	Sat Dec 28 18:12:16 2013 -0800
+++ b/setup.py	Sat Dec 28 21:56:06 2013 -0800
@@ -6,7 +6,7 @@
 except IOError:
     description = ''
 
-version = '0.12.2'
+version = '0.13.0'
 
 setup(name='decoupage',
       version=version,