=== added directory 'lava'
=== added file 'lava/__init__.py'
@@ -0,0 +1,3 @@
+__import__('pkg_resources').declare_namespace(__name__)
+# DO NOT ADD ANYTHING TO THIS FILE!
+# IT MUST STAY AS IS (empty apart from the two lines above)
=== added directory 'lava/utils'
=== added file 'lava/utils/__init__.py'
@@ -0,0 +1,3 @@
+__import__('pkg_resources').declare_namespace(__name__)
+# DO NOT ADD ANYTHING TO THIS FILE!
+# IT MUST STAY AS IS (empty apart from the two lines above)
=== added directory 'lava/utils/data_tables'
=== added file 'lava/utils/data_tables/__init__.py'
=== added file 'lava/utils/data_tables/backends.py'
@@ -0,0 +1,72 @@
+# Copyright (C) 2012 Linaro Limited
+#
+# Author: Zygmunt Krynicki <zygmunt.krynicki@linaro.org>
+#
+# This file is part of LAVA Server.
+#
+# LAVA Server is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# as published by the Free Software Foundation
+#
+# LAVA Server is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with LAVA Server. If not, see <http://www.gnu.org/licenses/>.
+
+from django.core.exceptions import ImproperlyConfigured
+
+from lava.utils.data_tables.interface import IBackend
+
+
+class _BackendBase(IBackend):
+ """
+ Common code for data backends to data tables
+ """
+
+ def process(self, query):
+ return {
+ 'sEcho': query.sEcho,
+ 'sColumns': query.sColumns
+ }
+
+
+class ArrayBackend(_BackendBase):
+ """
+ Array backend to data tables
+
+ Stores all data in a plain python list. All filtering is handled in the
+ running process. It is suitable for very small data sets only but has the
+ advantage of being unrelated to any databases.
+ """
+
+ def __init__(self, data):
+ self.data = data
+
+ def process(self, query):
+ # Get the basic response structure
+ response = super(ArrayBackend, self).process(query)
+ # 0) Copy original data
+ # TODO: add support for lazy copy (only if really needed)
+ data = list(self.data)
+ response['iTotalRecords'] = len(data)
+ # 1) Apply search/filtering
+ if query.sSearch:
+ if query.bRegex:
+ raise NotImplementedError("Searching with regular expresions is not implemented")
+ else:
+ data = [row for row in data if any((query.sSearch in unicode(cell) for cell in row))]
+ # Remember how many records matched filtering
+ response['iTotalDisplayRecords'] = len(data)
+ # TODO: Support regex search
+ # TODO: Support per-column search
+ # 2) Apply sorting
+ for column_index, order in reversed(euery.sorting_columns):
+ data.sort(key=lambda row: row[column_index], reverse=order == 'desc')
+ # 3) Apply offset/limit
+ data = data[query.iDisplayStart:query.iDisplayStart + query.iDisplayLength]
+ # Remember the subset of the displayed data
+ response['aaData'] = data
+ return response
=== added file 'lava/utils/data_tables/interface.py'
@@ -0,0 +1,34 @@
+# Copyright (C) 2012 Linaro Limited
+#
+# Author: Zygmunt Krynicki <zygmunt.krynicki@linaro.org>
+#
+# This file is part of LAVA Server.
+#
+# LAVA Server is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# as published by the Free Software Foundation
+#
+# LAVA Server is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with LAVA Server. If not, see <http://www.gnu.org/licenses/>.
+
+from lava.utils.interface import Interface, abstractmethod
+
+
+class IBackend(Interface):
+ """
+ Interface for data-store-and-compute backends to data-tables.
+ """
+
+ @abstractmethod
+ def process(self, query):
+ """
+ Process data query.
+
+ Process the query and return a JSON response object compatible with
+ data tables.
+ """
=== added file 'lava/utils/data_tables/query.py'
@@ -0,0 +1,67 @@
+# Copyright (C) 2012 Linaro Limited
+#
+# Author: Zygmunt Krynicki <zygmunt.krynicki@linaro.org>
+#
+# This file is part of LAVA Server.
+#
+# LAVA Server is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# as published by the Free Software Foundation
+#
+# LAVA Server is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with LAVA Server. If not, see <http://www.gnu.org/licenses/>.
+
+
+class DataTableQuery(object):
+ """
+ Query to data table server backend
+ """
+
+ DEFAULT_DISPLAY_LENGTH = 10
+
+ def __init__(self, request):
+ # Store the request object
+ self.request = request
+
+ # Number of columns
+ self.iColumns = int(request.GET.get('iColumns', 0))
+ self.sColumns = request.GET.get('sColumns', '')
+
+ # Echo data (seems to be cache poison, needs follow up checks)
+ self.sEcho = request.GET.get('sEcho', 0)
+
+ # Some unspecified value
+ # XXX: What is this for?
+ self._ = request.GET.get('_', '')
+
+ # Data window parameters
+ self.iDisplayStart = int(request.GET.get('iDisplayStart', 0))
+ self.iDisplayLength = int(request.GET.get('iDisplayLength', self.DEFAULT_DISPLAY_LENGTH))
+
+ # Sorting/ordering parameters
+ self.sorting_columns = []
+ self.iSortingCols = int(request.GET.get('iSortingCols', 0))
+ for i in range(self.iSortingCols):
+ column_index = int(request.GET.get('iSortCol_{0}'.format(i), 0))
+ sortable = request.GET.get('bSortable_{0}'.format(i), 'false') == 'true'
+ if sortable:
+ sorting_direction = request.GET.get('sSortDir_{0}'.format(i), 'asc')
+ self.sorting_columns.append((column_index, sorting_direction))
+
+ # Global search parameters
+ self.sSearch = request.GET.get('sSearch', '')
+ self.bRegex = request.GET.get('bRegex', 'false') == 'true'
+
+ # Per-column search parameters
+ self.search_columns = []
+ for i in range(self.iColumns):
+ searchable = request.GET.get('bSearchable_{0}'.format(i), 'false') == 'true'
+ if searchable:
+ regex = request.GET.get('bRegex_{0}'.format(i), 'false') == 'true'
+ term = request.GET.get('sSearch_{0}'.format(i), '')
+ self.search_columns.append((i, regex, term))
=== added file 'lava/utils/data_tables/views.py'
@@ -0,0 +1,42 @@
+# Copyright (C) 2012 Linaro Limited
+#
+# Author: Zygmunt Krynicki <zygmunt.krynicki@linaro.org>
+#
+# This file is part of LAVA Server.
+#
+# LAVA Server is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# as published by the Free Software Foundation
+#
+# LAVA Server is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with LAVA Server. If not, see <http://www.gnu.org/licenses/>.
+
+from django.core.exceptions import ImproperlyConfigured
+from django.http import HttpResponse
+from django.utils import simplejson
+from django.views.generic import View
+
+from lava.utils.data_tables.query import DataTableQuery
+
+
+class DataTableView(View):
+ """
+ View for processing data table requests
+ """
+
+ backend = None
+
+ def get(self, request, *args, **kwargs):
+ if self.backend is None:
+ raise ImproperlyConfigured(
+ "DataTableView requires a definition of a backend")
+ query = DataTableQuery(request)
+ result = self.backend.process(query)
+ return HttpResponse(
+ simplejson.dumps(result),
+ mimetype='application/json')
=== added directory 'lava/utils/interface'
=== added file 'lava/utils/interface/__init__.py'
@@ -0,0 +1,27 @@
+# Copyright (C) 2012 Linaro Limited
+#
+# Author: Zygmunt Krynicki <zygmunt.krynicki@linaro.org>
+#
+# This file is part of LAVA Server.
+#
+# LAVA Server is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# as published by the Free Software Foundation
+#
+# LAVA Server is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with LAVA Server. If not, see <http://www.gnu.org/licenses/>.
+
+from abc import ABCMeta, abstractmethod
+
+
+class Interface(object):
+ """
+ Interface class
+ """
+
+ __metaclass__ = ABCMeta
=== modified file 'setup.py'
@@ -26,6 +26,7 @@
version=":versiontools:lava_server:__version__",
author="Zygmunt Krynicki",
author_email="zygmunt.krynicki@linaro.org",
+ namespace_packages=['lava', 'lava.utils'],
packages=find_packages(),
entry_points="""
[console_scripts]
@@ -57,7 +58,7 @@
"Topic :: Software Development :: Testing",
],
install_requires=[
- 'django >= 1.2',
+ 'django >= 1.3',
'django-debian >= 0.10',
'django-openid-auth >= 0.2',
'django-restricted-resource >= 0.2.6',