diff --git a/doc/changes.rst b/docs/changes.rst
similarity index 100%
rename from doc/changes.rst
rename to docs/changes.rst
diff --git a/doc/conf.py b/docs/conf.py
similarity index 100%
rename from doc/conf.py
rename to docs/conf.py
diff --git a/doc/guide.rst b/docs/guide.rst
similarity index 100%
rename from doc/guide.rst
rename to docs/guide.rst
diff --git a/doc/index.rst b/docs/index.rst
similarity index 100%
rename from doc/index.rst
rename to docs/index.rst
diff --git a/doc/license.rst b/docs/license.rst
similarity index 100%
rename from doc/license.rst
rename to docs/license.rst
diff --git a/pbbt-input.yaml b/pbbt-input.yaml
new file mode 100644
index 0000000..b245cdc
--- /dev/null
+++ b/pbbt-input.yaml
@@ -0,0 +1,17 @@
+#
+# Copyright (c) 2015, Prometheus Research, LLC
+#
+
+title: RIOS.CONVERTER
+tests:
+ # check Python source syntax and style
+ - sh: flake8 ./src/
+
+ - sh: pip install --quiet coverage nose
+ ignore: true
+
+ - rmdir: ./tests/sandbox
+ - mkdir: ./tests/sandbox
+
+ - sh: nosetests --quiet
+ ignore: true
diff --git a/pbbt-output.yaml b/pbbt-output.yaml
new file mode 100644
index 0000000..0a86f58
--- /dev/null
+++ b/pbbt-output.yaml
@@ -0,0 +1,20 @@
+#
+# This file contains expected test output data generated by PBBT.
+#
+---
+suite: rios.converter
+tests:
+- sh: flake8 ./src/
+ stdout: ''
+- sh: pip install --quiet coverage nose
+ stdout: ''
+- sh: nosetests --quiet
+ stdout: |
+ Coverage.py warning: Module rios.converter was never imported.
+ Name Stmts Miss Cover Missing
+ -------------------------------------
+ nose.plugins.cover: WARNING: Failed to generate HTML report: No data to report.
+ ----------------------------------------------------------------------
+ Ran 0 tests in 0.005s
+
+ OK
diff --git a/setup.cfg b/setup.cfg
index 6e34a9c..b8f9329 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -1,20 +1,36 @@
-# coverage.py configuration
-[run]
-source = rios.converter
-branch = True
-data_file = ./build/coverage/coverage.dat
-parallel = True
-[report]
-exclude_lines =
- raise NotImplementedError
- return "REQUIRED"
+# setuptools configuration
+[bdist_wheel]
+universal=1
+
+# Prospector configuration
+[prospector]
+output_format = grouped
+profile = .prospector.yaml
+messages_only = true
+autodetect = false
+
+# Nose configuration
+[nosy]
+base_path = ./
+glob_patterns = *.py *.json
+[nosetests]
+with-coverage=1
+cover-package=rios.converter
+cover-erase=1
+cover-branches=1
+cover-html=1
+cover-html-dir=build/coverage
+nocapture=1
# PBBT configuration
-#[pbbt]
-#input = test/input.yaml
-#output = test/output.yaml
+[pbbt]
+input = pbbt-input.yaml
+output = pbbt-output.yaml
+max_errors = 1
# Sphinx configuration
[build_sphinx]
build_dir = build/doc
+[flake8]
+ignore = E123,E126,E127,E202,E241,E402,W503
diff --git a/setup.py b/setup.py
index 41f565a..e1b60e8 100644
--- a/setup.py
+++ b/setup.py
@@ -22,8 +22,22 @@
'rex.web >=3.5, <4',
'rios.conversion >=0.2, <1',
],
+ extras_require={
+ 'dev': [
+ 'pbbt>=0.1.4,<1',
+ 'coverage>=3.7,<4',
+ 'nose>=1.3,<2',
+ 'nosy>=1.1,<2',
+ 'prospector[with_pyroma]>=0.10,<0.11',
+ 'twine>=1.5,<2',
+ 'wheel>=0.24,<0.25',
+ 'Sphinx>=1.3,<2',
+ 'sphinx-autobuild>=0.5,<0.6',
+ 'tox>=2,<3',
+ 'flake8>=2.5.0,<3',
+ ],
+ },
+ test_suite='nose.collector',
rex_init='rios.converter',
rex_static='static',
)
-
-
diff --git a/src/rios/__init__.py b/src/rios/__init__.py
index 8ff904a..396c211 100644
--- a/src/rios/__init__.py
+++ b/src/rios/__init__.py
@@ -4,5 +4,3 @@
__import__('pkg_resources').declare_namespace(__name__)
-
-
diff --git a/src/rios/converter.py b/src/rios/converter.py
index f37b00a..81c651a 100644
--- a/src/rios/converter.py
+++ b/src/rios/converter.py
@@ -4,7 +4,6 @@
from rex.core import get_settings
from rex.core import AnyVal
from rex.core import StrVal
-from rex.core import PIntVal
from rex.core import Setting
from rex.web import Command
from rex.web import HandleError
@@ -72,8 +71,9 @@ class ConvertToRios(Command):
'redcap': RedcapToRios,
}
-
- def render(self, req,
+ def render(
+ self,
+ req,
system,
format,
instrument_title,
@@ -102,7 +102,7 @@ def render(self, req,
if not instrument_id:
errors.append('Instrument ID is required.')
if not instrument_title:
- errors.append('Instrument Title is required.')
+ errors.append('Instrument Title is required.')
args.extend([
'--id', instrument_id,
'--title', instrument_title, ])
@@ -119,7 +119,7 @@ def render(self, req,
return Response(json={
"status": 400,
"errors": errors
- })
+ })
with open(error_filename, 'wb') as stderr:
sys.stdin = infile.file
# I can't explain why I am
@@ -150,7 +150,7 @@ def render(self, req,
name = outname + '.zip'
shutil.rmtree(temp_dir)
return Response(
- content_type='application/zip',
+ content_type='application/zip',
content_disposition='attachment; filename="%s"' % name,
body=body)
else:
@@ -187,7 +187,9 @@ def load_file(self, file_field):
fo.write(file_field.file.read())
return filename
- def render(self, req,
+ def render(
+ self,
+ req,
system,
format,
localization,
@@ -195,7 +197,7 @@ def render(self, req,
form_file,
calculationset_file,
outname):
-
+
self.settings = get_settings()
tempfile.tempdir = self.settings.temp_dir
self.temp_dir = tempfile.mkdtemp()
@@ -208,23 +210,23 @@ def render(self, req,
args = [
'--verbose',
'--format', format,
- '--outfile', outfile,
+ '--outfile', outfile,
]
if hasattr(instrument_file, 'filename'):
args.extend([
- '--instrument',
- '%s' % self.load_file(instrument_file)])
+ '--instrument',
+ '%s' % self.load_file(instrument_file)])
else:
errors.append('An input instrument file is required.')
if hasattr(form_file, 'filename'):
args.extend([
- '--form',
+ '--form',
'%s' % self.load_file(form_file)])
else:
errors.append('An input form file is required.')
if hasattr(calculationset_file, 'filename'):
args.extend([
- '--calculationset',
+ '--calculationset',
'%s' % self.load_file(calculationset_file)])
if localization:
args.extend(['--localization', localization])
@@ -233,7 +235,7 @@ def render(self, req,
return Response(json={
"status": 400,
"errors": errors
- })
+ })
error_filename = outfile + '.stderr'
with open(error_filename, 'wb') as stderr:
# I can't eplain why I am
@@ -261,7 +263,7 @@ def render(self, req,
name = outname + '.zip'
shutil.rmtree(self.temp_dir)
return Response(
- content_type='application/zip',
+ content_type='application/zip',
content_disposition='attachment; filename="%s"' % name,
body=body)
else:
@@ -281,8 +283,8 @@ class HandleNotFound(HandleError):
def __call__(self, req):
return render_to_response(
- self.template,
- req,
+ self.template,
+ req,
status=self.code,
path=req.path)
diff --git a/src/rios/settings.py b/src/rios/settings.py
index dec34c9..abcea19 100644
--- a/src/rios/settings.py
+++ b/src/rios/settings.py
@@ -1,4 +1,6 @@
from rex.core import Setting
+from rex.core import StrVal
+
class TempDirSetting(Setting):
"""Directory with temporary data."""
diff --git a/tests/qualtrics/test_1.qsf b/tests/qualtrics/test_1.qsf
new file mode 100644
index 0000000..f524b5d
--- /dev/null
+++ b/tests/qualtrics/test_1.qsf
@@ -0,0 +1,1403 @@
+{
+ "SurveyElements": [
+ {
+ "Element": "BL",
+ "Payload": {
+ "1": {
+ "BlockElements": [],
+ "Description": "Trash / Unused Questions",
+ "ID": "BL_ewINXLLgPGSMToU",
+ "Type": "Trash"
+ },
+ "3": {
+ "BlockElements": [
+ {
+ "QuestionID": "QID17671673",
+ "Type": "Question"
+ },
+ {
+ "Type": "Page Break"
+ },
+ {
+ "QuestionID": "QID17671684",
+ "Type": "Question"
+ },
+ {
+ "QuestionID": "QID17671695",
+ "Type": "Question"
+ },
+ {
+ "QuestionID": "QID17671696",
+ "Type": "Question"
+ },
+ {
+ "QuestionID": "QID17671697",
+ "Type": "Question"
+ },
+ {
+ "QuestionID": "QID17671698",
+ "Type": "Question"
+ },
+ {
+ "QuestionID": "QID17671699",
+ "Type": "Question"
+ },
+ {
+ "QuestionID": "QID17671700",
+ "Type": "Question"
+ },
+ {
+ "QuestionID": "QID17671701",
+ "Type": "Question"
+ },
+ {
+ "QuestionID": "QID17671674",
+ "Type": "Question"
+ },
+ {
+ "QuestionID": "QID17671675",
+ "Type": "Question"
+ },
+ {
+ "QuestionID": "QID17671676",
+ "Type": "Question"
+ },
+ {
+ "QuestionID": "QID17671677",
+ "Type": "Question"
+ },
+ {
+ "QuestionID": "QID17671678",
+ "Type": "Question"
+ },
+ {
+ "QuestionID": "QID17671679",
+ "Type": "Question"
+ },
+ {
+ "QuestionID": "QID17671680",
+ "Type": "Question"
+ },
+ {
+ "QuestionID": "QID17671681",
+ "Type": "Question"
+ },
+ {
+ "QuestionID": "QID17671682",
+ "Type": "Question"
+ },
+ {
+ "QuestionID": "QID17671683",
+ "Type": "Question"
+ },
+ {
+ "QuestionID": "QID17671685",
+ "Type": "Question"
+ },
+ {
+ "QuestionID": "QID17671686",
+ "Type": "Question"
+ },
+ {
+ "QuestionID": "QID17671687",
+ "Type": "Question"
+ },
+ {
+ "QuestionID": "QID17671688",
+ "Type": "Question"
+ },
+ {
+ "QuestionID": "QID17671689",
+ "Type": "Question"
+ },
+ {
+ "QuestionID": "QID17671690",
+ "Type": "Question"
+ },
+ {
+ "QuestionID": "QID17671691",
+ "Type": "Question"
+ },
+ {
+ "QuestionID": "QID17671692",
+ "Type": "Question"
+ },
+ {
+ "QuestionID": "QID17671693",
+ "Type": "Question"
+ },
+ {
+ "Type": "Page Break"
+ },
+ {
+ "QuestionID": "QID17671694",
+ "Type": "Question"
+ }
+ ],
+ "Description": "Default Question Block",
+ "ID": "BL_egR0r71cln4IT53",
+ "Type": "Standard"
+ }
+ },
+ "PrimaryAttribute": "Survey Blocks",
+ "SecondaryAttribute": null,
+ "SurveyID": "SV_1MMcjvoGWqh8uUZ",
+ "TertiaryAttribute": null
+ },
+ {
+ "Element": "FL",
+ "Payload": {
+ "Flow": [
+ {
+ "FlowID": "FL_0H61Rc1wZydkW9f",
+ "ID": "BL_egR0r71cln4IT53",
+ "Type": "Standard"
+ }
+ ],
+ "FlowID": "FL_beFskwZfIF2w2Mt",
+ "Properties": {
+ "Count": 2,
+ "count": 1
+ }
+ },
+ "PrimaryAttribute": "Survey Flow",
+ "SecondaryAttribute": null,
+ "SurveyID": "SV_1MMcjvoGWqh8uUZ",
+ "TertiaryAttribute": null
+ },
+ {
+ "Element": "SO",
+ "Payload": {
+ "BackButton": "true",
+ "BallotBoxStuffing": "false",
+ "CustomStyles": {
+ "altRowStyles": {
+ "selector": ".Skin .ReadableAlt, .Skin .LightBG",
+ "styles": {
+ "backgroundColor": null
+ }
+ }
+ }
+ },
+ "PrimaryAttribute": "Survey Options",
+ "SecondaryAttribute": null,
+ "SurveyID": "SV_1MMcjvoGWqh8uUZ",
+ "TertiaryAttribute": null
+ },
+ {
+ "Element": "SCO",
+ "Payload": {
+ "DefaultScoringCategory": null,
+ "ID": "Scoring"
+ },
+ "PrimaryAttribute": "Scoring",
+ "SecondaryAttribute": null,
+ "SurveyID": "SV_1MMcjvoGWqh8uUZ",
+ "TertiaryAttribute": null
+ },
+ {
+ "Element": "SQ",
+ "Payload": {
+ "AnalysisType": {
+ "Type": "TableOnly"
+ },
+ "Choices": [
+ {
+ "Display": "Without test"
+ },
+ {
+ "Display": "With some test"
+ },
+ {
+ "Display": "or, are you completely unable to Q8?"
+ }
+ ],
+ "Configuration": {
+ "VariableCount": 3
+ },
+ "DataExportTag": "Q8",
+ "QuestionDescription": "(Q8)",
+ "QuestionID": "QID17671700",
+ "QuestionText": "Can you Q8:",
+ "QuestionType": "MC",
+ "Randomization": {
+ "Type": "None"
+ },
+ "Selector": "SAVR",
+ "SubSelector": "TX",
+ "Validation": {
+ "Settings": {
+ "Type": "None"
+ }
+ }
+ },
+ "PrimaryAttribute": "QID17671700",
+ "SurveyID": "SV_1MMcjvoGWqh8uUZ",
+ "TertiaryAttribute": null
+ },
+ {
+ "Element": "SQ",
+ "Payload": {
+ "AnalysisType": {
+ "Type": "TableOnly"
+ },
+ "Choices": [
+ {
+ "Display": "Without test"
+ },
+ {
+ "Display": "With some test"
+ },
+ {
+ "Display": "or, are you completely unable to Q11?"
+ }
+ ],
+ "Configuration": {
+ "VariableCount": 3
+ },
+ "DataExportTag": "Q11",
+ "QuestionDescription": "(11) Can you 11:",
+ "QuestionID": "QID17671675",
+ "QuestionText": " (11) Can you 11:",
+ "QuestionType": "MC",
+ "Randomization": {
+ "Type": "None"
+ },
+ "Selector": "SAVR",
+ "SubSelector": "TX",
+ "Validation": {
+ "Settings": {
+ "Type": "None"
+ }
+ }
+ },
+ "PrimaryAttribute": "QID17671675",
+ "SecondaryAttribute": "(11):",
+ "SurveyID": "SV_1MMcjvoGWqh8uUZ",
+ "TertiaryAttribute": null
+ },
+ {
+ "Element": "SQ",
+ "Payload": {
+ "AnalysisType": {
+ "Type": "TableOnly"
+ },
+ "Choices": [
+ {
+ "Display": "Without test"
+ },
+ {
+ "Display": "With some test"
+ },
+ {
+ "Display": "or, are you completely unable to Q10?"
+ }
+ ],
+ "Configuration": {
+ "VariableCount": 3
+ },
+ "DataExportTag": "Q10",
+ "QuestionDescription": "(your",
+ "QuestionID": "QID17671674",
+ "QuestionText": "Can you 10:",
+ "QuestionText_Unsafe": " (M:",
+ "QuestionType": "MC",
+ "Randomization": {
+ "Type": "None"
+ },
+ "Selector": "SAVR",
+ "SubSelector": "TX",
+ "Validation": {
+ "Settings": {
+ "Type": "None"
+ }
+ }
+ },
+ "PrimaryAttribute": "QID17671674",
+ "SecondaryAttribute": "(M",
+ "SurveyID": "SV_1MMcjvoGWqh8uUZ",
+ "TertiaryAttribute": null
+ },
+ {
+ "Element": "SQ",
+ "Payload": {
+ "AnalysisType": {
+ "Type": "TableOnly"
+ },
+ "Choices": [
+ {
+ "Display": "Without test"
+ },
+ {
+ "Display": "With some test"
+ },
+ {
+ "Display": "or, are you completely unable to Q12?"
+ }
+ ],
+ "Configuration": {
+ "VariableCount": 3
+ },
+ "DataExportTag": "Q12",
+ "QuestionDescription": "(12)",
+ "QuestionID": "QID17671676",
+ "QuestionText": " (12) Can you 12:",
+ "QuestionText_Unsafe": "12:",
+ "QuestionType": "MC",
+ "Randomization": {
+ "Type": "None"
+ },
+ "Selector": "SAVR",
+ "SubSelector": "TX",
+ "Validation": {
+ "Settings": {
+ "Type": "None"
+ }
+ }
+ },
+ "PrimaryAttribute": "QID17671676",
+ "SecondaryAttribute": "12",
+ "SurveyID": "SV_1MMcjvoGWqh8uUZ",
+ "TertiaryAttribute": null
+ },
+ {
+ "Element": "SQ",
+ "Payload": {
+ "AnalysisType": {
+ "Type": "TableOnly"
+ },
+ "Choices": [
+ {
+ "Display": "Without test"
+ },
+ {
+ "Display": "With some test"
+ },
+ {
+ "Display": "or, are you completely unable to Q14?"
+ }
+ ],
+ "Configuration": {
+ "VariableCount": 3
+ },
+ "DataExportTag": "Q14",
+ "QuestionDescription": "(14)",
+ "QuestionID": "QID17671678",
+ "QuestionText": " (14) Do you 14:",
+ "QuestionText_Unsafe": " (14:",
+ "QuestionType": "MC",
+ "Randomization": {
+ "Type": "None"
+ },
+ "Selector": "SAVR",
+ "SubSelector": "TX",
+ "Validation": {
+ "Settings": {
+ "Type": "None"
+ }
+ }
+ },
+ "PrimaryAttribute": "QID17671678",
+ "SecondaryAttribute": "14",
+ "SurveyID": "SV_1MMcjvoGWqh8uUZ",
+ "TertiaryAttribute": null
+ },
+ {
+ "Element": "SQ",
+ "Payload": {
+ "AnalysisType": {
+ "Type": "TableOnly"
+ },
+ "ChoiceOrder": [
+ "1",
+ "c2",
+ "c3"
+ ],
+ "Choices": {
+ "1": {
+ "Display": "Without test"
+ },
+ "c2": {
+ "Display": "With some test"
+ },
+ "c3": {
+ "Display": "or, are you completely unable to Q13?"
+ }
+ },
+ "Configuration": {
+ "QuestionDescriptionOption": "UseText",
+ "VariableCount": 3
+ },
+ "DataExportTag": "Q13",
+ "Language": [],
+ "QuestionDescription": "(13",
+ "QuestionID": "QID17671677",
+ "QuestionText": " (13) do you 13:",
+ "QuestionText_Unsafe": "13:",
+ "QuestionType": "MC",
+ "Randomization": {
+ "Type": "None"
+ },
+ "Selector": "SAVR",
+ "SubSelector": "TX",
+ "Validation": {
+ "Settings": {
+ "Type": "None"
+ }
+ }
+ },
+ "PrimaryAttribute": "QID17671677",
+ "SecondaryAttribute": "(13",
+ "SurveyID": "SV_1MMcjvoGWqh8uUZ",
+ "TertiaryAttribute": null
+ },
+ {
+ "Element": "SQ",
+ "Payload": {
+ "AnalysisType": {
+ "Type": "TableOnly"
+ },
+ "Choices": [
+ {
+ "Display": "Without test"
+ },
+ {
+ "Display": "With some test"
+ },
+ {
+ "Display": "or, are you completely unable to Q9?"
+ }
+ ],
+ "Configuration": {
+ "VariableCount": 3
+ },
+ "DataExportTag": "Q9",
+ "QuestionDescription": "(9",
+ "QuestionID": "QID17671701",
+ "QuestionText": " (9) Can you 9:",
+ "QuestionText_Unsafe": " (9:",
+ "QuestionType": "MC",
+ "Randomization": {
+ "Type": "None"
+ },
+ "Selector": "SAVR",
+ "SubSelector": "TX",
+ "Validation": {
+ "Settings": {
+ "Type": "None"
+ }
+ }
+ },
+ "PrimaryAttribute": "QID17671701",
+ "SecondaryAttribute": "(9",
+ "SurveyID": "SV_1MMcjvoGWqh8uUZ",
+ "TertiaryAttribute": null
+ },
+ {
+ "Element": "SQ",
+ "Payload": {
+ "AnalysisType": {
+ "Type": "TextEntry"
+ },
+ "DataExportTag": "Q15",
+ "QuestionDescription": "(15",
+ "QuestionID": "QID17671679",
+ "QuestionText": "
(do 15?",
+ "QuestionText_Unsafe": "
(15",
+ "QuestionType": "TE",
+ "Randomization": {
+ "Type": "None"
+ },
+ "Selector": "SL",
+ "SubSelector": null,
+ "Validation": {
+ "Settings": {
+ "Type": "None"
+ }
+ }
+ },
+ "PrimaryAttribute": "QID17671679",
+ "SecondaryAttribute": "(15",
+ "SurveyID": "SV_1MMcjvoGWqh8uUZ",
+ "TertiaryAttribute": null
+ },
+ {
+ "Element": "SQ",
+ "Payload": {
+ "AnalysisType": {
+ "Type": "TableOnly"
+ },
+ "Choices": [
+ {
+ "Display": "Without test"
+ },
+ {
+ "Display": "With some test"
+ },
+ {
+ "Display": "or, are you completely unable to Q7?"
+ }
+ ],
+ "Configuration": {
+ "VariableCount": 3
+ },
+ "DataExportTag": "Q7",
+ "QuestionDescription": "(7",
+ "QuestionID": "QID17671699",
+ "QuestionText": "can you 7?",
+ "QuestionText_Unsafe": " (7:",
+ "QuestionType": "MC",
+ "Randomization": {
+ "Type": "None"
+ },
+ "Selector": "SAVR",
+ "SubSelector": "TX",
+ "Validation": {
+ "Settings": {
+ "Type": "None"
+ }
+ }
+ },
+ "PrimaryAttribute": "QID17671699",
+ "SecondaryAttribute": "(7",
+ "SurveyID": "SV_1MMcjvoGWqh8uUZ",
+ "TertiaryAttribute": null
+ },
+ {
+ "Element": "QC",
+ "Payload": null,
+ "PrimaryAttribute": "Survey Question Count",
+ "SecondaryAttribute": "87",
+ "SurveyID": "SV_1MMcjvoGWqh8uUZ",
+ "TertiaryAttribute": null
+ },
+ {
+ "Element": "SQ",
+ "Payload": {
+ "AnalysisType": {
+ "Type": "TableOnly"
+ },
+ "Choices": [
+ {
+ "Display": "55-59"
+ },
+ {
+ "Display": "60-64"
+ },
+ {
+ "Display": "65-69"
+ },
+ {
+ "Display": "70-74"
+ },
+ {
+ "Display": "75-79"
+ },
+ {
+ "Display": "80-84"
+ },
+ {
+ "Display": "85+"
+ }
+ ],
+ "Configuration": {
+ "VariableCount": 7
+ },
+ "DataExportTag": "Q22",
+ "QuestionDescription": "Age category:",
+ "QuestionID": "QID17671687",
+ "QuestionText": " Age category:",
+ "QuestionText_Unsafe": " Age category:",
+ "QuestionType": "MC",
+ "Randomization": {
+ "Type": "None"
+ },
+ "Selector": "SAVR",
+ "SubSelector": "TX",
+ "Validation": {
+ "Settings": {
+ "Type": "None"
+ }
+ }
+ },
+ "PrimaryAttribute": "QID17671687",
+ "SecondaryAttribute": "Age category:",
+ "SurveyID": "SV_1MMcjvoGWqh8uUZ",
+ "TertiaryAttribute": null
+ },
+ {
+ "Element": "RS",
+ "Payload": null,
+ "PrimaryAttribute": "RS_5ARGPss19xUGVM1",
+ "SecondaryAttribute": "Default Response Set",
+ "SurveyID": "SV_1MMcjvoGWqh8uUZ",
+ "TertiaryAttribute": null
+ },
+ {
+ "Element": "SQ",
+ "Payload": {
+ "AnalysisType": {
+ "Type": "TableOnly"
+ },
+ "Choices": [
+ {
+ "Display": "Dog"
+ },
+ {
+ "Display": "Cat"
+ },
+ {
+ "Display": "Both"
+ },
+ {
+ "Display": "Neither"
+ }
+ ],
+ "Configuration": {
+ "VariableCount": 4
+ },
+ "DataExportTag": "Q19",
+ "QuestionDescription": "19",
+ "QuestionID": "QID17671683",
+ "QuestionText": " Do 19?",
+ "QuestionText_Unsafe": " Do 19",
+ "QuestionType": "MC",
+ "Randomization": {
+ "Type": "None"
+ },
+ "Selector": "SAVR",
+ "SubSelector": "TX",
+ "Validation": {
+ "Settings": {
+ "Type": "None"
+ }
+ }
+ },
+ "PrimaryAttribute": "QID17671683",
+ "SecondaryAttribute": "Do 19",
+ "SurveyID": "SV_1MMcjvoGWqh8uUZ",
+ "TertiaryAttribute": null
+ },
+ {
+ "Element": "SQ",
+ "Payload": {
+ "AnalysisType": {
+ "Type": "TableOnly"
+ },
+ "Choices": [
+ {
+ "Display": "Left"
+ },
+ {
+ "Display": "Right"
+ },
+ {
+ "Display": "Other"
+ }
+ ],
+ "Configuration": {
+ "VariableCount": 3
+ },
+ "DataExportTag": "Q26",
+ "QuestionDescription": "Do you 26?",
+ "QuestionID": "QID17671691",
+ "QuestionText": " Do you 26?",
+ "QuestionText_Unsafe": " Do you 26?",
+ "QuestionType": "MC",
+ "Randomization": {
+ "Type": "None"
+ },
+ "Selector": "SAVR",
+ "SubSelector": "TX",
+ "Validation": {
+ "Settings": {
+ "Type": "None"
+ }
+ }
+ },
+ "PrimaryAttribute": "QID17671691",
+ "SecondaryAttribute": "Do you 26?",
+ "SurveyID": "SV_1MMcjvoGWqh8uUZ",
+ "TertiaryAttribute": null
+ },
+ {
+ "Element": "SQ",
+ "Payload": {
+ "AnalysisType": {
+ "Type": "TableOnly"
+ },
+ "Choices": [
+ {
+ "Display": "Retired"
+ },
+ {
+ "Display": "Employed full time"
+ },
+ {
+ "Display": "Employed part time"
+ }
+ ],
+ "Configuration": {
+ "VariableCount": 3
+ },
+ "DataExportTag": "Q27",
+ "QuestionDescription": "Employment status:",
+ "QuestionID": "QID17671692",
+ "QuestionText": " Employment status:",
+ "QuestionText_Unsafe": " Employment status:",
+ "QuestionType": "MC",
+ "Randomization": {
+ "Type": "None"
+ },
+ "Selector": "SAVR",
+ "SubSelector": "TX",
+ "Validation": {
+ "Settings": {
+ "Type": "None"
+ }
+ }
+ },
+ "PrimaryAttribute": "QID17671692",
+ "SecondaryAttribute": "Employment status:",
+ "SurveyID": "SV_1MMcjvoGWqh8uUZ",
+ "TertiaryAttribute": null
+ },
+ {
+ "Element": "SQ",
+ "Payload": {
+ "AnalysisType": {
+ "Type": "TableOnly"
+ },
+ "Choices": [
+ {
+ "Display": "Excellent"
+ },
+ {
+ "Display": "Good"
+ },
+ {
+ "Display": "Fair"
+ },
+ {
+ "Display": "Poor"
+ }
+ ],
+ "Configuration": {
+ "VariableCount": 4
+ },
+ "DataExportTag": "Q2",
+ "QuestionDescription": "First 2",
+ "QuestionID": "QID17671684",
+ "QuestionText": " First of all, ?",
+ "QuestionText_Unsafe": " First of all?",
+ "QuestionType": "MC",
+ "Randomization": {
+ "Type": "None"
+ },
+ "Selector": "SAVR",
+ "SubSelector": "TX",
+ "Validation": {
+ "Settings": {
+ "Type": "None"
+ }
+ }
+ },
+ "PrimaryAttribute": "QID17671684",
+ "SecondaryAttribute": "First of all",
+ "SurveyID": "SV_1MMcjvoGWqh8uUZ",
+ "TertiaryAttribute": null
+ },
+ {
+ "Element": "SQ",
+ "Payload": {
+ "AnalysisType": {
+ "Type": "TableOnly"
+ },
+ "Choices": [
+ {
+ "Display": "Male"
+ },
+ {
+ "Display": "Female"
+ }
+ ],
+ "Configuration": {
+ "VariableCount": 2
+ },
+ "DataExportTag": "Q23",
+ "QuestionDescription": "Gender:",
+ "QuestionID": "QID17671688",
+ "QuestionText": " Gender:",
+ "QuestionText_Unsafe": " Gender:",
+ "QuestionType": "MC",
+ "Randomization": {
+ "Type": "None"
+ },
+ "Selector": "SAVR",
+ "SubSelector": "TX",
+ "Validation": {
+ "Settings": {
+ "Type": "None"
+ }
+ }
+ },
+ "PrimaryAttribute": "QID17671688",
+ "SecondaryAttribute": "Gender:",
+ "SurveyID": "SV_1MMcjvoGWqh8uUZ",
+ "TertiaryAttribute": null
+ },
+ {
+ "Element": "LBLK",
+ "Payload": null,
+ "PrimaryAttribute": "LS_4H0tobiMbH5qBZr",
+ "SecondaryAttribute": "GR_0rJTu2lC3cYWmrO",
+ "SurveyID": "SV_1MMcjvoGWqh8uUZ",
+ "TertiaryAttribute": null
+ },
+ {
+ "Element": "SQ",
+ "Payload": {
+ "AnalysisType": {
+ "Type": "TableOnly"
+ },
+ "Choices": [
+ {
+ "Display": "Daily"
+ },
+ {
+ "Display": "Several times a week"
+ },
+ {
+ "Display": "Weekly"
+ },
+ {
+ "Display": "Several times a month"
+ },
+ {
+ "Display": "Monthly or less often"
+ }
+ ],
+ "Configuration": {
+ "VariableCount": 5
+ },
+ "DataExportTag": "Q5",
+ "QuestionDescription": "How often does 5",
+ "QuestionID": "QID17671697",
+ "QuestionText": " How often does 5?",
+ "QuestionText_Unsafe": " How often does 5?",
+ "QuestionType": "MC",
+ "Randomization": {
+ "Type": "None"
+ },
+ "Selector": "SAVR",
+ "SubSelector": "TX",
+ "Validation": {
+ "Settings": {
+ "Type": "None"
+ }
+ }
+ },
+ "PrimaryAttribute": "QID17671697",
+ "SecondaryAttribute": "How often does 5",
+ "SurveyID": "SV_1MMcjvoGWqh8uUZ",
+ "TertiaryAttribute": null
+ },
+ {
+ "Element": "SQ",
+ "Payload": {
+ "AnalysisType": {
+ "Type": "TableOnly"
+ },
+ "Choices": [
+ {
+ "Display": "No treatment"
+ },
+ {
+ "Display": "Medication"
+ },
+ {
+ "Display": "Other"
+ }
+ ],
+ "Configuration": {
+ "VariableCount": 3
+ },
+ "DataExportTag": "Q20",
+ "QuestionDescription": "If 20",
+ "QuestionID": "QID17671685",
+ "QuestionText": " If 20?",
+ "QuestionText_Unsafe": " If 20?",
+ "QuestionType": "MC",
+ "Randomization": {
+ "Type": "None"
+ },
+ "Selector": "SAVR",
+ "SubSelector": "TX",
+ "Validation": {
+ "Settings": {
+ "Type": "None"
+ }
+ }
+ },
+ "PrimaryAttribute": "QID17671685",
+ "SecondaryAttribute": "If 20",
+ "SurveyID": "SV_1MMcjvoGWqh8uUZ",
+ "TertiaryAttribute": null
+ },
+ {
+ "Element": "SQ",
+ "Payload": {
+ "AnalysisType": {
+ "Type": "TextEntry"
+ },
+ "DataExportTag": "Q16",
+ "QuestionDescription": "If you have q16",
+ "QuestionID": "QID17671680",
+ "QuestionText": "
If you have q16?",
+ "QuestionText_Unsafe": "
If you q16?",
+ "QuestionType": "TE",
+ "Randomization": {
+ "Type": "None"
+ },
+ "Selector": "SL",
+ "SubSelector": null,
+ "Validation": {
+ "Settings": {
+ "Type": "None"
+ }
+ }
+ },
+ "PrimaryAttribute": "QID17671680",
+ "SecondaryAttribute": "If you have q16",
+ "SurveyID": "SV_1MMcjvoGWqh8uUZ",
+ "TertiaryAttribute": null
+ },
+ {
+ "Element": "SQ",
+ "Payload": {
+ "AnalysisType": {
+ "Type": "TableOnly"
+ },
+ "Choices": {
+ "1": {
+ "Display": "Without test"
+ },
+ "2": {
+ "Display": "With some test"
+ },
+ "3": {
+ "Display": "or, are you completely unable to Q17?"
+ }
+ },
+ "Configuration": {
+ "VariableCount": 3
+ },
+ "DataExportTag": "Q17",
+ "QuestionDescription": "If you q17",
+ "QuestionID": "QID17671681",
+ "QuestionText": " If you q17:",
+ "QuestionText_Unsafe": " If you have q17:",
+ "QuestionType": "MC",
+ "Randomization": {
+ "Type": "None"
+ },
+ "Selector": "SAVR",
+ "SubSelector": "TX",
+ "Validation": {
+ "Settings": {
+ "Type": "None"
+ }
+ }
+ },
+ "PrimaryAttribute": "QID17671681",
+ "SecondaryAttribute": "If you have q17",
+ "SurveyID": "SV_1MMcjvoGWqh8uUZ",
+ "TertiaryAttribute": null
+ },
+ {
+ "Element": "SQ",
+ "Payload": {
+ "DataExportTag": "Q21",
+ "QuestionDescription": "Just a few",
+ "QuestionID": "QID17671686",
+ "QuestionText": " Just a few:",
+ "QuestionText_Unsafe": " Just a few:",
+ "QuestionType": "DB",
+ "Selector": "PTB",
+ "SubSelector": null
+ },
+ "PrimaryAttribute": "QID17671686",
+ "SecondaryAttribute": "Just a few",
+ "SurveyID": "SV_1MMcjvoGWqh8uUZ",
+ "TertiaryAttribute": null
+ },
+ {
+ "Element": "SQ",
+ "Payload": {
+ "DataExportTag": "Q18",
+ "QuestionDescription": "Let me q18",
+ "QuestionID": "QID17671682",
+ "QuestionText": " Let me q18",
+ "QuestionText_Unsafe": " Let me q18",
+ "QuestionType": "DB",
+ "Selector": "PTB",
+ "SubSelector": null
+ },
+ "PrimaryAttribute": "QID17671682",
+ "SecondaryAttribute": "Let me q18",
+ "SurveyID": "SV_1MMcjvoGWqh8uUZ",
+ "TertiaryAttribute": null
+ },
+ {
+ "Element": "SQ",
+ "Payload": {
+ "AnalysisType": {
+ "Type": "TableOnly"
+ },
+ "ChoiceOrder": [
+ "0",
+ "1",
+ "2",
+ "3"
+ ],
+ "Choices": [
+ {
+ "Display": "Married"
+ },
+ {
+ "Display": "Divorced"
+ },
+ {
+ "Display": "Widowed"
+ },
+ {
+ "Display": "Never been married"
+ }
+ ],
+ "Configuration": {
+ "QuestionDescriptionOption": "UseText",
+ "VariableCount": 4
+ },
+ "DataExportTag": "Q28",
+ "Language": [],
+ "QuestionDescription": "Marital status:",
+ "QuestionID": "QID17671693",
+ "QuestionText": " Marital status:",
+ "QuestionText_Unsafe": " Marital status:",
+ "QuestionType": "MC",
+ "Randomization": {
+ "Type": "None"
+ },
+ "Selector": "SAVR",
+ "SubSelector": "TX",
+ "Validation": {
+ "Settings": {
+ "ForceResponseType": "ON",
+ "Type": "None"
+ }
+ }
+ },
+ "PrimaryAttribute": "QID17671693",
+ "SecondaryAttribute": "Marital status:",
+ "SurveyID": "SV_1MMcjvoGWqh8uUZ",
+ "TertiaryAttribute": null
+ },
+ {
+ "Element": "SQ",
+ "Payload": {
+ "AnalysisType": {
+ "Type": "TableOnly"
+ },
+ "ChoiceOrder": [
+ "1",
+ "2",
+ "3",
+ "4",
+ "5"
+ ],
+ "Choices": {
+ "1": {
+ "Display": "You can 1 (Excellent capacity)"
+ },
+ "2": {
+ "Display": "You can 2 (Good capacity)"
+ },
+ "3": {
+ "Display": "You can 3 (Moderate capacity)"
+ },
+ "4": {
+ "Display": "You 4 (Severely impaired capacity)"
+ },
+ "5": {
+ "Display": "You 5 (Completely impaired capacity)"
+ }
+ },
+ "Configuration": {
+ "QuestionDescriptionOption": "UseText",
+ "VariableCount": 5
+ },
+ "DataExportTag": "Q6",
+ "Language": [],
+ "QuestionDescription": "Now, about q6",
+ "QuestionID": "QID17671698",
+ "QuestionText": " Now, about q6:",
+ "QuestionText_Unsafe": " Now, about q6:",
+ "QuestionType": "MC",
+ "Randomization": {
+ "Type": "None"
+ },
+ "Selector": "SAVR",
+ "SubSelector": "TX",
+ "Validation": {
+ "Settings": {
+ "Type": "None"
+ }
+ }
+ },
+ "PrimaryAttribute": "QID17671698",
+ "SecondaryAttribute": "Now, about q6",
+ "SurveyID": "SV_1MMcjvoGWqh8uUZ",
+ "TertiaryAttribute": null
+ },
+ {
+ "Element": "SQ",
+ "Payload": {
+ "AnalysisType": {
+ "Type": "TableOnly"
+ },
+ "ChoiceOrder": [
+ "1",
+ "2",
+ "3",
+ "4",
+ "5"
+ ],
+ "Choices": {
+ "1": {
+ "Display": "Good"
+ },
+ "2": {
+ "Display": "Mildly"
+ },
+ "3": {
+ "Display": "Moderately"
+ },
+ "4": {
+ "Display": "Severely"
+ },
+ "5": {
+ "Display": "Totally"
+ }
+ },
+ "Configuration": {
+ "QuestionDescriptionOption": "UseText",
+ "VariableCount": 5
+ },
+ "DataExportTag": "Q3",
+ "Language": [],
+ "QuestionDescription": "Now, q3",
+ "QuestionID": "QID17671695",
+ "QuestionText": " Now, q3:",
+ "QuestionText_Unsafe": " Now, q3:",
+ "QuestionType": "MC",
+ "Randomization": {
+ "Type": "None"
+ },
+ "Selector": "SAVR",
+ "SubSelector": "TX",
+ "Validation": {
+ "Settings": {
+ "Type": "None"
+ }
+ }
+ },
+ "PrimaryAttribute": "QID17671695",
+ "SecondaryAttribute": "Now, q3",
+ "SurveyID": "SV_1MMcjvoGWqh8uUZ",
+ "TertiaryAttribute": null
+ },
+ {
+ "Element": "SQ",
+ "Payload": {
+ "AnalysisType": {
+ "Type": "TextEntry"
+ },
+ "DataExportTag": "Q24",
+ "QuestionDescription": "Number of q24",
+ "QuestionID": "QID17671689",
+ "QuestionText": "
Number of q24:",
+ "QuestionText_Unsafe": "
Number of q24:",
+ "QuestionType": "TE",
+ "Randomization": {
+ "Type": "None"
+ },
+ "Selector": "SL",
+ "SubSelector": null,
+ "Validation": {
+ "Settings": {
+ "Type": "None"
+ }
+ }
+ },
+ "PrimaryAttribute": "QID17671689",
+ "SecondaryAttribute": "Number of q24",
+ "SurveyID": "SV_1MMcjvoGWqh8uUZ",
+ "TertiaryAttribute": null
+ },
+ {
+ "Element": "SQ",
+ "Payload": {
+ "DataExportTag": "Q29",
+ "QuestionDescription": "Thank you.",
+ "QuestionID": "QID17671694",
+ "QuestionText": " Thank you.",
+ "QuestionText_Unsafe": " Thank you.",
+ "QuestionType": "DB",
+ "Selector": "PTB",
+ "SubSelector": null
+ },
+ "PrimaryAttribute": "QID17671694",
+ "SecondaryAttribute": "Thank you.",
+ "SurveyID": "SV_1MMcjvoGWqh8uUZ",
+ "TertiaryAttribute": null
+ },
+ {
+ "Element": "SQ",
+ "Payload": {
+ "DataExportTag": "Q1",
+ "QuestionDescription": "We are conducting a test",
+ "QuestionID": "QID17671673",
+ "QuestionText": " We are conducting a test.",
+ "QuestionText_Unsafe": " We are conducting a test.",
+ "QuestionType": "DB",
+ "Selector": "PTB",
+ "SubSelector": null
+ },
+ "PrimaryAttribute": "QID17671673",
+ "SecondaryAttribute": "We are conducting a test",
+ "SurveyID": "SV_1MMcjvoGWqh8uUZ",
+ "TertiaryAttribute": null
+ },
+ {
+ "Element": "SQ",
+ "Payload": {
+ "AnalysisType": {
+ "Type": "TableOnly"
+ },
+ "ChoiceOrder": [
+ "1",
+ "2",
+ "3",
+ "4",
+ "5"
+ ],
+ "Choices": {
+ "1": {
+ "Display": "High"
+ },
+ "2": {
+ "Display": "Above average"
+ },
+ "3": {
+ "Display": "Average"
+ },
+ "4": {
+ "Display": "Below average"
+ },
+ "5": {
+ "Display": "None"
+ }
+ },
+ "Configuration": {
+ "QuestionDescriptionOption": "UseText",
+ "VariableCount": 5
+ },
+ "DataExportTag": "Q4",
+ "Language": [],
+ "QuestionDescription": "What about q4",
+ "QuestionID": "QID17671696",
+ "QuestionText": " What about q4:",
+ "QuestionText_Unsafe": " What about q4:",
+ "QuestionType": "MC",
+ "Randomization": {
+ "Type": "None"
+ },
+ "Selector": "SAVR",
+ "SubSelector": "TX",
+ "Validation": {
+ "Settings": {
+ "Type": "None"
+ }
+ }
+ },
+ "PrimaryAttribute": "QID17671696",
+ "SecondaryAttribute": "What about q4",
+ "SurveyID": "SV_1MMcjvoGWqh8uUZ",
+ "TertiaryAttribute": null
+ },
+ {
+ "Element": "SQ",
+ "Payload": {
+ "AnalysisType": {
+ "Type": "TableOnly"
+ },
+ "Choices": [
+ {
+ "Display": "Live only"
+ },
+ {
+ "Display": "Live"
+ },
+ {
+ "Display": "Live alone"
+ },
+ {
+ "Display": "Other"
+ }
+ ],
+ "Configuration": {
+ "VariableCount": 4
+ },
+ "DataExportTag": "Q25",
+ "QuestionDescription": "What are your q25",
+ "QuestionID": "QID17671690",
+ "QuestionText": " What are your q25?",
+ "QuestionText_Unsafe": " What are your q25?",
+ "QuestionType": "MC",
+ "Randomization": {
+ "Type": "None"
+ },
+ "Selector": "SAVR",
+ "SubSelector": "TX",
+ "Validation": {
+ "Settings": {
+ "Type": "None"
+ }
+ }
+ },
+ "PrimaryAttribute": "QID17671690",
+ "SecondaryAttribute": "What are your q25",
+ "SurveyID": "SV_1MMcjvoGWqh8uUZ",
+ "TertiaryAttribute": null
+ }
+ ],
+ "SurveyEntry": {
+ "CreatorID": "UR_e3UnVvV8g0t4gux",
+ "Deleted": null,
+ "DivisionID": null,
+ "LastAccessed": "0000-00-00 00:00:00",
+ "LastActivated": "0000-00-00 00:00:00",
+ "LastModified": "2015-05-12 09:18:31",
+ "SurveyActiveResponseSet": "RS_5ARGPss19xUGVM1",
+ "SurveyBrandID": "noleadtrial",
+ "SurveyCreationDate": "2015-05-12 09:18:31",
+ "SurveyDescription": "Health Status Survey - Copy",
+ "SurveyExpirationDate": "0000-00-00 00:00:00",
+ "SurveyID": "SV_1MMcjvoGWqh8uUZ",
+ "SurveyLanguage": "EN",
+ "SurveyName": "Health Status Survey - Copy",
+ "SurveyOwnerID": "UR_e3UnVvV8g0t4gux",
+ "SurveyStartDate": "0000-00-00 00:00:00",
+ "SurveyStatus": "Inactive"
+ }
+}
diff --git a/tests/redcap/format_1.csv b/tests/redcap/format_1.csv
new file mode 100644
index 0000000..fd79bd0
--- /dev/null
+++ b/tests/redcap/format_1.csv
@@ -0,0 +1,25 @@
+Variable / Field Name,Form Name,Section Header,Field Type,Field Label,Choices OR Calculations,Field Note,Text Validation Type OR Show Slider Number,Text Validation Min,Text Validation Max,Identifier?,Branching Logic (Show field only if...),Required Field?,Custom Alignment,Question Number (surveys only)
+study_id,demographics,,text,Study ID,,,,,,,,,,
+date_enrolled,demographics,Demographic Attributes,text,Date of consent,,YYYY-MM-DD,date_ymd,,,,,,,
+first_name,demographics,,text,First Name,,,,,,y,,,,
+last_name,demographics,,text,Last Name,,,,,,y,,,,
+address,demographics,Contact Information,notes,"Street, City, State, ZIP",,,,,,y,,,,
+telephone_1,demographics,,text,Phone number,,Include Area Code,phone,,,y,,,,
+telephone_2,demographics,,text,Second phone number,,Include Area Code,phone,,,y,,,,
+email,demographics,,text,E-mail,,,email,,,y,,,,
+sex,demographics,,dropdown,Gender,"0, Female | 1, Male",,,,,,,y,,
+given_birth,demographics,,dropdown,Has the subject given birth before?,"0, No | 1, Yes",,,,,,"[sex] = ""0""",,,
+num_children,demographics,,text,How many times has the subject given birth?,,,integer,0,,,"[sex] = ""0"" and [given_birth] = ""1""",,,
+ethnicity,demographics,,radio,Ethnicity,"0, Left Handed | 1, NOT Left Handed | 2, Unknown / Not Reported",,,,,,,,,
+race,demographics,,checkbox,Race,"0, Human | 1, Android | 2, More Than One Race | 3, Unknown / Not Reported",,,,,,,,,
+sliderq,demographics,,slider,How much slide,,,,,,,,,,
+truefalseq,demographics,,truefalse,T or F,,,,,,,,,,
+yesnoq,demographics,,yesno,Y or N,,,,,,,,,,
+dob,demographics,,text,Date of birth,,YYYY-MM-DD,date_ymd,,,y,,,,
+age,demographics,,calc,Age (years),"round(datediff([dob],'today','y'),0)",,,,,,,,,
+height,demographics,,text,Height (cm),,cm,number,130,215,,,,,
+weight,demographics,,text,Weight (kilograms),,kilograms,integer,35,200,,,,,
+ami,demographics,,calc,AMI,"round(([age]*10000)/(([height])^(2)),1)",kilograms,,,,,,,,
+info,info,Information,text,Date of first treatment,,DD-MM-YYYYY,date_dmy,,,,,,,
+schedule_days,info,,radio,Days of the week patient is tested,"0, Monday-Wednesday-Friday | 1, Tuesday-Thursday-Saturday | 2, Other",,,,,,,,,
+comments,info,General Comments,notes,Comments,,,,,,,,,,
diff --git a/tests/redcap/format_1_c.yaml b/tests/redcap/format_1_c.yaml
new file mode 100644
index 0000000..ede1ed6
--- /dev/null
+++ b/tests/redcap/format_1_c.yaml
@@ -0,0 +1,17 @@
+calculations:
+- description: Age (years)
+ id: age
+ method: python
+ options:
+ expression: rios.conversion.redcap.math.round_(rios.conversion.redcap.date.datediff(assessment["dob"],'today','y'),0)
+ type: float
+- description: AMI
+ id: ami
+ method: python
+ options:
+ expression: rios.conversion.redcap.math.round_((calculations["age"]*10000)/(math.pow(assessment["height"],
+ 2)),1)
+ type: float
+instrument:
+ id: urn:format_1
+ version: '1.0'
diff --git a/tests/redcap/format_1_f.yaml b/tests/redcap/format_1_f.yaml
new file mode 100644
index 0000000..c99b6af
--- /dev/null
+++ b/tests/redcap/format_1_f.yaml
@@ -0,0 +1,262 @@
+defaultLocalization: en
+instrument:
+ id: urn:format_1
+ version: '1.0'
+pages:
+- elements:
+ - options:
+ fieldId: study_id
+ text:
+ en: Study ID
+ widget:
+ type: inputText
+ type: question
+ - options:
+ text:
+ en: Demographic Attributes
+ type: header
+ - options:
+ fieldId: date_enrolled
+ help:
+ en: YYYY-MM-DD
+ text:
+ en: Date of consent
+ widget:
+ type: dateTimePicker
+ type: question
+ - options:
+ fieldId: first_name
+ text:
+ en: First Name
+ widget:
+ type: inputText
+ type: question
+ - options:
+ fieldId: last_name
+ text:
+ en: Last Name
+ widget:
+ type: inputText
+ type: question
+ - options:
+ text:
+ en: Contact Information
+ type: header
+ - options:
+ fieldId: address
+ text:
+ en: Street, City, State, ZIP
+ widget:
+ type: textArea
+ type: question
+ - options:
+ fieldId: telephone_1
+ help:
+ en: Include Area Code
+ text:
+ en: Phone number
+ widget:
+ type: inputText
+ type: question
+ - options:
+ fieldId: telephone_2
+ help:
+ en: Include Area Code
+ text:
+ en: Second phone number
+ widget:
+ type: inputText
+ type: question
+ - options:
+ fieldId: email
+ text:
+ en: E-mail
+ widget:
+ type: inputText
+ type: question
+ - options:
+ enumerations:
+ - id: id_0
+ text:
+ en: Female
+ - id: id_1
+ text:
+ en: Male
+ fieldId: sex
+ text:
+ en: Gender
+ widget:
+ type: dropDown
+ type: question
+ - options:
+ enumerations:
+ - id: id_0
+ text:
+ en: 'No'
+ - id: id_1
+ text:
+ en: 'Yes'
+ events:
+ - action: disable
+ trigger: '!(assessment["sex"] = "0")'
+ fieldId: given_birth
+ text:
+ en: Has the subject given birth before?
+ widget:
+ type: dropDown
+ type: question
+ - options:
+ events:
+ - action: disable
+ trigger: '!(assessment["sex"] = "0" and assessment["given_birth"] = "1")'
+ fieldId: num_children
+ text:
+ en: How many times has the subject given birth?
+ widget:
+ type: inputNumber
+ type: question
+ - options:
+ enumerations:
+ - id: id_0
+ text:
+ en: Left Handed
+ - id: id_1
+ text:
+ en: NOT Left Handed
+ - id: id_2
+ text:
+ en: Unknown / Not Reported
+ fieldId: ethnicity
+ text:
+ en: Ethnicity
+ widget:
+ type: radioGroup
+ type: question
+ - options:
+ enumerations:
+ - id: id_0
+ text:
+ en: Human
+ - id: id_1
+ text:
+ en: Android
+ - id: id_2
+ text:
+ en: More Than One Race
+ - id: id_3
+ text:
+ en: Unknown / Not Reported
+ fieldId: race
+ text:
+ en: Race
+ widget:
+ type: checkGroup
+ type: question
+ - options:
+ fieldId: sliderq
+ text:
+ en: How much slide
+ widget:
+ type: inputNumber
+ type: question
+ - options:
+ enumerations:
+ - id: 'true'
+ text:
+ en: 'True'
+ - id: 'false'
+ text:
+ en: 'False'
+ fieldId: truefalseq
+ text:
+ en: T or F
+ widget:
+ type: radioGroup
+ type: question
+ - options:
+ enumerations:
+ - id: 'yes'
+ text:
+ en: 'Yes'
+ - id: 'no'
+ text:
+ en: 'No'
+ fieldId: yesnoq
+ text:
+ en: Y or N
+ widget:
+ type: radioGroup
+ type: question
+ - options:
+ fieldId: dob
+ help:
+ en: YYYY-MM-DD
+ text:
+ en: Date of birth
+ widget:
+ type: dateTimePicker
+ type: question
+ - options:
+ fieldId: height
+ help:
+ en: cm
+ text:
+ en: Height (cm)
+ widget:
+ type: inputNumber
+ type: question
+ - options:
+ fieldId: weight
+ help:
+ en: kilograms
+ text:
+ en: Weight (kilograms)
+ widget:
+ type: inputNumber
+ type: question
+ id: demographics
+- elements:
+ - options:
+ text:
+ en: Information
+ type: header
+ - options:
+ fieldId: info
+ help:
+ en: DD-MM-YYYYY
+ text:
+ en: Date of first treatment
+ widget:
+ type: dateTimePicker
+ type: question
+ - options:
+ enumerations:
+ - id: id_0
+ text:
+ en: Monday-Wednesday-Friday
+ - id: id_1
+ text:
+ en: Tuesday-Thursday-Saturday
+ - id: id_2
+ text:
+ en: Other
+ fieldId: schedule_days
+ text:
+ en: Days of the week patient is tested
+ widget:
+ type: radioGroup
+ type: question
+ - options:
+ text:
+ en: General Comments
+ type: header
+ - options:
+ fieldId: comments
+ text:
+ en: Comments
+ widget:
+ type: textArea
+ type: question
+ id: info
+title:
+ en: format_1
diff --git a/tests/redcap/format_1_i.yaml b/tests/redcap/format_1_i.yaml
new file mode 100644
index 0000000..a065d5f
--- /dev/null
+++ b/tests/redcap/format_1_i.yaml
@@ -0,0 +1,165 @@
+id: urn:format_1
+record:
+- description: Study ID
+ id: study_id
+ identifiable: false
+ required: false
+ type: text
+- description: Date of consent
+ id: date_enrolled
+ identifiable: false
+ required: false
+ type: dateTime
+- description: First Name
+ id: first_name
+ identifiable: true
+ required: false
+ type: text
+- description: Last Name
+ id: last_name
+ identifiable: true
+ required: false
+ type: text
+- description: Street, City, State, ZIP
+ id: address
+ identifiable: true
+ required: false
+ type: text
+- description: Phone number
+ id: telephone_1
+ identifiable: true
+ required: false
+ type: text
+- description: Second phone number
+ id: telephone_2
+ identifiable: true
+ required: false
+ type: text
+- description: E-mail
+ id: email
+ identifiable: true
+ required: false
+ type: text
+- description: Gender
+ id: sex
+ identifiable: false
+ required: true
+ type:
+ base: enumeration
+ enumerations:
+ id_0: null
+ id_1: null
+- description: Has the subject given birth before?
+ id: given_birth
+ identifiable: false
+ required: false
+ type:
+ base: enumeration
+ enumerations:
+ id_0: null
+ id_1: null
+- description: How many times has the subject given birth?
+ id: num_children
+ identifiable: false
+ required: false
+ type:
+ base: integer
+ range:
+ min: 0
+- description: Ethnicity
+ id: ethnicity
+ identifiable: false
+ required: false
+ type:
+ base: enumeration
+ enumerations:
+ id_0: null
+ id_1: null
+ id_2: null
+- description: Race
+ id: race
+ identifiable: false
+ required: false
+ type:
+ base: enumerationSet
+ enumerations:
+ id_0: null
+ id_1: null
+ id_2: null
+ id_3: null
+- description: How much slide
+ id: sliderq
+ identifiable: false
+ required: false
+ type:
+ base: float
+ range:
+ max: 100.0
+ min: 0.0
+- description: T or F
+ id: truefalseq
+ identifiable: false
+ required: false
+ type:
+ base: enumeration
+ enumerations:
+ 'false':
+ description: 'False'
+ 'true':
+ description: 'True'
+- description: Y or N
+ id: yesnoq
+ identifiable: false
+ required: false
+ type:
+ base: enumeration
+ enumerations:
+ 'no':
+ description: 'No'
+ 'yes':
+ description: 'Yes'
+- description: Date of birth
+ id: dob
+ identifiable: true
+ required: false
+ type: dateTime
+- description: Height (cm)
+ id: height
+ identifiable: false
+ required: false
+ type:
+ base: float
+ range:
+ max: 215.0
+ min: 130.0
+- description: Weight (kilograms)
+ id: weight
+ identifiable: false
+ required: false
+ type:
+ base: integer
+ range:
+ max: 200
+ min: 35
+- description: Date of first treatment
+ id: info
+ identifiable: false
+ required: false
+ type: dateTime
+- description: Days of the week patient is tested
+ id: schedule_days
+ identifiable: false
+ required: false
+ type:
+ base: enumeration
+ enumerations:
+ id_0: null
+ id_1: null
+ id_2: null
+- description: Comments
+ id: comments
+ identifiable: false
+ required: false
+ type: text
+title: format_1
+version: '1.0'
diff --git a/tests/test_rios_converter.py b/tests/test_rios_converter.py
new file mode 100644
index 0000000..a85c292
--- /dev/null
+++ b/tests/test_rios_converter.py
@@ -0,0 +1,84 @@
+from rex.core import get_settings
+from rex.core import Rex
+from webob import Request
+
+def test_pages():
+ app = Rex('rios.converter')
+ app.on()
+ print Request.blank('/').get_response(app)
+ print Request.blank('/convert/to').get_response(app)
+ print Request.blank('/convert/from').get_response(app)
+
+ settings = get_settings()
+ settings.temp_dir = 'tests/sandbox'
+
+ with open('tests/redcap/format_1.csv') as input_file:
+ print Request.blank('/convert/to/rios', POST={
+ 'system': 'redcap',
+ 'format': 'yaml',
+ 'instrument_title':'Test title',
+ 'instrument_id': 'id0',
+ 'instrument_version':'1.6',
+ 'localization':'en',
+ 'outname':'red2rio-out',
+ 'infile': ('format_1.csv', input_file),
+ }).get_response(app)
+
+ with open('tests/qualtrics/test_1.qsf') as input_file:
+ print Request.blank('/convert/to/rios', POST={
+ 'system': 'qualtrics',
+ 'format': 'yaml',
+ 'instrument_title':'Test title',
+ 'instrument_id': 'id0',
+ 'instrument_version':'1.6',
+ 'localization':'en',
+ 'outname':'q2rio-out',
+ 'infile': ('test_1.qsf', input_file),
+ }).get_response(app)
+ app.off()
+
+def test_rios_to_redcap():
+ app = Rex('rios.converter')
+ app.on()
+ settings = get_settings()
+ settings.temp_dir = 'tests/sandbox'
+
+ i_file = open('tests/redcap/format_1_i.yaml')
+ f_file = open('tests/redcap/format_1_f.yaml')
+ c_file = open('tests/redcap/format_1_c.yaml')
+ print Request.blank('/convert/from/rios', POST={
+ 'system': 'redcap',
+ 'format': 'yaml',
+ 'localization':'en',
+ 'instrument_file': ('format_1_i.yaml', i_file),
+ 'form_file': ('format_1_f.yaml', f_file),
+ 'calculationset_file': ('format_1_c.yaml', c_file),
+ 'outname':'rio2red-out.csv',
+ }).get_response(app)
+ i_file.close()
+ f_file.close()
+ c_file.close()
+ app.off()
+
+def test_rios_to_qualtrics():
+ app = Rex('rios.converter')
+ app.on()
+ settings = get_settings()
+ settings.temp_dir = 'tests/sandbox'
+
+ i_file = open('tests/redcap/format_1_i.yaml')
+ f_file = open('tests/redcap/format_1_f.yaml')
+ c_file = open('tests/redcap/format_1_c.yaml')
+ print Request.blank('/convert/from/rios', POST={
+ 'system': 'qualtrics',
+ 'format': 'yaml',
+ 'localization':'en',
+ 'instrument_file': ('format_1_i.yaml', i_file),
+ 'form_file': ('format_1_f.yaml', f_file),
+ 'calculationset_file': ('format_1_c.yaml', c_file),
+ 'outname':'rio2q-out.txt',
+ }).get_response(app)
+ i_file.close()
+ f_file.close()
+ c_file.close()
+ app.off()
diff --git a/tox.ini b/tox.ini
new file mode 100644
index 0000000..a768335
--- /dev/null
+++ b/tox.ini
@@ -0,0 +1,9 @@
+[tox]
+envlist = py27, py32, py33, py34
+
+[testenv]
+deps =
+ nose
+ coverage>=3.7,<4
+commands = nosetests
+