Commits

David Bennett committed 75eec57

Initial commit.

Comments (0)

Files changed (8)

+syntax: glob
+*.pyc
+*.pyo
+*.orig
+*.egg-info
+MANIFEST
+dist
+build
+include README.rst
+global-exclude *.pyc
+============================
+django-uwsgi-admin-grappelli
+============================
+
+This is a version of the `uWSGI Django App`_ that looks nice when using the
+`Django Grappelli`_ admin theme. I've turned it into an installable app for
+convenience.
+
+Here's an example of how you might want to include it in your `urls.py`::
+
+    try:
+        import uwsgi
+        urlpatterns = patterns('',
+            url(r'^admin/uwsgi/', include('aportal.uwsgi_admin.urls')),
+        )
+    except ImportError:
+        urlpatterns = ()
+
+    urlpatterns += patterns('',
+        url(r'^grappelli/', include('grappelli.urls')),
+        url(r'^admin/doc/', include('django.contrib.admindocs.urls')),
+        url(r'^admin/', include(admin.site.urls)),
+    )
+
+.. _uWSGI Django App: http://projects.unbit.it/uwsgi/wiki/uWSGIDjangoApp
+.. _Django Grappelli: http://sehmaschine.github.com/django-grappelli/
+import os
+import re
+import sys
+from fnmatch import fnmatchcase
+from distutils.util import convert_path
+from setuptools import setup, find_packages
+
+
+def read(*parts):
+    return open(os.path.join(os.path.dirname(__file__), *parts)).read()
+
+
+def find_version(*file_paths):
+    version_file = read(*file_paths)
+    version_match = re.search(r"^__version__ = ['\"]([^'\"]*)['\"]",
+                              version_file, re.M)
+    if version_match:
+        return version_match.group(1)
+    raise RuntimeError("Unable to find version string.")
+
+
+# Provided as an attribute, so you can append to these instead
+# of replicating them:
+standard_exclude = ('*.py', '*.pyc', '*$py.class', '*~', '.*', '*.bak')
+standard_exclude_directories = ('.*', 'CVS', '_darcs', './build',
+                                './dist', 'EGG-INFO', '*.egg-info')
+
+
+# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
+# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
+# Note: you may want to copy this into your setup.py file verbatim, as
+# you can't import this from another package, when you don't know if
+# that package is installed yet.
+def find_package_data(
+    where='.', package='',
+    exclude=standard_exclude,
+    exclude_directories=standard_exclude_directories,
+    only_in_packages=True,
+    show_ignored=False):
+    """
+    Return a dictionary suitable for use in ``package_data``
+    in a distutils ``setup.py`` file.
+
+    The dictionary looks like::
+
+        {'package': [files]}
+
+    Where ``files`` is a list of all the files in that package that
+    don't match anything in ``exclude``.
+
+    If ``only_in_packages`` is true, then top-level directories that
+    are not packages won't be included (but directories under packages
+    will).
+
+    Directories matching any pattern in ``exclude_directories`` will
+    be ignored; by default directories with leading ``.``, ``CVS``,
+    and ``_darcs`` will be ignored.
+
+    If ``show_ignored`` is true, then all the files that aren't
+    included in package data are shown on stderr (for debugging
+    purposes).
+
+    Note patterns use wildcards, or can be exact paths (including
+    leading ``./``), and all searching is case-insensitive.
+    """
+
+    out = {}
+    stack = [(convert_path(where), '', package, only_in_packages)]
+    while stack:
+        where, prefix, package, only_in_packages = stack.pop(0)
+        for name in os.listdir(where):
+            fn = os.path.join(where, name)
+            if os.path.isdir(fn):
+                bad_name = False
+                for pattern in exclude_directories:
+                    if (fnmatchcase(name, pattern)
+                        or fn.lower() == pattern.lower()):
+                        bad_name = True
+                        if show_ignored:
+                            print >> sys.stderr, (
+                                "Directory %s ignored by pattern %s"
+                                % (fn, pattern))
+                        break
+                if bad_name:
+                    continue
+                if (os.path.isfile(os.path.join(fn, '__init__.py'))
+                    and not prefix):
+                    if not package:
+                        new_package = name
+                    else:
+                        new_package = package + '.' + name
+                    stack.append((fn, '', new_package, False))
+                else:
+                    stack.append((fn, prefix + name + '/', package, only_in_packages))
+            elif package or not only_in_packages:
+                # is a file
+                bad_name = False
+                for pattern in exclude:
+                    if (fnmatchcase(name, pattern)
+                        or fn.lower() == pattern.lower()):
+                        bad_name = True
+                        if show_ignored:
+                            print >> sys.stderr, (
+                                "File %s ignored by pattern %s"
+                                % (fn, pattern))
+                        break
+                if bad_name:
+                    continue
+                out.setdefault(package, []).append(prefix+name)
+    return out
+
+
+setup(
+    name="django-uwsgi-admin-grappelli",
+    version=find_version("uwsgi_admin", "__init__.py"),
+    description="uWSGI Django App that looks nice when using Django Grappelli.",
+    long_description=read("README.rst"),
+    author="David Bennett",
+    author_email="david@dbinit.com",
+    license="BSD",
+    url="http://bitbucket.org/dbinit/django-uwsgi-admin-grappelli/",
+    packages=find_packages(),
+    package_data=find_package_data(),
+    classifiers=[
+        "Development Status :: 4 - Beta",
+        "Environment :: Web Environment",
+        "Intended Audience :: Developers",
+        "License :: OSI Approved :: BSD License",
+        "Operating System :: OS Independent",
+        "Programming Language :: Python",
+        'Programming Language :: Python :: 2.5',
+        'Programming Language :: Python :: 2.6',
+        'Programming Language :: Python :: 2.7',
+        "Framework :: Django",
+    ],
+    zip_safe=False,
+)

uwsgi_admin/__init__.py

+# http://semver.org
+__version__ = "0.1.0"

uwsgi_admin/templates/admin/uwsgi.html

+{% extends "admin/base_site.html" %}
+
+{% load i18n %}
+
+
+{% block breadcrumbs %}
+<div id="breadcrumbs">
+    <a href="../">{% trans 'Home' %}</a> &rsaquo;
+    {{ title }}
+</div>
+{% endblock %}
+
+
+{% block content %}
+<div id="content-main">
+<b>Master PID:</b> {{masterpid}}<br/>
+<b>Started on:</b> {{started_on}}<br/>
+<b>Buffer size:</b> {{buffer_size}}<br/>
+<b>Workers:</b> {{numproc}}<br/>
+<b>Total requests:</b> {{total_requests}}<br/>
+
+<br/>
+
+<div class="module" style="width:860px">
+<h2>Workers</h2>
+<table style="width:860px">
+    <thead>
+        <tr>
+            <th scope="col">ID</th>
+            <th scope="col">PID</th>
+            <th scope="col">Requests</th>
+            <th scope="col">Running time (ms)</th>
+            <th scope="col">Load</th>
+            <th scope="col">Last spawn</th>
+            <th scope="col">Respawn count</th>
+            <th scope="col">Address space (VSZ)</th>
+            <th scope="col">Resident memory (RSS)</th>
+        </tr>
+    </thead>
+    <tbody>
+{% for w in workers %}
+    <tr>
+        <td align="center">{{w.id}}</td>
+        <td align="center">{{w.pid}}</td>
+        <td align="right">{{w.requests}}</td>
+        <td align="right">{{w.running_time}}</td>
+        <td align="right">{{w.load|floatformat:2}} %</td>
+        <td align="right">{{w.last_spawn_str}}</td>
+        <td align="right">{{w.respawn_count}}</td>
+        <td align="right">{{w.vsz|filesizeformat}}</td>
+        <td align="right">{{w.rss|filesizeformat}}</td>
+    </tr>
+{% endfor %}
+    </tbody>
+</table>
+</div>
+
+<div class="module" style="width:860px">
+<h2>Spooler jobs</h2>
+<table style="width:860px">
+    <thead>
+        <tr>
+            <th scope="row">Job filename</th>
+            <th scope="row">Environment</th>
+        </tr>
+    </thead>
+    <tbody>
+{% for j in jobs %}
+    <tr>
+        <td align="left">{{j.file}}</td>
+        <td align="left">{{j.env}}</td>
+    </tr>
+{% endfor %}
+    </tbody>
+</table>
+</div>
+
+{% if masterpid %}
+<br/>
+<form {% if has_file_field %}enctype="multipart/form-data" {% endif %}action="reload/" method="post">
+{% csrf_token %}
+<div class="module submit-row">
+    <ul class="submit-row">
+        <li>
+            <input type="submit" class="default" value="Gracefully reload uWSGI" name="_reload"/>
+        </li>
+    </ul>
+</div>
+</form>
+{% endif %}
+
+</div>
+
+{% endblock %}
+

uwsgi_admin/urls.py

+from django.conf.urls.defaults import patterns, url
+from views import index, reload
+
+
+urlpatterns = patterns('',
+    url(r'^$', index),
+    url(r'^reload/$', reload)
+)

uwsgi_admin/views.py

+import uwsgi
+import time
+from django.contrib.auth.decorators import user_passes_test
+from django.shortcuts import render_to_response
+from django.template import RequestContext
+from django.core.urlresolvers import reverse
+from django.http import HttpResponseRedirect
+
+
+@user_passes_test(lambda u: u.is_superuser)
+def index(request):
+    workers = uwsgi.workers()
+    total_load = time.time() - uwsgi.started_on
+    for w in workers:
+        w['load'] = (100 * (w['running_time'] / 1000)) / total_load
+        w['last_spawn_str'] = time.ctime(w['last_spawn'])
+
+    jobs = []
+    if 'spooler' in uwsgi.opt:
+        spooler_jobs = uwsgi.spooler_jobs()
+        for j in spooler_jobs:
+            jobs.append({'file': j, 'env': uwsgi.parsefile(j)})
+
+    return render_to_response('admin/uwsgi.html', {
+        'masterpid': uwsgi.masterpid(),
+        'started_on': time.ctime(uwsgi.started_on),
+        'buffer_size': uwsgi.buffer_size,
+        'total_requests': uwsgi.total_requests(),
+        'numproc': uwsgi.numproc,
+        'workers': workers,
+        'jobs': jobs,
+        'title': 'uWSGI status',
+    }, RequestContext(request, {}))
+
+
+@user_passes_test(lambda u: u.is_superuser)
+def reload(request):
+    if uwsgi.masterpid() > 0:
+        uwsgi.reload()
+        request.user.message_set.create(message="uWSGI reloaded")
+    else:
+        request.user.message_set.create(
+            message="The uWSGI master process is not active")
+
+    return HttpResponseRedirect(reverse(index))
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.