Commit 6a41685d authored by LE GAC Renaud's avatar LE GAC Renaud
Browse files

Merge branch '10-pylint-jslint' into 'master'

10 apply pylint and jslint rules

* Close #10

See merge request !9
parents b1d537f3 2326dbe3
......@@ -7,23 +7,27 @@ from gluon import current
from plugin_dbui import CALLBACK_ERRORS, get_where_query
def INHIBIT_CASCADE_DELETE(set):
MSG_INHIBIT_DELETE = \
"Can't delete this record since several transactions refer to it."
def INHIBIT_CASCADE_DELETE(myset):
"""Inhibit the delete when at least one history row uses
the reference field.
@type set: gluon.dal.Set
@param set:
@type myset: gluon.dal.Set
@param myset:
@rtype: bool
@return:
"""
db, T = current.globalenv['db'], current.T
field = set.query.first
field = myset.query.first
# protection
# the query of the set should be "table.id == 45"
if field._db._adapter.EQ != set.query.op:
if field._db._adapter.EQ != myset.query.op:
return False
# protection
......@@ -40,11 +44,10 @@ def INHIBIT_CASCADE_DELETE(set):
# inhibit the delete if at least one history row use the reference field
query = get_where_query(db.history)
query = (query) & (set.query)
query = (query) & (myset.query)
if db(query).count():
field._table[CALLBACK_ERRORS] = \
T("Can't delete this record since several transactions refer to it.")
field._table[CALLBACK_ERRORS] = T(MSG_INHIBIT_DELETE)
return True
return False
\ No newline at end of file
return False
......@@ -11,7 +11,6 @@ class IS_IN_USET(IS_IN_SET):
"""IS_IN_SET validator but working with unicode string.
"""
def __init__(self, theset, **kwargs):
myset = []
......@@ -32,7 +31,6 @@ class IS_IN_USET(IS_IN_SET):
IS_IN_SET.__init__(self, myset, **kwargs)
def __call__(self, value):
if isinstance(value, unicode):
......
......@@ -3,17 +3,17 @@
"""
import json
import matplotlib
import pandas as pd
import re
from datetime import date, timedelta
from gluon import current
from gluon.dal import Field, FieldVirtual, smart_query
from gluon.dal import FieldVirtual, smart_query
from gluon.storage import Storage
from pandas import DataFrame, MultiIndex, to_datetime
from plugin_dbui import get_id, Store
from StringIO import StringIO
MSG_NO_DATAINDEX = "The property dataIndex is required when eval is used."
MSG_NO_XTYPE = "The property xtype is missing."
......@@ -132,7 +132,8 @@ def split_dbfield(value):
return tuple(li)
class ReportException(BaseException): pass
class ReportException(BaseException):
pass
class BaseReport(object):
......@@ -178,7 +179,6 @@ class BaseReport(object):
q_conditions = smart_query(db.history, config.conditions)
selector.append_query(q_conditions)
def _do_data(self, maps):
"""Build a temporarily list with the raw data for each series.
This method handle the "year" database field.
......@@ -192,7 +192,6 @@ class BaseReport(object):
"""
data = []
config = self.config
db = self.db
selector = self.selector
......@@ -219,18 +218,17 @@ class BaseReport(object):
selector.set_year(year)
for row in db(query(db.history)).select(*dbfields):
values = [get_value(row, *map, year=year) for map in maps]
values = [get_value(row, *elt, year=year) for elt in maps]
data.append(values)
# standard scan
else:
for row in db(query(db.history)).select(*dbfields):
values = [get_value(row, *map) for map in maps]
values = [get_value(row, *elt) for elt in maps]
data.append(values)
return data
def _is_year(self, maps):
"""
@type maps: list
......@@ -244,7 +242,6 @@ class BaseReport(object):
li = [True for el in maps if el[0] == 'year']
return (True if li else False)
def to_df(self):
"""Return the pandas DataFrame.
......@@ -298,7 +295,7 @@ class Graph(BaseReport):
report_id = get_id(db[report_type], name=report_name)
report_config = db[report_type][report_id]
if report_type == "lists":
if report_type == "lists":
report = List(report_config, selector)
elif report_type == "metrics1d":
......@@ -315,7 +312,6 @@ class Graph(BaseReport):
self._do_legend()
self._do_tick()
def _do_graph(self):
"""Build the graph from the C{DataFrame} structure.
......@@ -330,16 +326,15 @@ class Graph(BaseReport):
# generate the plot using a specific set of columns
if steer.index and len(steer.index) <= len(df.columns):
ax = df.ix[:,steer.index].plot(**plot)
ax = df.ix[:, steer.index].plot(**plot)
# generate the plot using all columns
else:
ax = df.ix[:,:].plot(**plot)
ax = df.ix[:, :].plot(**plot)
# persistence
self.ax = ax
def _do_labels(self):
"""Deal with axes label.
......@@ -353,7 +348,6 @@ class Graph(BaseReport):
if steer.ylabel:
ax.set_ylabel(steer.ylabel, y=1, horizontalalignment='right')
def _do_legend(self):
"""Deal with legend.
......@@ -368,7 +362,6 @@ class Graph(BaseReport):
fontsize=10,
ncol=3)
def _do_tick(self):
"""Polish the tick mark
......@@ -379,18 +372,17 @@ class Graph(BaseReport):
ax.tick_params(which='major', length=8)
ax.tick_params(which='minor', length=4)
def _savefig(self, format):
def _savefig(self, fmt):
"""Save the figure as a string.
@type format: str
@param format: possible values are pdf, png and svg.
@type fmt: str
@param fmt: possible values are pdf, png and svg.
"""
fig = self.ax.get_figure()
fi = StringIO()
fig.savefig(fi, format=format)
fig.savefig(fi, format=fmt)
data = fi.getvalue()
fi.close()
......@@ -399,7 +391,6 @@ class Graph(BaseReport):
return data
def to_pdf(self):
"""
@rtype: string
......@@ -416,7 +407,6 @@ class Graph(BaseReport):
"""
return self._savefig('png')
def to_svg(self):
"""
@rtype: string
......@@ -459,8 +449,7 @@ class List(BaseReport):
# instantiate and fill the DataFrame
self._do_metric()
def _cast_type(self, column, map, xtype):
def _cast_type(self, column, dbfield, xtype):
"""Cast the type of a dataframe column to the database field type
or to the grid column xtype.
......@@ -476,8 +465,8 @@ class List(BaseReport):
@type column: str
@param column: the index of the column in the DataFrame
@type map: tuple
@param map: address of the database field encoded as
@type dbfield: tuple
@param dbfield: address of the database field encoded as
(tablename, fieldname, keyname).
@type xtype: str
......@@ -487,7 +476,7 @@ class List(BaseReport):
"""
df = self.df
tablename, fieldname, keyname = map
tablename, fieldname = dbfield[0:2]
# the dtype of column containing a mixture of type is object.
if (tablename == 'year') or (df[column].dtype != 'object'):
......@@ -503,7 +492,7 @@ class List(BaseReport):
df[column] = df[column].astype('bool')
elif dbtype in ('date', 'datetime', 'time'):
df[column] = pd.to_datetime(df[column])
df[column] = to_datetime(df[column])
elif dbtype in ('double', 'integer'):
df[column] = df[column].astype('float64')
......@@ -520,12 +509,11 @@ class List(BaseReport):
df[column] = df[column].astype('bool')
elif xtype == 'datecolumn':
df[column] = pd.to_datetime(df[column])
df[column] = to_datetime(df[column])
elif xtype == 'numbercolumn':
df[column] = df[column].astype('float64')
def _check_column(self, column):
"""Check column configuration:
......@@ -554,7 +542,6 @@ class List(BaseReport):
if not (column.dataIndex or xtype == "rownumberer"):
column.dataIndex = column.dbfield.replace('.', '')
def _do_metric(self):
"""Interface the database with the DataFrame structure.
This method handle the "year" database field.
......@@ -576,11 +563,11 @@ class List(BaseReport):
# protection
if not data:
self.df = pd.DataFrame(columns=index)
self.df = DataFrame(columns=index)
return
# fill the DataFrame
df = pd.DataFrame(data, columns=index)
df = DataFrame(data, columns=index)
# make the data frame persistent
self.df = df
......@@ -598,7 +585,6 @@ class List(BaseReport):
index = [el.dataIndex for el in columns if el.dataIndex]
df = df[index]
def _set_store_data(self):
""" Generate the C{Ext.data.Store.data} property.
It is a list of dictionaries. Each of them contains the data
......@@ -613,7 +599,6 @@ class List(BaseReport):
# convert the JSON-string into a list
self._store.data = json.loads(data)
def _set_store_fields(self):
""" Generate the C{Ext.data.Store.fields} property.
It is a list of C{Ext.data.Field} configuration.
......@@ -641,7 +626,7 @@ class List(BaseReport):
# the pseudo field year
if el.dbfield == 'year':
cfg.type ='int'
cfg.type = 'int'
# the computed column
elif el.eval:
......@@ -686,7 +671,6 @@ class List(BaseReport):
store.fields.append(cfg)
def to_grid(self):
"""Build the configuration of the C{App.grid.Panel}.
......@@ -715,11 +699,11 @@ class List(BaseReport):
# reference to javascript function or the function itself
# are surrounded by double quoted. removed them.
grid.columns = json.dumps(grid.columns)
grid.columns = re.sub('("renderer": *)(")(\w+)(")', r'\1\3',grid.columns)
grid.columns = \
re.sub('("renderer": *)(")(\w+)(")', r'\1\3', grid.columns)
return grid
def to_store(self):
"""Build the configuration of the C{Ext.data.Store}.
......@@ -787,8 +771,8 @@ class Metric1D(List):
text_groupby = 'year'
else:
tu = split_dbfield(field_groupby)
index_groupby = field_groupby.replace('.', '')
text_groupby = (tu[2] if tu[2] else tu[1])
index_groupby = field_groupby.replace('.', '')
text_groupby = (tu[2] if tu[2] else tu[1])
# first column contains group by information
first_column = Storage(aggregate="",
......@@ -812,16 +796,11 @@ class Metric1D(List):
self._do_metric()
def _do_metric(self):
"""Compute the metric according to user specifications.
"""
db = self.db
config = self.config
columns = self._columns
field_groupby = self._field_groupby
index_groupby = self._index_groupby
# extract columns associated to database field
......@@ -846,10 +825,10 @@ class Metric1D(List):
# protection against empty data
if not data:
indexes = (el.dataIndex for el in columns)
self.df = pd.DataFrame(columns=indexes)
self.df = DataFrame(columns=indexes)
return
df = pd.DataFrame(data, columns=indexes)
df = DataFrame(data, columns=indexes)
# cast dataframe column type to database field or grid column types
self.df = df
......@@ -870,13 +849,12 @@ class Metric1D(List):
df = df[index]
# transform year MultiIndex into Index (only for year pseudo field)
if isinstance(df.index, pd.core.index.MultiIndex):
if isinstance(df.index, MultiIndex):
df.index = [el[1] for el in df.index]
# make the data frame persistent
self.df = df
def _is_year(self, maps):
"""Supersede the method of the base class.
......@@ -885,7 +863,6 @@ class Metric1D(List):
"""
return self.config.group_field == 'year'
def _set_store_data(self):
"""Generate the C{Ext.data.Store.data} property.
It is a list of dictionaries. Each of them contains the data
......@@ -902,7 +879,6 @@ class Metric1D(List):
self._store.data.extend(data)
def _set_store_fields(self):
""" Generate the Ext.data.Store.fields property.
The store contains four fields: group, count, sum_fte and avg_age
......@@ -933,7 +909,6 @@ class Metric1D(List):
store.sorters = [index_groupby]
def to_grid(self):
"""Build the configuration of the C{App.grid.Panel}.
......@@ -943,7 +918,6 @@ class Metric1D(List):
"""
columns = self._columns
index_groupby = self._index_groupby
grid = Storage(columns=[], features=[])
......@@ -966,7 +940,6 @@ class Metric1D(List):
return grid
def to_store(self):
"""Build the configuration of the C{Ext.data.Store}.
......@@ -1002,7 +975,6 @@ class Metric2D(BaseReport):
# replace undefined value by 0
self.df = self.df.fillna(0)
def _do_metric(self):
"""Compute the metric involving two database field.
......@@ -1023,12 +995,12 @@ class Metric2D(BaseReport):
addresses = [address_x, address_y, address_z]
# the database field maps (tablename, fieldname, keyname)
map_x = split_dbfield(address_x)
map_y = split_dbfield(address_y)
map_z = split_dbfield(address_z)
# the database field encoded as (tablename, fieldname, keyname)
dbfield_x = split_dbfield(address_x)
dbfield_y = split_dbfield(address_y)
dbfield_z = split_dbfield(address_z)
maps = [map_x, map_y, map_z]
dbfields = [dbfield_x, dbfield_y, dbfield_z]
# metric
aggregate = config.aggregation_z
......@@ -1042,28 +1014,28 @@ class Metric2D(BaseReport):
expression = address_z
ref_addresses = list(addresses)
del maps[2]
del dbfields[2]
del addresses[2]
i = 0
for m in REG_DBFIELD.finditer(address_z):
address = m.group()
map = split_dbfield(address)
dbfield = split_dbfield(address)
tmp = "a%i" % i
i += 1
addresses.append(tmp)
maps.append(map)
dbfields.append(dbfield)
expression = expression.replace(address, tmp)
# build the data frame
data = self._do_data(maps)
data = self._do_data(dbfields)
if not data:
self.df = pd.DataFrame(columns=addresses)
self.df = DataFrame(columns=addresses)
return
df = pd.DataFrame(data, columns=addresses)
df = DataFrame(data, columns=addresses)
# compute the expression and remove temporarely column
if expression:
......@@ -1086,16 +1058,15 @@ class Metric2D(BaseReport):
df = df.T
# transform year MultiIndex into Index
if isinstance(df.columns, pd.core.index.MultiIndex):
if isinstance(df.columns, MultiIndex):
df.columns = [el[1] for el in df.columns]
if isinstance(df.index, pd.core.index.MultiIndex):
if isinstance(df.index, MultiIndex):
df.index = [el[1] for el in df.index]
# data frame is persistent
self.df = df
def _set_store_data(self):
""" Generate the C{Ext.data.Store.data} property.
......@@ -1117,12 +1088,10 @@ class Metric2D(BaseReport):
self._store.data.append(di)
def _set_store_fields(self):
""" Generate the C{Ext.data.Store.fields} property.
"""
df = self.df
store = self._store
# first column is for the grouped values of the vertical field
......@@ -1138,7 +1107,6 @@ class Metric2D(BaseReport):
store.sorters = [index_group_y]
def to_grid(self):
"""Build the configuration of the C{App.grid.Panel}.
......@@ -1175,7 +1143,6 @@ class Metric2D(BaseReport):
return grid
def to_store(self):
"""Build the configuration of the C{Ext.data.Store}.
......@@ -1189,7 +1156,8 @@ class Metric2D(BaseReport):
# extract column label from the column index
# the latter can be an Index of a MultIndex
idx = df.columns
idx = (idx.get_level_values(-1) if isinstance(idx, pd.MultiIndex) else idx)
idx = \
(idx.get_level_values(-1) if isinstance(idx, MultiIndex) else idx)
self._columns = idx.tolist()
# build the store configuration
......@@ -1199,4 +1167,3 @@ class Metric2D(BaseReport):
self._set_store_data()
return self._store
......@@ -79,9 +79,10 @@ class SelectorActiveItems(Selector):
query = Selector.query(self, table)
if self._period_start and self._period_end:
q = table.start_date <= self._period_end
q = (q) & ((table.end_date == None) | (table.end_date >= self._period_start))
query = (query) & (q)
q1 = table.start_date <= self._period_end
q2 = table.end_date is None
q3 = table.end_date >= self._period_start
query &= (q1) & (q2 | q3)
return query
......
......@@ -40,6 +40,8 @@ Ext.define('MyApp.form.field.UserData', {
textUpdateTitle: 'Modify the property name',
textValue: 'value',
// jshint strict: false
// private method requests by the component model of ExtJS
initComponent: function () {
......@@ -143,6 +145,8 @@ Ext.define('MyApp.form.field.UserData', {
me.callParent(arguments);
},
// jshint strict: true
/**
* Return the field value as an object with the following structure:
*
......@@ -226,10 +230,9 @@ Ext.define('MyApp.form.field.UserData', {
* @param {HTMLElement} tr
* @param {Number} rowIndex
* @param {Ext.EventObject} event
* @param {Object} eOpts
*
*/
onCellContextMenu: function (table, td, cellIndex, record, tr, rowIndex, event, eOpts) {
onCellContextMenu: function (table, td, cellIndex, record, tr, rowIndex, event) {
"use strict";
var me = this;
......@@ -271,10 +274,9 @@ Ext.define('MyApp.form.field.UserData', {
* @param {Ext.grid.header.Container} headerContainer
* @param {Ext.grid.column.Column} column
* @param {Ext.EventObject} event
* @param {HTMLElement} html
* @param {Object} eOpts
*
*/
onHeaderContextMenu: function (headerContainer, column, event, html, eOpts) {
onHeaderContextMenu: function (headerContainer, column, event) {
"use strict";
......
......@@ -143,9 +143,9 @@ Ext.define('MyApp.form.field.UserDataMultiDefault', {
//
// @param {Ext.form.field.ComboBox} combo
// @param {Ext.data.Model[]} records
// @param {Object} eOpts
//
onComboBoxSelect: function (combo, records, eOpts) {
//
onComboBoxSelect: function (combo, records) {
"use strict";
var me = this,
......
......@@ -104,9 +104,8 @@ Ext.define('MyApp.form.plugin.UserDataConsistency', {
// Inform the user and clean the mask on the viewport
//
// @param {Object} response
// @param {Object} options
//
onAjaxFailure: function (response, options) {
onAjaxFailure: function (response) {
"use strict";
var me = this;
......@@ -120,9 +119,8 @@ Ext.define('MyApp.form.plugin.UserDataConsistency', {
// Clean the mask on the viewport