From 9fa85fac474a409423924bc080aea8d8f1f9863f Mon Sep 17 00:00:00 2001 From: "Dustin C. Hatch" Date: Sun, 27 Mar 2011 15:24:41 -0500 Subject: [PATCH] Added an icon and support for automatically serving favicon.ico --- MANIFEST.in | 1 + milla.svg | 324 +++++++++++++++++++++++++++++++++++++++ src/milla/app.py | 20 ++- src/milla/controllers.py | 31 ++++ src/milla/milla.ico | Bin 0 -> 93726 bytes 5 files changed, 374 insertions(+), 2 deletions(-) create mode 100644 MANIFEST.in create mode 100755 milla.svg create mode 100755 src/milla/milla.ico diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 0000000..3ab3f39 --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1 @@ +include src/milla/milla.ico diff --git a/milla.svg b/milla.svg new file mode 100755 index 0000000..3332376 --- /dev/null +++ b/milla.svg @@ -0,0 +1,324 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + diff --git a/src/milla/app.py b/src/milla/app.py index 30a575a..2a54876 100644 --- a/src/milla/app.py +++ b/src/milla/app.py @@ -7,6 +7,7 @@ Please give me a docstring! :Updated: $Date$ :Updater: $Author$ ''' +from milla.controllers import FaviconController from webob.exc import HTTPNotFound, WSGIHTTPException import milla.dispatch import webob @@ -34,14 +35,29 @@ class Application(object): def __init__(self, dispatcher): self.dispatcher = dispatcher - self.config = {} + self.config = {'milla.favicon': True} def __call__(self, environ, start_response): path_info = environ['PATH_INFO'] try: func = self.dispatcher.resolve(path_info) except milla.dispatch.UnresolvedPath: - return HTTPNotFound()(environ, start_response) + def asbool(val): + if not val: + return False + try: + val = val.lower() + except AttributeError: + pass + if val in ('false', 'no', 'f', 'n', 'off'): + return False + return True + + if asbool(self.config.get('milla.favicon')) and \ + path_info == '/favicon.ico': + func = FaviconController() + else: + return HTTPNotFound()(environ, start_response) request = webob.Request(environ) request.config = self.config.copy() diff --git a/src/milla/controllers.py b/src/milla/controllers.py index 796233d..5f8cd9b 100644 --- a/src/milla/controllers.py +++ b/src/milla/controllers.py @@ -9,6 +9,11 @@ from one or more of these classes can make things significantly easier. :Updated: $Date$ :Updater: $Author$ ''' +import milla +import os + +__all__ = ['Controller', 'FaviconController'] + class Controller(object): '''The base controller class @@ -21,3 +26,29 @@ class Controller(object): def __after__(self, request): pass + +class FaviconController(Controller): + '''A controller for the "favicon" + + This controller is specifically suited to serve a site "favicon" or + bookmark icon. By default, it will serve the *Milla* icon, but you + can pass an alternate file time to the constructor. + + :param icon: Path to an icon to serve + ''' + + def __init__(self, icon=None): + if not icon: + icon = os.path.join(os.path.dirname(milla.__file__), 'milla.ico') + try: + self.icon = open(icon) + except (IOError, OSError): + self.icon = None + + def __call__(self, request): + if not self.icon: + raise milla.HTTPNotFound + response = milla.Response() + response.app_iter = self.icon + response.headers['Content-Type'] = 'image/x-icon' + return response diff --git a/src/milla/milla.ico b/src/milla/milla.ico new file mode 100755 index 0000000000000000000000000000000000000000..5e6fe35e82a45046645cb473aa237ee4879b3f15 GIT binary patch literal 93726 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�VMnHmSi8f9i(;`jEU^2)-4ezC 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 literal 0 HcmV?d00001