Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
103 changes: 58 additions & 45 deletions src/formpack/schema/fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -253,13 +253,13 @@ def from_json_definition(
'select_one_external': partial(TextField, data_type=data_type),
'cascading_select': partial(TextField, data_type=data_type),
# qualitative analysis and NLP
'qual_auto_keyword_count': QualField,
'qual_integer': QualNumField,
'qual_note': QualField,
'qual_select_multiple': QualSelectMultipleField,
'qual_select_one': QualSelectOneField,
'qual_tags': QualTagsField,
'qual_text': QualField,
'qualAutoKeywordCount': QualField,
'qualInteger': QualNumField,
'qualNote': QualField,
'qualSelectMultiple': QualSelectMultipleField,
'qualSelectOne': QualSelectOneField,
'qualTags': QualTagsField,
'qualText': QualField,
'transcript': QualTranscriptField,
'translation': QualTranslationField,
}
Expand Down Expand Up @@ -530,20 +530,25 @@ def get_labels(self, *args, **kwargs):
return [self._get_label(*args, **kwargs)]

def get_value_from_entry(self, entry):
name = self.name.split('/')[-1]
name_parts = self.name.split('/')
# must have at least the source question path and the qual field uuid
assert len(name_parts) >= 2
field_uuid = name_parts[-1]
# is it still necessary to have a separate `source` attribute?
source = '/'.join(name_parts[:-1])
assert source == self.source

try:
responses = entry['_supplementalDetails'][self.source_field.path][
'qual'
]
# all responses nested within `qual`
responses = entry['_supplementalDetails'][source]['qual']
except KeyError:
return ''

# sure would be nice if this were a dict with uuids as keys instead of
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tell me about it

# a list requiring this kind of iteration
for response in responses:
if response['uuid'] == name:
return response['val']
if response['uuid'] == field_uuid:
return response['value']

return ''

Expand Down Expand Up @@ -614,53 +619,61 @@ def get_value_from_entry(self, entry):
return list_to_csv(val)


class QualTranscriptField(QualField):
def _get_label(self, *args, **kwargs):
source_label = self.source_field._get_label(*args, **kwargs)
return f'{source_label} - transcript ({self.language})'

class QualNameSplittingTransxField(QualField):
"""
The (largely pre-refactor) structure of `_supplementalDetails` should be
changed to match the improved structure of `analysis_form`, and this `name`
splitting logic should be trashed.
"""
def get_value_from_entry(self, entry):
name = self.name.split('/')[-1]
name_parts = self.name.split('/')
# must have at least the source question path and `transcript_??` or
# `translation_??` (where `??` is the language code)
assert len(name_parts) >= 2
transx, _lang = name_parts[-1].split('_') # 🤢
assert transx in ('transcript', 'translation')
assert _lang == self.language
# is it still necessary to have a separate `source` attribute?
source = '/'.join(name_parts[:-1])
assert source == self.source

try:
responses = entry['_supplementalDetails'][self.source_field.path]
responses = entry['_supplementalDetails'][source][transx]
except KeyError:
return ''

name_without_lang, lang = name.split('_')
assert name_without_lang == 'transcript'

# A transcript does not have a dictionary with language keys:
# {'transcript': {'languageCode': 'en', 'value': 'i am a raisin'}}
if responses.get('languageCode') == self.language:
# Grab the value directly
return responses['value']

# However, translations do have an outer dictionary with language keys:
# {
# 'translation': {
# 'es': {'languageCode': 'es', 'value': 'soy una pasa'},
# 'fr': {
# 'languageCode': 'fr',
# 'value': 'je suis un raisin sec',
# },
# }
# }
try:
response = responses['transcript']
return responses[self.language]['value']
except KeyError:
return ''

if response.get('languageCode') == lang:
return response['value']
else:
return ''


class QualTranslationField(QualField):
class QualTranscriptField(QualNameSplittingTransxField):
def _get_label(self, *args, **kwargs):
source_label = self.source_field._get_label(*args, **kwargs)
return f'{source_label} - translation ({self.language})'

def get_value_from_entry(self, entry):
name = self.name.split('/')[-1]

try:
responses = entry['_supplementalDetails'][self.source_field.path]
except KeyError:
return ''
return f'{source_label} - transcript ({self.language})'

name_without_lang, lang = name.split('_')
assert name_without_lang == 'translation'

try:
return responses['translation'][lang]['value']
except KeyError:
return ''
class QualTranslationField(QualNameSplittingTransxField):
def _get_label(self, *args, **kwargs):
source_label = self.source_field._get_label(*args, **kwargs)
return f'{source_label} - translation ({self.language})'


class MediaField(TextField):
Expand Down
6 changes: 2 additions & 4 deletions src/formpack/version.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,15 +81,13 @@ def __init__(
formpack: 'FormPack',
schema: Dict[str, Union[str, List]],
) -> None:

self.schema = schema
self.formpack = formpack

survey = self.schema.get('additional_fields', [])
fields_by_name = self._get_fields_by_name(survey)
survey = self.schema
section = FormSection(name=formpack.title)

self.translations = self._get_translations(schema)
self.translations = [UNTRANSLATED]

for data_def in survey:
field = FormField.from_json_definition(
Expand Down
124 changes: 37 additions & 87 deletions tests/fixtures/analysis_form/analysis_form.json
Original file line number Diff line number Diff line change
@@ -1,88 +1,38 @@
{
"engines": {
"engines/transcript_manual": {
"details": "A human provided transcription"
}
[
{
"type": "transcript",
"name": "record_a_note/transcript_en",
"language": "en",
"source": "record_a_note"
},
"additional_fields": [
{
"type": "transcript",
"name": "record_a_note/transcript_en",
"path": [
"record_a_note",
"transcript_en"
],
"language": "en",
"source": "record_a_note",
"settings": {
"mode": "manual",
"engine": "engines/transcript_manual"
}
},
{
"type": "transcript",
"name": "record_a_note/transcript_es",
"path": [
"record_a_note",
"transcript_es"
],
"language": "es",
"source": "record_a_note",
"settings": {
"mode": "manual",
"engine": "engines/transcript_manual"
}
},
{
"type": "translation",
"name": "record_a_note/translation_en",
"language": "en",
"path": [
"record_a_note",
"translation_en"
],
"source": "record_a_note",
"settings": {
"mode": "manual",
"engine": "engines/translation_manual"
}
},
{
"type": "translation",
"name": "record_a_note/translation_es",
"language": "es",
"path": [
"record_a_note",
"translation_es"
],
"source": "record_a_note",
"settings": {
"mode": "manual",
"engine": "engines/translation_manual"
}
},
{
"type": "qual_text",
"name": "name_of_clerk/comment",
"path": [
"clerk_details/name_of_clerk",
"comment"
],
"label": "Comment on the name of the clerk",
"source": "clerk_details/name_of_clerk"
},
{
"type": "qual_text",
"name": "name_of_shop/comment",
"path": [
"clerk_details/name_of_shop",
"comment"
],
"label": "Comment on the name of the shop",
"source": "clerk_details/name_of_shop"
}
],
"translations": [
"English (en)"
]
}
{
"type": "transcript",
"name": "record_a_note/transcript_es",
"language": "es",
"source": "record_a_note"
},
{
"type": "translation",
"name": "record_a_note/translation_en",
"language": "en",
"source": "record_a_note"
},
{
"type": "translation",
"name": "record_a_note/translation_es",
"language": "es",
"source": "record_a_note"
},
{
"type": "qualText",
"name": "clerk_details/name_of_clerk/uuid_for_comment",
"label": "Comment on the name of the clerk",
"source": "clerk_details/name_of_clerk"
},
{
"type": "qualText",
"name": "clerk_details/name_of_shop/uuid_for_comment",
"label": "Comment on the name of the shop",
"source": "clerk_details/name_of_shop"
}
]
7 changes: 4 additions & 3 deletions tests/fixtures/analysis_form/v1.json
Original file line number Diff line number Diff line change
Expand Up @@ -59,15 +59,16 @@
},
"translation": {
"en": {
"value": "Hello how may I help you?"
"value": "Hello how may I help you?",
"languageCode": "en"
}
}
},
"clerk_details/name_of_clerk": {
"qual": [
{
"uuid": "comment",
"val": "Sounds like an interesting person"
"uuid": "uuid_for_comment",
"value": "Sounds like an interesting person"
}
]
}
Expand Down
4 changes: 2 additions & 2 deletions tests/fixtures/analysis_form/v2.json
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,8 @@
"clerk_details/name_of_shop": {
"qual": [
{
"uuid": "comment",
"val": "Pretty cliche"
"uuid": "uuid_for_comment",
"value": "Pretty cliche"
}
]
}
Expand Down
Loading