euscanwww: add basic json/xml API
Signed-off-by: Corentin Chary <corentincj@iksaif.net>
This commit is contained in:
		
							
								
								
									
										0
									
								
								euscanwww/api/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								euscanwww/api/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										171
									
								
								euscanwww/api/handlers.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										171
									
								
								euscanwww/api/handlers.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,171 @@
 | 
			
		||||
from piston.handler import AnonymousBaseHandler, BaseHandler
 | 
			
		||||
from piston.utils import rc, HttpStatusCode
 | 
			
		||||
 | 
			
		||||
from django.db.models import Sum, Max
 | 
			
		||||
from django.shortcuts import get_object_or_404
 | 
			
		||||
from django.forms.models import model_to_dict
 | 
			
		||||
 | 
			
		||||
from euscan.models import Version, Package, Herd, Maintainer, EuscanResult, VersionLog
 | 
			
		||||
from euscan.forms import WorldForm, PackagesForm
 | 
			
		||||
 | 
			
		||||
def xint(i):
 | 
			
		||||
    try:
 | 
			
		||||
        return int(i)
 | 
			
		||||
    except:
 | 
			
		||||
        return 0
 | 
			
		||||
 | 
			
		||||
def renameFields(vqs, fields):
 | 
			
		||||
    ret = []
 | 
			
		||||
    for n in vqs:
 | 
			
		||||
        for tr in fields:
 | 
			
		||||
            if tr[0] in n:
 | 
			
		||||
                n[tr[1]] = n[tr[0]]
 | 
			
		||||
                del n[tr[0]]
 | 
			
		||||
        ret.append(n)
 | 
			
		||||
    return ret
 | 
			
		||||
 | 
			
		||||
# /api/1.0/
 | 
			
		||||
class RootHandler(AnonymousBaseHandler):
 | 
			
		||||
    allowed_methods = ('GET',)
 | 
			
		||||
 | 
			
		||||
    def read(self, request):
 | 
			
		||||
        return {'api-version': '1.0'}
 | 
			
		||||
 | 
			
		||||
# /api/1.0/statistics
 | 
			
		||||
class StatisticsHandler(AnonymousBaseHandler):
 | 
			
		||||
    allowed_methods = ('GET',)
 | 
			
		||||
 | 
			
		||||
    def read(self, request):
 | 
			
		||||
        print request
 | 
			
		||||
        data = {}
 | 
			
		||||
        data['n_packaged'] = xint(Package.objects.aggregate(Sum('n_packaged'))['n_packaged__sum'])
 | 
			
		||||
        data['n_overlay'] = xint(Package.objects.aggregate(Sum('n_overlay'))['n_overlay__sum'])
 | 
			
		||||
        data['n_versions'] = xint(Package.objects.aggregate(Sum('n_versions'))['n_versions__sum'])
 | 
			
		||||
        data['n_upstream'] = data['n_versions'] - data['n_packaged'] - data['n_overlay']
 | 
			
		||||
        data['n_packages'] = Package.objects.count()
 | 
			
		||||
        data['n_herds'] = Herd.objects.count()
 | 
			
		||||
        data['n_maintainers'] = Maintainer.objects.count()
 | 
			
		||||
        data['last_scan'] = EuscanResult.objects.get(id=EuscanResult.objects.aggregate(Max('id'))['id__max']).datetime
 | 
			
		||||
 | 
			
		||||
        return data
 | 
			
		||||
 | 
			
		||||
# /api/1.0/maintainers
 | 
			
		||||
class MaintainersHandler(AnonymousBaseHandler):
 | 
			
		||||
    allowed_methods = ('GET',)
 | 
			
		||||
 | 
			
		||||
    def read(self, request):
 | 
			
		||||
        maintainers = Package.objects.filter(maintainers__isnull=False)
 | 
			
		||||
        maintainers = maintainers.values('maintainers__id', 'maintainers__name', 'maintainers__email')
 | 
			
		||||
        maintainers = maintainers.annotate(n_packaged=Sum('n_packaged'),
 | 
			
		||||
                                           n_overlay=Sum('n_overlay'),
 | 
			
		||||
                                           n_versions=Sum('n_versions'))
 | 
			
		||||
 | 
			
		||||
        maintainers = renameFields(maintainers, [('maintainers__id', 'id'),
 | 
			
		||||
                                                 ('maintainers__name', 'name'),
 | 
			
		||||
                                                 ('maintainers__email', 'email')])
 | 
			
		||||
        return maintainers
 | 
			
		||||
 | 
			
		||||
# /api/1.0/herds
 | 
			
		||||
class HerdsHandler(AnonymousBaseHandler):
 | 
			
		||||
    allowed_methods = ('GET',)
 | 
			
		||||
 | 
			
		||||
    def read(self, request):
 | 
			
		||||
        # FIXME: optimize the query, it uses 'LEFT OUTER JOIN' instead of 'INNER JOIN'
 | 
			
		||||
        herds = Package.objects.filter(herds__isnull=False)
 | 
			
		||||
        herds = herds.values('herds__herd').annotate(n_packaged=Sum('n_packaged'),
 | 
			
		||||
                                                     n_overlay=Sum('n_overlay'),
 | 
			
		||||
                                                     n_versions=Sum('n_versions'))
 | 
			
		||||
 | 
			
		||||
        herds = renameFields(herds, [('herds__herd', 'herd')])
 | 
			
		||||
        return herds
 | 
			
		||||
 | 
			
		||||
# /api/1.0/categories
 | 
			
		||||
class CategoriesHandler(AnonymousBaseHandler):
 | 
			
		||||
    allowed_methods = ('GET',)
 | 
			
		||||
 | 
			
		||||
    def read(self, request):
 | 
			
		||||
        categories = Package.objects.values('category')
 | 
			
		||||
        categories = categories.annotate(n_packaged=Sum('n_packaged'),
 | 
			
		||||
                                         n_overlay=Sum('n_overlay'),
 | 
			
		||||
                                         n_versions=Sum('n_versions'))
 | 
			
		||||
 | 
			
		||||
        return { 'categories' : categories }
 | 
			
		||||
 | 
			
		||||
# /api/1.0/packages/by-maintainer/
 | 
			
		||||
# /api/1.0/packages/by-category/
 | 
			
		||||
# /api/1.0/packages/by-herd/
 | 
			
		||||
class PackagesHandler(AnonymousBaseHandler):
 | 
			
		||||
    allowed_methods = ('GET',)
 | 
			
		||||
    fields = ('category', 'name', 'n_packaged', 'n_overlay', 'n_versions')
 | 
			
		||||
    model = Package
 | 
			
		||||
 | 
			
		||||
    def read(self, request, **kwargs):
 | 
			
		||||
        data = {}
 | 
			
		||||
 | 
			
		||||
        if 'category' in kwargs:
 | 
			
		||||
            packages = Package.objects.filter(category=kwargs['category'])
 | 
			
		||||
            data = { 'category' : kwargs['category'], 'packages' : packages }
 | 
			
		||||
        elif 'herd' in kwargs:
 | 
			
		||||
            herd = get_object_or_404(Herd, herd=kwargs['herd'])
 | 
			
		||||
            packages = Package.objects.filter(herds__id=herd.id)
 | 
			
		||||
            data = { 'herd' : herd, 'packages' : packages }
 | 
			
		||||
        elif 'maintainer' in kwargs:
 | 
			
		||||
            maintainer = get_object_or_404(Maintainer, id=kwargs['maintainer'])
 | 
			
		||||
            packages = Package.objects.filter(maintainers__id=maintainer.id)
 | 
			
		||||
            data = { 'maintainer' : maintainer, 'packages' : packages }
 | 
			
		||||
 | 
			
		||||
        return data
 | 
			
		||||
 | 
			
		||||
# /api/1.0/package/
 | 
			
		||||
class PackageHandler(AnonymousBaseHandler):
 | 
			
		||||
    allowed_methods = ('GET',)
 | 
			
		||||
 | 
			
		||||
    def read(self, request, category, package):
 | 
			
		||||
        package = get_object_or_404(Package, category=category, name=package)
 | 
			
		||||
        package.homepages = package.homepage.split(' ')
 | 
			
		||||
        versions = Version.objects.filter(package=package)
 | 
			
		||||
        log = EuscanResult.objects.filter(package=package).order_by('-datetime')[:1]
 | 
			
		||||
        log = log[0] if log else None
 | 
			
		||||
        vlog = VersionLog.objects.filter(package=package).order_by('-id')
 | 
			
		||||
 | 
			
		||||
        herds = []
 | 
			
		||||
        for herd in package.herds.all():
 | 
			
		||||
            print herd
 | 
			
		||||
            herds.append(model_to_dict(herd, ['herd']))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        maintainers = []
 | 
			
		||||
        for maintainer in package.maintainers.all():
 | 
			
		||||
            maintainers.append(model_to_dict(maintainer, ['name', 'email']))
 | 
			
		||||
 | 
			
		||||
        version_log = []
 | 
			
		||||
        for v in vlog:
 | 
			
		||||
            v = model_to_dict(v, ['version', 'revision', 'slot', 'overlay', 'datetime', 'action'])
 | 
			
		||||
            if v['action'] == VersionLog.VERSION_ADDED:
 | 
			
		||||
                v['action'] = 'added'
 | 
			
		||||
            if v['action'] == VersionLog.VERSION_REMOVED:
 | 
			
		||||
                v['action'] = 'removed'
 | 
			
		||||
            version_log.append(v)
 | 
			
		||||
 | 
			
		||||
        upstream = []
 | 
			
		||||
        packaged = []
 | 
			
		||||
        for version in versions:
 | 
			
		||||
            unpackaged = not version.packaged
 | 
			
		||||
            version = model_to_dict(version, ['version', 'revision', 'slot', 'overlay', 'urls'])
 | 
			
		||||
            if unpackaged:
 | 
			
		||||
                upstream.append(version)
 | 
			
		||||
            else:
 | 
			
		||||
                packaged.append(version)
 | 
			
		||||
 | 
			
		||||
        package = model_to_dict(package, ['category', 'name', 'description',
 | 
			
		||||
                                          'homepage'])
 | 
			
		||||
        package['herds'] = herds
 | 
			
		||||
        package['maintainers'] = maintainers
 | 
			
		||||
        package['packaged'] = packaged
 | 
			
		||||
        package['upstream'] = upstream
 | 
			
		||||
        package['vlog'] = version_log
 | 
			
		||||
        if log:
 | 
			
		||||
            package['log'] = model_to_dict(log, ['result', 'datetime'])
 | 
			
		||||
 | 
			
		||||
        return package
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										26
									
								
								euscanwww/api/urls.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								euscanwww/api/urls.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,26 @@
 | 
			
		||||
from django.conf.urls.defaults import *
 | 
			
		||||
 | 
			
		||||
from piston.resource import Resource
 | 
			
		||||
from api.handlers import *
 | 
			
		||||
 | 
			
		||||
root_handler = Resource(handler=RootHandler)
 | 
			
		||||
statistics_handler = Resource(handler=StatisticsHandler)
 | 
			
		||||
herds_handler = Resource(handler=HerdsHandler)
 | 
			
		||||
categories_handler = Resource(handler=CategoriesHandler)
 | 
			
		||||
maintainers_handler = Resource(handler=MaintainersHandler)
 | 
			
		||||
packages_handler = Resource(handler=PackagesHandler)
 | 
			
		||||
package_handler = Resource(handler=PackageHandler)
 | 
			
		||||
 | 
			
		||||
urlpatterns = patterns('api.views',
 | 
			
		||||
    (r'^1.0/statistics\.(?P<emitter_format>.+)$', statistics_handler),
 | 
			
		||||
    (r'^1.0/herds\.(?P<emitter_format>.+)$', herds_handler),
 | 
			
		||||
    (r'^1.0/categories\.(?P<emitter_format>.+)$', categories_handler),
 | 
			
		||||
    (r'^1.0/maintainers\.(?P<emitter_format>.+)$', maintainers_handler),
 | 
			
		||||
 | 
			
		||||
    (r'^1.0/packages/by-maintainer/(?P<maintainer_id>\d+)\.(?P<emitter_format>.+)$', packages_handler),
 | 
			
		||||
    (r'^1.0/packages/by-herd/(?P<herd>[\@\{\}\w+.-]*)\.(?P<emitter_format>.+)?$', packages_handler),
 | 
			
		||||
    (r'^1.0/packages/by-category/(?P<category>[\w+][\w+.-]*)\.(?P<emitter_format>.+)?$', packages_handler),
 | 
			
		||||
    (r'^1.0/package/(?P<category>[\w+][\w+.-]*)/(?P<package>[\w+][\w+.-]*)\.(?P<emitter_format>.+)$', package_handler),
 | 
			
		||||
 | 
			
		||||
    (r'^1.0/api\.(?P<emitter_format>.+)$', root_handler),
 | 
			
		||||
)
 | 
			
		||||
		Reference in New Issue
	
	Block a user