Skip to content

Commit

Permalink
adjusting kobo_to_xlsform (and tests) based on new
Browse files Browse the repository at this point in the history
content rules
  • Loading branch information
dorey committed Oct 13, 2016
1 parent 5e09e83 commit 284b892
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 36 deletions.
9 changes: 6 additions & 3 deletions kpi/tests/test_kobo_to_xlsform.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,9 @@ def test_rank_conversion(self):
self.assertEqual(surv[1]['type'], 'note')
self.assertEqual(surv[1].get('relevant', None), None)

self.assertEqual(surv[2]['required'], 'true')
self.assertEqual(surv[2]['required'], True)
self.assertEqual(surv[2]['type'], 'select_one items')
# self.assertEqual(surv[2]['select_from_list_name'], 'items')
self.assertTrue('constraint' not in surv[2].keys())
self.assertEqual(surv[2].get('constraint_message'), 'Rank Message')

Expand All @@ -112,12 +113,14 @@ def test_score_conversion(self):
self.assertEqual(surv[0]['type'], 'begin_group')
self.assertEqual(surv[0]['relevant'], 'ghijkl')

self.assertEqual(surv[1]['type'], 'select_one items')
self.assertEqual(surv[1]['type'], 'select_one')
self.assertEqual(surv[1]['select_from_list_name'], 'items')
self.assertEqual(surv[1]['appearance'], 'label')
self.assertEqual(surv[1].get('relevant', None), None)

self.assertEqual(surv[2]['appearance'], 'list-nolabel')
self.assertEqual(surv[2]['type'], 'select_one items')
self.assertEqual(surv[2]['type'], 'select_one')
self.assertEqual(surv[2]['select_from_list_name'], 'items')

self.assertEqual(surv[3]['appearance'], 'overridden')

Expand Down
69 changes: 36 additions & 33 deletions kpi/utils/kobo_to_xlsform.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,11 @@ class GroupHandler(RowHandler):
def __init__(self, base_handler):
self._base_handler = base_handler

def begin(self, row):
def begin(self, initial_row):
self._rows = []
self.initial_row_type = initial_row.get('type')
self.name_key = 'name' if ('name' in initial_row) else '$autoname'
self.name = initial_row[self.name_key]

def finish(self):
survey_contents = self._base_handler.survey_contents
Expand Down Expand Up @@ -91,11 +94,11 @@ class KoboRankGroup(GroupHandler):
description = '''Ask a user to rank a number of things.'''

def begin(self, initial_row):
_name = initial_row.get('$autoname')
super(KoboRankGroup, self).begin(initial_row)
self._previous_levels = []

begin_group = {'type': 'begin_group',
'$autoname': _name,
'$autoname': self.name,
'appearance': 'field-list'}

if 'required' in initial_row:
Expand All @@ -104,21 +107,21 @@ def begin(self, initial_row):
begin_group['relevant'] = initial_row['relevant']
del initial_row['relevant']

initial_row_type = initial_row.get('type')

try:
self._rank_itemset = initial_row[COLS['rank-items']]
del initial_row[COLS['rank-items']]
self._rank_constraint_message = initial_row[COLS['rank-cmessage']]
del initial_row[COLS['rank-cmessage']]
except KeyError:
raise KeyError("Row with type: %s must have columns: %s and %s" % (
initial_row_type,
self.initial_row_type,
COLS['rank-items'],
COLS['rank-cmessage'],
))
initial_row.update({'$autoname': '%s_label' % _name,
'type': 'note'})
initial_row.update({'type': 'note',
'name': '%s_label' % self.name,
'type': 'note',
})
self._rows = [
begin_group,
initial_row,
Expand All @@ -138,7 +141,7 @@ def add_level(self, row):
# all ranking sub-questions are required
row.update({
'type': 'select_one %s' % self._rank_itemset,
'required': 'true',
'required': True,
'constraint_message': self._rank_constraint_message,
'appearance': appearance,
})
Expand Down Expand Up @@ -174,9 +177,9 @@ def __init__(self, base_handler):
#survey
| type | name | label | kobo--score-choices | required |
|-------------|-------|-------|---------------------|----------|
| begin_score | skore | Score | skorechoices | true |
| score__row | skr1 | Q1 | | |
| score__row | skr2 | Q2 | | |
| begin_score | | Score | skorechoices | true |
| score__row | | Q1 | | |
| score__row | | Q2 | | |
| end_score | | | | |
#choices
| list name | name | label |
Expand All @@ -188,8 +191,8 @@ def __init__(self, base_handler):
#survey
| type | name | label | appearance | required |
|-------------------------|--------------|-------|--------------|----------|
| begin_group | skore | | field-list | |
| select_one skorechoices | skore_header | Score | label | |
| begin_group | Score | | field-list | |
| select_one skorechoices | Score_header | Score | label | |
| select_one skorechoices | skr1 | Q1 | list-nolabel | true |
| select_one skorechoices | skr2 | Q2 | list-nolabel | true |
| end group | | | | |
Expand All @@ -202,12 +205,11 @@ def __init__(self, base_handler):
self._base_handler = base_handler

def begin(self, initial_row):
initial_row_type = initial_row.get('type')
_name = initial_row['$autoname']
super(KoboScoreGroup, self).begin(initial_row)

begin_group = {'type': 'begin_group',
'$autoname': _name,
'appearance': 'field-list'}
begin_group = {u'type': u'begin_group',
u'appearance': u'field-list'}
begin_group[u'name'] = self.name

if 'required' in initial_row:
self._initial_row_required = initial_row['required']
Expand All @@ -219,38 +221,39 @@ def begin(self, initial_row):

try:
choice_colname = initial_row[COLS['score-choices']]
self._common_type = 'select_one %s' % choice_colname
self._common = {
u'type': u'select_one',
u'select_from_list_name': choice_colname,
}
del initial_row[COLS['score-choices']]
except KeyError:
raise KeyError("Row with type: %s must have a column: %s" % (
initial_row_type,
self.initial_row_type,
COLS['score-choices'],
))
initial_row.update({
'type': self._common_type,
'$autoname': '%s_header' % _name,
'name': '%s_header' % self.name,
'appearance': 'label',
})

})
initial_row.update(self._common)
self._rows = [
begin_group,
initial_row,
]

def add_row(self, row):
appearance = row.get('appearance') or 'list-nolabel'
row.update({'type': self._common_type,
'appearance': appearance,
})
row['appearance'] = appearance
row.update(self._common)
if hasattr(self, '_initial_row_required') and \
self._initial_row_required:
row.update({'required': 'true'})
row.update({u'required': True})
self._rows.append(row)

def handle_row(self, row):
if row.get('type') == 'end_score':
self._rows.append({
'type': 'end_group',
u'type': u'end_group',
})
self.finish()
return False
Expand Down Expand Up @@ -294,14 +297,14 @@ def _is_kobo_specific(sheet_name):
return re.search(r'^kobo--', sheet_name)


def remove_empty_expressions(content):
def remove_empty_expressions_in_place(content):
# xls2json_backends.csv_to_dict(), called by dkobo, omits 'name' keys
# whose values are blank. Since we read JSON from the form builder
# instead of CSV, however, we have to tolerate not only missing names
# but blank ones as well.
for surv_row in content.get('survey'):
for skip_key in ['appearance', 'relevant', 'bind']:
if skip_key in surv_row and surv_row[skip_key] == '':
if skip_key in surv_row and surv_row[skip_key] in ['', None]:
del surv_row[skip_key]


Expand Down Expand Up @@ -332,7 +335,7 @@ def to_xlsform_structure(surv,
_srt.values()[0])

# this is also done in asset.save()
remove_empty_expressions(surv)
remove_empty_expressions_in_place(surv)

if deprecated_autoname:
surv['survey'] = autoname_fields__depr(surv)
Expand Down

0 comments on commit 284b892

Please sign in to comment.