Merge pull request #1 from volpino/master

Removing django-annoying from the codebase, setuptools for setup.py and some cleaning
This commit is contained in:
Corentin Chary 2012-03-27 23:12:17 -07:00
commit a8d38127cc
13 changed files with 70 additions and 671 deletions

4
.gitignore vendored
View File

@ -1,4 +1,6 @@
*~
*.pyc
*.py[co]
euscanwww/rrd/*.rrd
euscanwww/media/charts/*.png
*.egg-info
local_settings.py

View File

@ -16,7 +16,6 @@ __version__ = "git"
""" Imports """
import os
import sys
import getopt
import errno

View File

@ -1,194 +0,0 @@
from django.shortcuts import render_to_response
from django import forms
from django.template import RequestContext
from django.db.models import signals as signalmodule
from django.http import HttpResponse
from django.utils import simplejson
__all__ = ['render_to', 'signals', 'ajax_request', 'autostrip']
try:
from functools import wraps
except ImportError:
def wraps(wrapped, assigned=('__module__', '__name__', '__doc__'),
updated=('__dict__',)):
def inner(wrapper):
for attr in assigned:
setattr(wrapper, attr, getattr(wrapped, attr))
for attr in updated:
getattr(wrapper, attr).update(getattr(wrapped, attr, {}))
return wrapper
return inner
def render_to(template=None, mimetype=None):
"""
Decorator for Django views that sends returned dict to render_to_response
function.
Template name can be decorator parameter or TEMPLATE item in returned
dictionary. RequestContext always added as context instance.
If view doesn't return dict then decorator simply returns output.
Parameters:
- template: template name to use
- mimetype: content type to send in response headers
Examples:
# 1. Template name in decorator parameters
@render_to('template.html')
def foo(request):
bar = Bar.object.all()
return {'bar': bar}
# equals to
def foo(request):
bar = Bar.object.all()
return render_to_response('template.html',
{'bar': bar},
context_instance=RequestContext(request))
# 2. Template name as TEMPLATE item value in return dictionary.
if TEMPLATE is given then its value will have higher priority
than render_to argument.
@render_to()
def foo(request, category):
template_name = '%s.html' % category
return {'bar': bar, 'TEMPLATE': template_name}
#equals to
def foo(request, category):
template_name = '%s.html' % category
return render_to_response(template_name,
{'bar': bar},
context_instance=RequestContext(request))
"""
def renderer(function):
@wraps(function)
def wrapper(request, *args, **kwargs):
output = function(request, *args, **kwargs)
if not isinstance(output, dict):
return output
tmpl = output.pop('TEMPLATE', template)
return render_to_response(tmpl, output, \
context_instance=RequestContext(request), mimetype=mimetype)
return wrapper
return renderer
class Signals(object):
'''
Convenient wrapper for working with Django's signals (or any other
implementation using same API).
Example of usage::
# connect to registered signal
@signals.post_save(sender=YourModel)
def sighandler(instance, **kwargs):
pass
# connect to any signal
signals.register_signal(siginstance, signame) # and then as in example above
or
@signals(siginstance, sender=YourModel)
def sighandler(instance, **kwargs):
pass
In any case defined function will remain as is, without any changes.
(c) 2008 Alexander Solovyov, new BSD License
'''
def __init__(self):
self._signals = {}
# register all Django's default signals
for k, v in signalmodule.__dict__.iteritems():
# that's hardcode, but IMHO it's better than isinstance
if not k.startswith('__') and k != 'Signal':
self.register_signal(v, k)
def __getattr__(self, name):
return self._connect(self._signals[name])
def __call__(self, signal, **kwargs):
def inner(func):
signal.connect(func, **kwargs)
return func
return inner
def _connect(self, signal):
def wrapper(**kwargs):
return self(signal, **kwargs)
return wrapper
def register_signal(self, signal, name):
self._signals[name] = signal
signals = Signals()
class JsonResponse(HttpResponse):
"""
HttpResponse descendant, which return response with ``application/json`` mimetype.
"""
def __init__(self, data):
super(JsonResponse, self).__init__(content=simplejson.dumps(data), mimetype='application/json')
def ajax_request(func):
"""
If view returned serializable dict, returns JsonResponse with this dict as content.
example:
@ajax_request
def my_view(request):
news = News.objects.all()
news_titles = [entry.title for entry in news]
return {'news_titles': news_titles}
"""
@wraps(func)
def wrapper(request, *args, **kwargs):
response = func(request, *args, **kwargs)
if isinstance(response, dict):
return JsonResponse(response)
else:
return response
return wrapper
def autostrip(cls):
"""
strip text fields before validation
example:
class PersonForm(forms.Form):
name = forms.CharField(min_length=2, max_length=10)
email = forms.EmailField()
PersonForm = autostrip(PersonForm)
#or you can use @autostrip in python >= 2.6
Author: nail.xx
"""
fields = [(key, value) for key, value in cls.base_fields.iteritems() if isinstance(value, forms.CharField)]
for field_name, field_object in fields:
def get_clean_func(original_clean):
return lambda value: original_clean(value and value.strip())
clean_func = get_clean_func(getattr(field_object, 'clean'))
setattr(field_object, 'clean', clean_func)
return cls

View File

@ -1,5 +0,0 @@
class Redirect(Exception):
def __init__(self, *args, **kwargs):
self.args = args
self.kwargs = kwargs

View File

@ -1,69 +0,0 @@
from django.db import models
from django.db.models import OneToOneField
from django.utils import simplejson as json
from django.core.serializers.json import DjangoJSONEncoder
from django.db.models.fields.related import SingleRelatedObjectDescriptor
class AutoSingleRelatedObjectDescriptor(SingleRelatedObjectDescriptor):
def __get__(self, instance, instance_type=None):
try:
return super(AutoSingleRelatedObjectDescriptor, self).__get__(instance, instance_type)
except self.related.model.DoesNotExist:
obj = self.related.model(**{self.related.field.name: instance})
obj.save()
return obj
class AutoOneToOneField(OneToOneField):
'''
OneToOneField creates related object on first call if it doesnt exist yet.
Use it instead of original OneToOne field.
example:
class MyProfile(models.Model):
user = AutoOneToOneField(User, primary_key=True)
home_page = models.URLField(max_length=255, blank=True)
icq = models.IntegerField(max_length=255, null=True)
'''
def contribute_to_related_class(self, cls, related):
setattr(cls, related.get_accessor_name(), AutoSingleRelatedObjectDescriptor(related))
class JSONField(models.TextField):
"""
JSONField is a generic textfield that neatly serializes/unserializes
JSON objects seamlessly.
Django snippet #1478
example:
class Page(models.Model):
data = JSONField(blank=True, null=True)
page = Page.objects.get(pk=5)
page.data = {'title': 'test', 'type': 3}
page.save()
"""
__metaclass__ = models.SubfieldBase
def to_python(self, value):
if value == "":
return None
try:
if isinstance(value, basestring):
return json.loads(value)
except ValueError:
pass
return value
def get_db_prep_save(self, value, *args, **kwargs):
if value == "":
return None
if isinstance(value, dict):
value = json.dumps(value, cls=DjangoJSONEncoder)
return super(JSONField, self).get_db_prep_save(value, *args, **kwargs)

View File

@ -1,32 +0,0 @@
from django.shortcuts import _get_queryset
from django.conf import settings
def get_object_or_None(klass, *args, **kwargs):
"""
Uses get() to return an object or None if the object does not exist.
klass may be a Model, Manager, or QuerySet object. All other passed
arguments and keyword arguments are used in the get() query.
Note: Like with get(), a MultipleObjectsReturned will be raised if more than one
object is found.
"""
queryset = _get_queryset(klass)
try:
return queryset.get(*args, **kwargs)
except queryset.model.DoesNotExist:
return None
def get_config(key, default):
"""
Get settings from django.conf if exists,
return default value otherwise
example:
ADMIN_EMAIL = get_config('ADMIN_EMAIL', 'default@email.com')
"""
return getattr(settings, key, default)

View File

@ -1,32 +0,0 @@
import re
from django.conf import settings
from django.views.static import serve
from django.shortcuts import redirect
from .exceptions import Redirect
class StaticServe(object):
"""
Django middleware for serving static files instead of using urls.py
"""
regex = re.compile(r'^%s(?P<path>.*)$' % settings.MEDIA_URL)
def process_request(self, request):
if settings.DEBUG:
match = self.regex.search(request.path)
if match:
return serve(request, match.group(1), settings.MEDIA_ROOT)
class RedirectMiddleware(object):
"""
You must add this middleware to MIDDLEWARE_CLASSES list,
to make work Redirect exception. All arguments passed to
Redirect will be passed to django built in redirect function.
"""
def process_exception(self, request, exception):
if not isinstance(exception, Redirect):
return
return redirect(*exception.args, **exception.kwargs)

View File

@ -1,14 +0,0 @@
import django
from django import template
from smart_if import smart_if
register = template.Library()
try:
if int(django.get_version()[-5:]) < 11806:
register.tag('if', smart_if)
except ValueError:
pass

View File

@ -1,240 +0,0 @@
from django import template
__author__ = "SmileyChris"
#==============================================================================
# Calculation objects
#==============================================================================
class BaseCalc(object):
def __init__(self, var1, var2=None, negate=False):
self.var1 = var1
self.var2 = var2
self.negate = negate
def resolve(self, context):
try:
var1, var2 = self.resolve_vars(context)
outcome = self.calculate(var1, var2)
except:
outcome = False
if self.negate:
return not outcome
return outcome
def resolve_vars(self, context):
var2 = self.var2 and self.var2.resolve(context)
return self.var1.resolve(context), var2
def calculate(self, var1, var2):
raise NotImplementedError()
class Or(BaseCalc):
def calculate(self, var1, var2):
return var1 or var2
class And(BaseCalc):
def calculate(self, var1, var2):
return var1 and var2
class Equals(BaseCalc):
def calculate(self, var1, var2):
return var1 == var2
class Greater(BaseCalc):
def calculate(self, var1, var2):
return var1 > var2
class GreaterOrEqual(BaseCalc):
def calculate(self, var1, var2):
return var1 >= var2
class In(BaseCalc):
def calculate(self, var1, var2):
return var1 in var2
OPERATORS = {
'=': (Equals, True),
'==': (Equals, True),
'!=': (Equals, False),
'>': (Greater, True),
'>=': (GreaterOrEqual, True),
'<=': (Greater, False),
'<': (GreaterOrEqual, False),
'or': (Or, True),
'and': (And, True),
'in': (In, True),
}
BOOL_OPERATORS = ('or', 'and')
class IfParser(object):
error_class = ValueError
def __init__(self, tokens):
self.tokens = tokens
def _get_tokens(self):
return self._tokens
def _set_tokens(self, tokens):
self._tokens = tokens
self.len = len(tokens)
self.pos = 0
tokens = property(_get_tokens, _set_tokens)
def parse(self):
if self.at_end():
raise self.error_class('No variables provided.')
var1 = self.get_bool_var()
while not self.at_end():
op, negate = self.get_operator()
var2 = self.get_bool_var()
var1 = op(var1, var2, negate=negate)
return var1
def get_token(self, eof_message=None, lookahead=False):
negate = True
token = None
pos = self.pos
while token is None or token == 'not':
if pos >= self.len:
if eof_message is None:
raise self.error_class()
raise self.error_class(eof_message)
token = self.tokens[pos]
negate = not negate
pos += 1
if not lookahead:
self.pos = pos
return token, negate
def at_end(self):
return self.pos >= self.len
def create_var(self, value):
return TestVar(value)
def get_bool_var(self):
"""
Returns either a variable by itself or a non-boolean operation (such as
``x == 0`` or ``x < 0``).
This is needed to keep correct precedence for boolean operations (i.e.
``x or x == 0`` should be ``x or (x == 0)``, not ``(x or x) == 0``).
"""
var = self.get_var()
if not self.at_end():
op_token = self.get_token(lookahead=True)[0]
if isinstance(op_token, basestring) and (op_token not in
BOOL_OPERATORS):
op, negate = self.get_operator()
return op(var, self.get_var(), negate=negate)
return var
def get_var(self):
token, negate = self.get_token('Reached end of statement, still '
'expecting a variable.')
if isinstance(token, basestring) and token in OPERATORS:
raise self.error_class('Expected variable, got operator (%s).' %
token)
var = self.create_var(token)
if negate:
return Or(var, negate=True)
return var
def get_operator(self):
token, negate = self.get_token('Reached end of statement, still '
'expecting an operator.')
if not isinstance(token, basestring) or token not in OPERATORS:
raise self.error_class('%s is not a valid operator.' % token)
if self.at_end():
raise self.error_class('No variable provided after "%s".' % token)
op, true = OPERATORS[token]
if not true:
negate = not negate
return op, negate
#==============================================================================
# Actual templatetag code.
#==============================================================================
class TemplateIfParser(IfParser):
error_class = template.TemplateSyntaxError
def __init__(self, parser, *args, **kwargs):
self.template_parser = parser
return super(TemplateIfParser, self).__init__(*args, **kwargs)
def create_var(self, value):
return self.template_parser.compile_filter(value)
class SmartIfNode(template.Node):
def __init__(self, var, nodelist_true, nodelist_false=None):
self.nodelist_true, self.nodelist_false = nodelist_true, nodelist_false
self.var = var
def render(self, context):
if self.var.resolve(context):
return self.nodelist_true.render(context)
if self.nodelist_false:
return self.nodelist_false.render(context)
return ''
def __repr__(self):
return "<Smart If node>"
def __iter__(self):
for node in self.nodelist_true:
yield node
if self.nodelist_false:
for node in self.nodelist_false:
yield node
def get_nodes_by_type(self, nodetype):
nodes = []
if isinstance(self, nodetype):
nodes.append(self)
nodes.extend(self.nodelist_true.get_nodes_by_type(nodetype))
if self.nodelist_false:
nodes.extend(self.nodelist_false.get_nodes_by_type(nodetype))
return nodes
def smart_if(parser, token):
"""
A smarter {% if %} tag for django templates.
While retaining current Django functionality, it also handles equality,
greater than and less than operators. Some common case examples::
{% if articles|length >= 5 %}...{% endif %}
{% if "ifnotequal tag" != "beautiful" %}...{% endif %}
Arguments and operators _must_ have a space between them, so
``{% if 1>2 %}`` is not a valid smart if tag.
All supported operators are: ``or``, ``and``, ``in``, ``=`` (or ``==``),
``!=``, ``>``, ``>=``, ``<`` and ``<=``.
"""
bits = token.split_contents()[1:]
var = TemplateIfParser(parser, bits).parse()
nodelist_true = parser.parse(('else', 'endif'))
token = parser.next_token()
if token.contents == 'else':
nodelist_false = parser.parse(('endif',))
parser.delete_first_token()
else:
nodelist_false = None
return SmartIfNode(var, nodelist_true, nodelist_false)

View File

@ -1,26 +0,0 @@
from django.http import HttpResponse
from django.utils.encoding import iri_to_uri
class HttpResponseReload(HttpResponse):
"""
Reload page and stay on the same page from where request was made.
example:
def simple_view(request):
if request.POST:
form = CommentForm(request.POST):
if form.is_valid():
form.save()
return HttpResponseReload(request)
else:
form = CommentForm()
return render_to_response('some_template.html', {'form': form})
"""
status_code = 302
def __init__(self, request):
HttpResponse.__init__(self)
referer = request.META.get('HTTP_REFERER')
self['Location'] = iri_to_uri(referer or "/")

View File

@ -4,8 +4,11 @@ from __future__ import print_function
import re
import sys
import distutils
from distutils import core, log
from distutils import log
try:
from setuptools import setup, Command
except ImportError:
from distutils.core import setup, Command
from glob import glob
import os
@ -21,27 +24,29 @@ cwd = os.getcwd()
try:
from portage.const import EPREFIX
except ImportError:
EPREFIX=''
EPREFIX = ''
# Python files that need `__version__ = ""` subbed, relative to this dir:
python_scripts = [os.path.join(cwd, path) for path in (
'bin/euscan',
)]
class set_version(core.Command):
class set_version(Command):
"""Set python __version__ to our __version__."""
description = "hardcode scripts' version using VERSION from environment"
user_options = [] # [(long_name, short_name, desc),]
def initialize_options (self):
def initialize_options(self):
pass
def finalize_options (self):
def finalize_options(self):
pass
def run(self):
ver = 'git' if __version__ == '9999' else __version__
print("Settings version to %s" % ver)
def sub(files, pattern):
for f in files:
updated_file = []
@ -63,7 +68,7 @@ packages = [
if '__init__.py' in files
]
core.setup(
setup(
name='euscan',
version=__version__,
description='Ebuild upstream scan utility.',
@ -72,16 +77,21 @@ core.setup(
maintainer='Corentin Chary',
maintainer_email='corentin.chary@gmail.com',
url='http://euscan.iksaif.net',
download_url='https://github.com/iksaif/euscan/tarball/' + ('master' if __version__ == '9999' else ('euscan-%s' % __version__)),
download_url=(
'https://github.com/iksaif/euscan/tarball/' +
('master' if __version__ == '9999' else ('euscan-%s' % __version__))
),
install_requires=['Django==1.3.1', 'django-annoying', 'South',
'django-piston', 'matplotlib'],
package_dir={'': 'pym'},
packages=packages,
package_data = {},
package_data={},
scripts=python_scripts,
data_files=(
(os.path.join(os.sep, EPREFIX.lstrip(os.sep), 'usr/share/man/man1'), glob('man/*')),
(os.path.join(os.sep, EPREFIX.lstrip(os.sep), 'usr/share/man/man1'),
glob('man/*')),
),
cmdclass={
'set_version': set_version,
},
)