From 6fd623e5b7a83fbf9fd5e0e240be423a34bbda3f Mon Sep 17 00:00:00 2001 From: Davis Raymond Muro Date: Tue, 3 Mar 2020 10:28:36 +0300 Subject: [PATCH 1/9] Upgrade pyxform to v1.1.0 --- requirements/base.pip | 144 +++++++++++++++++++-------------------- requirements/dev.pip | 155 +++++++++++++++++++++--------------------- 2 files changed, 150 insertions(+), 149 deletions(-) diff --git a/requirements/base.pip b/requirements/base.pip index ce635b375f..c2869de5cb 100644 --- a/requirements/base.pip +++ b/requirements/base.pip @@ -4,12 +4,12 @@ # # pip-compile --output-file=requirements/base.pip requirements/base.in # --e git+https://github.com/onaio/django-digest.git@eb85c7ae19d70d4690eeb20983e94b9fde8ab8c2#egg=django-digest --e git+https://github.com/onaio/django-multidb-router.git@f711368180d58eef87eda54fadfd5f8355623d52#egg=django-multidb-router --e git+https://github.com/onaio/oauth2client.git@75dfdee77fb640ae30469145c66440571dfeae5c#egg=oauth2client --e git+https://github.com/onaio/floip-py.git@3bbf5c76b34ec49c438a3099ab848870514d1e50#egg=pyfloip --e git+https://github.com/onaio/python-digest.git@3af1bd0ef6114e24bf23d0e8fd9d7ebf389845d1#egg=python-digest --e git+https://github.com/onaio/python-json2xlsclient.git@62b4645f7b4f2684421a13ce98da0331a9dd66a0#egg=python-json2xlsclient +-e git+https://github.com/onaio/django-digest.git@eb85c7ae19d70d4690eeb20983e94b9fde8ab8c2#egg=django-digest # via -r requirements/base.in +-e git+https://github.com/onaio/django-multidb-router.git@f711368180d58eef87eda54fadfd5f8355623d52#egg=django-multidb-router # via -r requirements/base.in +-e git+https://github.com/onaio/oauth2client.git@75dfdee77fb640ae30469145c66440571dfeae5c#egg=oauth2client # via -r requirements/base.in +-e git+https://github.com/onaio/floip-py.git@3bbf5c76b34ec49c438a3099ab848870514d1e50#egg=pyfloip # via -r requirements/base.in +-e git+https://github.com/onaio/python-digest.git@3af1bd0ef6114e24bf23d0e8fd9d7ebf389845d1#egg=python-digest # via -r requirements/base.in +-e git+https://github.com/onaio/python-json2xlsclient.git@62b4645f7b4f2684421a13ce98da0331a9dd66a0#egg=python-json2xlsclient # via -r requirements/base.in alabaster==0.7.12 # via sphinx amqp==2.5.2 # via kombu argparse==1.4.0 # via unittest2 @@ -19,50 +19,50 @@ billiard==3.6.2.0 # via celery boto3==1.12.4 # via tabulator botocore==1.15.4 # via boto3, s3transfer cchardet==2.1.5 # via datapackage, tabulator -celery==4.4.0 # via django-celery-results +celery==4.4.0 # via django-celery-results, onadata certifi==2019.11.28 # via requests cffi==1.14.0 # via cryptography chardet==3.0.4 # via requests click==7.0 # via datapackage, tableschema, tabulator -cryptography==2.8 -datapackage==1.11.1 +cryptography==2.8 # via onadata +datapackage==1.11.1 # via pyfloip defusedxml==0.6.0 # via djangorestframework-xml -dict2xml==1.6.1 -django-activity-stream==0.8.0 -django-celery-results==1.2.0 -django-cors-headers==3.2.1 -django-debug-toolbar==2.2 -django-filter==2.2.0 -django-guardian==2.1.0 # via djangorestframework-guardian -django-nose==1.4.6 -django-oauth-toolkit==1.2.0 -django-ordered-model==3.3.0 -django-query-builder==1.2.0 -django-registration-redux==2.7 +dict2xml==1.6.1 # via onadata +django-activity-stream==0.8.0 # via onadata +django-celery-results==1.2.0 # via onadata +django-cors-headers==3.2.1 # via onadata +django-debug-toolbar==2.2 # via onadata +django-filter==2.2.0 # via onadata +django-guardian==2.1.0 # via djangorestframework-guardian, onadata +django-nose==1.4.6 # via onadata +django-oauth-toolkit==1.2.0 # via onadata +django-ordered-model==3.3.0 # via onadata +django-query-builder==1.2.0 # via onadata +django-registration-redux==2.7 # via onadata django-render-block==0.6 # via django-templated-email -django-reversion==3.0.7 -django-taggit==1.2.0 -django-templated-email==2.3.0 -django==2.2.10 # via django-cors-headers, django-debug-toolbar, django-filter, django-guardian, django-oauth-toolkit, django-query-builder, django-render-block, django-reversion, django-taggit, djangorestframework, djangorestframework-guardian, djangorestframework-jsonapi, jsonfield -djangorestframework-csv==2.1.0 -djangorestframework-gis==0.15 -djangorestframework-guardian==0.3.0 -djangorestframework-jsonapi==3.1.0 -djangorestframework-jsonp==1.0.2 -djangorestframework-xml==1.4.0 -djangorestframework==3.11.0 # via djangorestframework-csv, djangorestframework-gis, djangorestframework-guardian, djangorestframework-jsonapi +django-reversion==3.0.7 # via onadata +django-taggit==1.2.0 # via onadata +django-templated-email==2.3.0 # via onadata +django==2.2.10 # via django-cors-headers, django-debug-toolbar, django-filter, django-oauth-toolkit, django-query-builder, django-render-block, django-reversion, django-taggit, djangorestframework, djangorestframework-guardian, djangorestframework-jsonapi, jsonfield, onadata +djangorestframework-csv==2.1.0 # via onadata +djangorestframework-gis==0.15 # via onadata +djangorestframework-guardian==0.3.0 # via onadata +djangorestframework-jsonapi==3.1.0 # via onadata +djangorestframework-jsonp==1.0.2 # via onadata +djangorestframework-xml==1.4.0 # via onadata +djangorestframework==3.11.0 # via djangorestframework-csv, djangorestframework-gis, djangorestframework-guardian, djangorestframework-jsonapi, onadata docutils==0.15.2 # via botocore, sphinx -dpath==2.0.1 -elaphe3==0.2.0 +dpath==2.0.1 # via onadata +elaphe3==0.2.0 # via onadata entrypoints==0.3 # via flake8 et-xmlfile==1.0.1 # via openpyxl -flake8==3.7.9 +flake8==3.7.9 # via onadata fleming==0.5.0 # via django-query-builder formencode==1.3.1 # via pyxform -future==0.18.2 -geojson==2.5.0 -httmock==1.3.0 -httplib2==0.17.0 +future==0.18.2 # via python-json2xlsclient +geojson==2.5.0 # via onadata +httmock==1.3.0 # via onadata +httplib2==0.17.0 # via oauth2client, onadata idna==2.9 # via requests ijson==2.6.1 # via tabulator imagesize==1.2.0 # via sphinx @@ -72,55 +72,55 @@ isodate==0.6.0 # via tableschema jdcal==1.4.1 # via openpyxl jinja2==2.11.1 # via sphinx jmespath==0.9.4 # via boto3, botocore -jsonfield==0.9.23 +jsonfield==0.9.23 # via onadata jsonlines==1.2.0 # via tabulator -jsonpickle==1.3 +jsonpickle==1.3 # via onadata jsonpointer==2.0 # via datapackage jsonschema==3.2.0 # via datapackage, tableschema kombu==4.6.7 # via celery linear-tsv==1.1.0 # via tabulator linecache2==1.0.0 # via traceback2 -lxml==4.5.0 -markdown==3.2.1 +lxml==4.5.0 # via onadata +markdown==3.2.1 # via onadata markupsafe==1.1.1 # via jinja2 mccabe==0.6.1 # via flake8 -mock==4.0.1 -modilabs-python-utils==0.1.5 +mock==4.0.1 # via onadata +modilabs-python-utils==0.1.5 # via onadata nose==1.3.7 # via django-nose -numpy==1.18.1 +numpy==1.18.1 # via onadata oauthlib==3.1.0 # via django-oauth-toolkit -openpyxl==3.0.3 # via tabulator +openpyxl==3.0.3 # via onadata, tabulator packaging==20.1 # via sphinx -paho-mqtt==1.5.0 -pillow==7.0.0 # via elaphe3 -psycopg2==2.8.4 -pyasn1-modules==0.2.8 -pyasn1==0.4.8 # via pyasn1-modules, rsa +paho-mqtt==1.5.0 # via onadata +pillow==7.0.0 # via elaphe3, onadata +psycopg2==2.8.4 # via onadata +pyasn1-modules==0.2.8 # via oauth2client +pyasn1==0.4.8 # via oauth2client, pyasn1-modules, rsa pycodestyle==2.5.0 # via flake8 pycparser==2.19 # via cffi pyflakes==2.1.1 # via flake8 pygments==2.5.2 # via sphinx -pyjwt==1.7.1 -pylibmc==1.6.1 -pymongo==3.10.1 +pyjwt==1.7.1 # via onadata +pylibmc==1.6.1 # via onadata +pymongo==3.10.1 # via onadata pyparsing==2.4.6 # via packaging pyrsistent==0.15.7 # via jsonschema -python-dateutil==2.8.1 # via botocore, fleming, tableschema -python-memcached==1.59 -pytz==2019.3 # via babel, celery, django, django-query-builder, fleming -pyxform==0.15.1 -raven==6.10.0 -recaptcha-client==1.0.6 -requests-mock==1.7.0 -requests==2.23.0 # via datapackage, django-oauth-toolkit, httmock, requests-mock, sphinx, tableschema, tabulator +python-dateutil==2.8.1 # via botocore, fleming, onadata, tableschema +python-memcached==1.59 # via onadata +pytz==2019.3 # via babel, celery, django, django-query-builder, fleming, onadata +pyxform==1.1.0 # via onadata, pyfloip +raven==6.10.0 # via onadata +recaptcha-client==1.0.6 # via onadata +requests-mock==1.7.0 # via onadata +requests==2.23.0 # via datapackage, django-oauth-toolkit, httmock, onadata, python-json2xlsclient, requests-mock, sphinx, tableschema, tabulator rfc3986==1.3.2 # via tableschema -rsa==4.0 +rsa==4.0 # via oauth2client s3transfer==0.3.3 # via boto3 -savreaderwriter==3.4.2 -simplejson==3.17.0 -six==1.14.0 # via cryptography, datapackage, dict2xml, django-query-builder, django-templated-email, djangorestframework-csv, isodate, jsonlines, jsonschema, linear-tsv, packaging, pyrsistent, python-dateutil, python-memcached, requests-mock, tableschema, tabulator, unittest2 +savreaderwriter==3.4.2 # via onadata +simplejson==3.17.0 # via onadata +six==1.14.0 # via cryptography, datapackage, dict2xml, django-query-builder, django-templated-email, djangorestframework-csv, isodate, jsonlines, jsonschema, linear-tsv, oauth2client, packaging, pyrsistent, python-dateutil, python-memcached, requests-mock, tableschema, tabulator, unittest2 snowballstemmer==2.0.0 # via sphinx -sphinx==2.4.2 +sphinx==2.4.2 # via onadata sphinxcontrib-applehelp==1.0.1 # via sphinx sphinxcontrib-devhelp==1.0.1 # via sphinx sphinxcontrib-htmlhelp==1.0.2 # via sphinx @@ -132,11 +132,11 @@ sqlparse==0.3.0 # via django, django-debug-toolbar tableschema==1.13.1 # via datapackage tabulator==1.35.0 # via datapackage, tableschema traceback2==1.4.0 # via unittest2 -unicodecsv==0.14.1 # via datapackage, djangorestframework-csv, pyxform, tableschema, tabulator +unicodecsv==0.14.1 # via datapackage, djangorestframework-csv, onadata, pyxform, tableschema, tabulator unittest2==1.1.0 # via pyxform urllib3==1.25.8 # via botocore, requests -uwsgi==2.0.18 +uwsgi==2.0.18 # via onadata vine==1.3.0 # via amqp, celery -xlrd==1.2.0 # via pyxform, tabulator -xlwt==1.3.0 +xlrd==1.2.0 # via onadata, pyxform, tabulator +xlwt==1.3.0 # via onadata zipp==3.0.0 # via importlib-metadata diff --git a/requirements/dev.pip b/requirements/dev.pip index c4a1b3e733..6a47ff83b1 100644 --- a/requirements/dev.pip +++ b/requirements/dev.pip @@ -4,12 +4,12 @@ # # pip-compile --output-file=requirements/dev.pip requirements/dev.in # --e git+https://github.com/onaio/django-digest.git@eb85c7ae19d70d4690eeb20983e94b9fde8ab8c2#egg=django-digest --e git+https://github.com/onaio/django-multidb-router.git@f711368180d58eef87eda54fadfd5f8355623d52#egg=django-multidb-router --e git+https://github.com/onaio/oauth2client.git@75dfdee77fb640ae30469145c66440571dfeae5c#egg=oauth2client --e git+https://github.com/onaio/floip-py.git@3bbf5c76b34ec49c438a3099ab848870514d1e50#egg=pyfloip --e git+https://github.com/onaio/python-digest.git@3af1bd0ef6114e24bf23d0e8fd9d7ebf389845d1#egg=python-digest --e git+https://github.com/onaio/python-json2xlsclient.git@62b4645f7b4f2684421a13ce98da0331a9dd66a0#egg=python-json2xlsclient +-e git+https://github.com/onaio/django-digest.git@eb85c7ae19d70d4690eeb20983e94b9fde8ab8c2#egg=django-digest # via -r requirements/base.in +-e git+https://github.com/onaio/django-multidb-router.git@f711368180d58eef87eda54fadfd5f8355623d52#egg=django-multidb-router # via -r requirements/base.in +-e git+https://github.com/onaio/oauth2client.git@75dfdee77fb640ae30469145c66440571dfeae5c#egg=oauth2client # via -r requirements/base.in +-e git+https://github.com/onaio/floip-py.git@3bbf5c76b34ec49c438a3099ab848870514d1e50#egg=pyfloip # via -r requirements/base.in +-e git+https://github.com/onaio/python-digest.git@3af1bd0ef6114e24bf23d0e8fd9d7ebf389845d1#egg=python-digest # via -r requirements/base.in +-e git+https://github.com/onaio/python-json2xlsclient.git@62b4645f7b4f2684421a13ce98da0331a9dd66a0#egg=python-json2xlsclient # via -r requirements/base.in alabaster==0.7.12 # via sphinx amqp==2.5.2 # via kombu appnope==0.1.0 # via ipython @@ -22,123 +22,124 @@ billiard==3.6.2.0 # via celery boto3==1.12.4 # via tabulator botocore==1.15.4 # via boto3, s3transfer cchardet==2.1.5 # via datapackage, tabulator -celery==4.4.0 # via django-celery-results +celery==4.4.0 # via django-celery-results, onadata certifi==2019.11.28 # via requests cffi==1.14.0 # via cryptography chardet==3.0.4 # via requests click==7.0 # via datapackage, tableschema, tabulator -cryptography==2.8 -datapackage==1.11.1 +cryptography==2.8 # via onadata +datapackage==1.11.1 # via pyfloip decorator==4.4.1 # via ipython, traitlets defusedxml==0.6.0 # via djangorestframework-xml -dict2xml==1.6.1 -django-activity-stream==0.8.0 -django-celery-results==1.2.0 -django-cors-headers==3.2.1 -django-debug-toolbar==2.2 -django-extensions==2.2.8 -django-filter==2.2.0 -django-guardian==2.2.0 -django-nose==1.4.6 -django-oauth-toolkit==1.2.0 -django-ordered-model==3.3.0 -django-query-builder==1.2.0 -django-registration-redux==2.7 +dict2xml==1.6.1 # via onadata +django-activity-stream==0.8.0 # via onadata +django-celery-results==1.2.0 # via onadata +django-cors-headers==3.2.1 # via onadata +django-debug-toolbar==2.2 # via onadata +django-extensions==2.2.8 # via -r requirements/dev.in +django-filter==2.2.0 # via onadata +django-guardian==2.2.0 # via djangorestframework-guardian, onadata +django-nose==1.4.6 # via onadata +django-oauth-toolkit==1.2.0 # via onadata +django-ordered-model==3.3.0 # via onadata +django-query-builder==1.2.0 # via onadata +django-registration-redux==2.7 # via onadata django-render-block==0.6 # via django-templated-email -django-reversion==3.0.7 -django-taggit==1.2.0 -django-templated-email==2.3.0 -django==2.2.10 # via django-cors-headers, django-debug-toolbar, django-filter, django-guardian, django-oauth-toolkit, django-query-builder, django-render-block, django-reversion, django-taggit, djangorestframework, djangorestframework-jsonapi, jsonfield -djangorestframework-csv==2.1.0 -djangorestframework-gis==0.15 -djangorestframework-jsonapi==3.1.0 -djangorestframework-jsonp==1.0.2 -djangorestframework-xml==1.4.0 -djangorestframework==3.11.0 # via djangorestframework-csv, djangorestframework-gis, djangorestframework-jsonapi +django-reversion==3.0.7 # via onadata +django-taggit==1.2.0 # via onadata +django-templated-email==2.3.0 # via onadata +django==2.2.10 # via django-cors-headers, django-debug-toolbar, django-filter, django-guardian, django-oauth-toolkit, django-query-builder, django-render-block, django-reversion, django-taggit, djangorestframework, djangorestframework-guardian, djangorestframework-jsonapi, jsonfield, onadata +djangorestframework-csv==2.1.0 # via onadata +djangorestframework-gis==0.15 # via onadata +djangorestframework-guardian==0.3.0 # via onadata +djangorestframework-jsonapi==3.1.0 # via onadata +djangorestframework-jsonp==1.0.2 # via onadata +djangorestframework-xml==1.4.0 # via onadata +djangorestframework==3.11.0 # via djangorestframework-csv, djangorestframework-gis, djangorestframework-guardian, djangorestframework-jsonapi, onadata docutils==0.15.2 # via botocore, sphinx -dpath==2.0.1 -elaphe3==0.2.0 +dpath==2.0.1 # via onadata +elaphe3==0.2.0 # via onadata entrypoints==0.3 # via flake8 et-xmlfile==1.0.1 # via openpyxl -flake8==3.7.9 +flake8==3.7.9 # via onadata fleming==0.5.0 # via django-query-builder formencode==1.3.1 # via pyxform -future==0.18.2 -geojson==2.5.0 -httmock==1.3.0 -httplib2==0.17.0 +future==0.18.2 # via python-json2xlsclient +geojson==2.5.0 # via onadata +httmock==1.3.0 # via onadata +httplib2==0.17.0 # via oauth2client, onadata idna==2.9 # via requests ijson==2.6.1 # via tabulator imagesize==1.2.0 # via sphinx importlib-metadata==1.5.0 # via jsonschema, kombu inflection==0.3.1 # via djangorestframework-jsonapi -ipdb==0.12.3 +ipdb==0.12.3 # via -r requirements/dev.in ipython-genutils==0.2.0 # via traitlets ipython==7.12.0 # via ipdb isodate==0.6.0 # via tableschema -isort==4.3.21 +isort==4.3.21 # via -r requirements/dev.in, pylint jdcal==1.4.1 # via openpyxl jedi==0.16.0 # via ipython jinja2==2.11.1 # via sphinx jmespath==0.9.4 # via boto3, botocore -jsonfield==0.9.23 +jsonfield==0.9.23 # via onadata jsonlines==1.2.0 # via tabulator -jsonpickle==1.3 +jsonpickle==1.3 # via onadata jsonpointer==2.0 # via datapackage jsonschema==3.2.0 # via datapackage, tableschema kombu==4.6.7 # via celery lazy-object-proxy==1.4.3 # via astroid linear-tsv==1.1.0 # via tabulator linecache2==1.0.0 # via traceback2 -lxml==4.5.0 -markdown==3.2.1 +lxml==4.5.0 # via onadata +markdown==3.2.1 # via onadata markupsafe==1.1.1 # via jinja2 mccabe==0.6.1 # via flake8, pylint -mock==4.0.1 -modilabs-python-utils==0.1.5 +mock==4.0.1 # via onadata +modilabs-python-utils==0.1.5 # via onadata nose==1.3.7 # via django-nose -numpy==1.18.1 +numpy==1.18.1 # via onadata oauthlib==3.1.0 # via django-oauth-toolkit -openpyxl==3.0.3 # via tabulator +openpyxl==3.0.3 # via onadata, tabulator packaging==20.1 # via sphinx -paho-mqtt==1.5.0 +paho-mqtt==1.5.0 # via onadata parso==0.6.1 # via jedi pexpect==4.8.0 # via ipython pickleshare==0.7.5 # via ipython -pillow==7.0.0 # via elaphe3 +pillow==7.0.0 # via elaphe3, onadata prompt-toolkit==3.0.3 # via ipython -psycopg2==2.8.4 +psycopg2==2.8.4 # via onadata ptyprocess==0.6.0 # via pexpect -pyasn1-modules==0.2.8 -pyasn1==0.4.8 # via pyasn1-modules, rsa +pyasn1-modules==0.2.8 # via oauth2client +pyasn1==0.4.8 # via oauth2client, pyasn1-modules, rsa pycodestyle==2.5.0 # via flake8 pycparser==2.19 # via cffi pyflakes==2.1.1 # via flake8 pygments==2.5.2 # via ipython, sphinx -pyjwt==1.7.1 -pylibmc==1.6.1 -pylint-django==0.11.1 +pyjwt==1.7.1 # via onadata +pylibmc==1.6.1 # via onadata +pylint-django==0.11.1 # via -r requirements/dev.in pylint-plugin-utils==0.6 # via pylint-django -pylint==1.9.4 -pymongo==3.10.1 +pylint==1.9.4 # via -r requirements/dev.in, pylint-django, pylint-plugin-utils +pymongo==3.10.1 # via onadata pyparsing==2.4.6 # via packaging pyrsistent==0.15.7 # via jsonschema -python-dateutil==2.8.1 # via botocore, fleming, tableschema -python-memcached==1.59 -pytz==2019.3 # via babel, celery, django, django-query-builder, fleming -pyxform==0.15.1 -raven==6.10.0 -recaptcha-client==1.0.6 -requests-mock==1.7.0 -requests==2.23.0 # via datapackage, django-oauth-toolkit, httmock, requests-mock, sphinx, tableschema, tabulator +python-dateutil==2.8.1 # via botocore, fleming, onadata, tableschema +python-memcached==1.59 # via onadata +pytz==2019.3 # via babel, celery, django, django-query-builder, fleming, onadata +pyxform==1.1.0 # via onadata, pyfloip +raven==6.10.0 # via onadata +recaptcha-client==1.0.6 # via onadata +requests-mock==1.7.0 # via onadata +requests==2.23.0 # via datapackage, django-oauth-toolkit, httmock, onadata, python-json2xlsclient, requests-mock, sphinx, tableschema, tabulator rfc3986==1.3.2 # via tableschema -rsa==4.0 +rsa==4.0 # via oauth2client s3transfer==0.3.3 # via boto3 -savreaderwriter==3.4.2 -simplejson==3.17.0 -six==1.14.0 # via astroid, cryptography, datapackage, dict2xml, django-extensions, django-query-builder, django-templated-email, djangorestframework-csv, isodate, jsonlines, jsonschema, linear-tsv, packaging, pylint, pyrsistent, python-dateutil, python-memcached, requests-mock, tableschema, tabulator, traitlets, unittest2 +savreaderwriter==3.4.2 # via onadata +simplejson==3.17.0 # via onadata +six==1.14.0 # via astroid, cryptography, datapackage, dict2xml, django-extensions, django-query-builder, django-templated-email, djangorestframework-csv, isodate, jsonlines, jsonschema, linear-tsv, oauth2client, packaging, pylint, pyrsistent, python-dateutil, python-memcached, requests-mock, tableschema, tabulator, traitlets, unittest2 snowballstemmer==2.0.0 # via sphinx -sphinx==2.4.2 +sphinx==2.4.2 # via onadata sphinxcontrib-applehelp==1.0.1 # via sphinx sphinxcontrib-devhelp==1.0.1 # via sphinx sphinxcontrib-htmlhelp==1.0.2 # via sphinx @@ -151,14 +152,14 @@ tableschema==1.13.1 # via datapackage tabulator==1.35.0 # via datapackage, tableschema traceback2==1.4.0 # via unittest2 traitlets==4.3.3 # via ipython -unicodecsv==0.14.1 # via datapackage, djangorestframework-csv, pyxform, tableschema, tabulator +unicodecsv==0.14.1 # via datapackage, djangorestframework-csv, onadata, pyxform, tableschema, tabulator unittest2==1.1.0 # via pyxform urllib3==1.25.8 # via botocore, requests -uwsgi==2.0.18 +uwsgi==2.0.18 # via onadata vine==1.3.0 # via amqp, celery wcwidth==0.1.8 # via prompt-toolkit wrapt==1.12.0 # via astroid -xlrd==1.2.0 # via pyxform, tabulator -xlwt==1.3.0 -yapf==0.29.0 +xlrd==1.2.0 # via onadata, pyxform, tabulator +xlwt==1.3.0 # via onadata +yapf==0.29.0 # via -r requirements/dev.in zipp==3.0.0 # via importlib-metadata From 4f5ee332dcb671671080b79b11cb3c8f55e1349f Mon Sep 17 00:00:00 2001 From: Davis Raymond Muro Date: Tue, 25 Feb 2020 10:19:00 +0300 Subject: [PATCH 2/9] Add MULTIPLE_SELECT_TYPE and SELECT_BIND_TYPE tags Add MULTI_SELECT_TYPE and SELECT_BIND_TYPE tags removing the previously used SELECT_ONE and SELECT_MULTIPLE variables. More info: https://github.com/XLSForm/pyxform/pull/410 --- onadata/apps/logger/models/xform.py | 7 ++++--- onadata/libs/utils/common_tags.py | 1 + onadata/libs/utils/csv_builder.py | 7 +++++-- onadata/libs/utils/export_builder.py | 15 +++++++-------- 4 files changed, 17 insertions(+), 13 deletions(-) diff --git a/onadata/apps/logger/models/xform.py b/onadata/apps/logger/models/xform.py index 1764a5d25a..fedfeac54b 100644 --- a/onadata/apps/logger/models/xform.py +++ b/onadata/apps/logger/models/xform.py @@ -43,7 +43,8 @@ NOTES, SUBMISSION_TIME, SUBMITTED_BY, TAGS, TOTAL_MEDIA, UUID, VERSION, REVIEW_STATUS, - REVIEW_COMMENT) + REVIEW_COMMENT, + MULTIPLE_SELECT_TYPE) from onadata.libs.utils.model_tools import queryset_iterator from onadata.libs.utils.mongo import _encode_for_mongo @@ -437,7 +438,8 @@ def xpaths(self, # replace the single question column with a column for each # item in a select all that apply question. - if survey_element.bind.get(u'type') == u'select': + if survey_element.bind.get(u'type') == u'string' \ + and survey_element.type == MULTIPLE_SELECT_TYPE: result.pop() for child in survey_element.children: result.append('/'.join([path, child.name])) @@ -475,7 +477,6 @@ def get_headers(self, include_additional_headers=False): """ Return a list of headers for a csv file. """ - def shorten(xpath): xpath_list = xpath.split('/') return '/'.join(xpath_list[2:]) diff --git a/onadata/libs/utils/common_tags.py b/onadata/libs/utils/common_tags.py index b9928b4875..de7bbfa669 100644 --- a/onadata/libs/utils/common_tags.py +++ b/onadata/libs/utils/common_tags.py @@ -83,6 +83,7 @@ TEXTIT = 'textit' OSM = 'osm' +SELECT_BIND_TYPE = 'string' MULTIPLE_SELECT_TYPE = 'select all that apply' GROUPNAME_REMOVED_FLAG = 'group-name-removed' DATAVIEW_EXPORT = U'dataview' diff --git a/onadata/libs/utils/csv_builder.py b/onadata/libs/utils/csv_builder.py index b687fa40b5..0b5d6e7bed 100644 --- a/onadata/libs/utils/csv_builder.py +++ b/onadata/libs/utils/csv_builder.py @@ -24,7 +24,9 @@ SUBMISSION_TIME, SUBMITTED_BY, TAGS, TOTAL_MEDIA, UUID, VERSION, XFORM_ID_STRING, REVIEW_STATUS, - REVIEW_COMMENT) + REVIEW_COMMENT, + MULTIPLE_SELECT_TYPE, + SELECT_BIND_TYPE) from onadata.libs.utils.export_builder import (get_choice_label, get_value_or_attachment_uri, track_task_progress) @@ -222,7 +224,8 @@ def _collect_select_multiples(cls, dd, language=None): select_multiples = [] select_multiple_elements = [ e for e in dd.get_survey_elements_with_choices() - if e.bind.get('type') == 'select' + if e.bind.get('type') == SELECT_BIND_TYPE + and e.type == MULTIPLE_SELECT_TYPE ] for e in select_multiple_elements: xpath = e.get_abbreviated_xpath() diff --git a/onadata/libs/utils/export_builder.py b/onadata/libs/utils/export_builder.py index 360749ce92..529f29ab3e 100644 --- a/onadata/libs/utils/export_builder.py +++ b/onadata/libs/utils/export_builder.py @@ -29,15 +29,12 @@ from onadata.apps.viewer.models.data_dictionary import DataDictionary from onadata.libs.utils.common_tags import ( ATTACHMENTS, BAMBOO_DATASET_ID, DELETEDAT, DURATION, GEOLOCATION, - ID, INDEX, MULTIPLE_SELECT_TYPE, NOTES, PARENT_INDEX, + ID, INDEX, MULTIPLE_SELECT_TYPE, SELECT_ONE, NOTES, PARENT_INDEX, PARENT_TABLE_NAME, REPEAT_INDEX_TAGS, SAV_255_BYTES_TYPE, SAV_NUMERIC_TYPE, STATUS, SUBMISSION_TIME, SUBMITTED_BY, TAGS, UUID, - VERSION, XFORM_ID_STRING, REVIEW_STATUS, REVIEW_COMMENT) + VERSION, XFORM_ID_STRING, REVIEW_STATUS, REVIEW_COMMENT, SELECT_BIND_TYPE) from onadata.libs.utils.mongo import _decode_from_mongo, _is_invalid_for_mongo - # the bind type of select multiples that we use to compare -MULTIPLE_SELECT_BIND_TYPE = 'select' -SELECT_ONE_BIND_TYPE = 'select1' GEOPOINT_BIND_TYPE = 'geopoint' OSM_BIND_TYPE = 'osm' DEFAULT_UPDATE_BATCH = 100 @@ -475,7 +472,8 @@ def build_sections( {child_xpath: _encode_for_mongo(child_xpath)}) # if its a select multiple, make columns out of its choices - if child.bind.get('type') == MULTIPLE_SELECT_BIND_TYPE: + if child.bind.get('type') == SELECT_BIND_TYPE \ + and child.type == MULTIPLE_SELECT_TYPE: choices = [] if self.SPLIT_SELECT_MULTIPLES: choices = self._get_select_mulitples_choices( @@ -527,7 +525,8 @@ def build_sections( _append_xpaths_to_section( current_section_name, osm_fields, child.get_abbreviated_xpath(), xpaths) - if child.bind.get(u"type") == SELECT_ONE_BIND_TYPE: + if child.bind.get(u"type") == SELECT_BIND_TYPE \ + and child.type == SELECT_ONE: _append_xpaths_to_section( current_section_name, select_ones, child.get_abbreviated_xpath(), []) @@ -1062,7 +1061,7 @@ def _is_numeric(xpath, element_type, data_dictionary): parent_xpath = '/'.join(xpath.split('/')[:-1]) parent = data_dictionary.get_element(parent_xpath) return (parent and parent.type == MULTIPLE_SELECT_TYPE) - elif element_type != SELECT_ONE_BIND_TYPE: + elif element_type != 'select1': return False if var_name not in all_value_labels: From 0b0793dc1300464238be8d6703087e8f161df3d4 Mon Sep 17 00:00:00 2001 From: Davis Raymond Muro Date: Tue, 25 Feb 2020 10:47:43 +0300 Subject: [PATCH 3/9] Modify Export Builder tests Modify Export Builder tests passing in the new 'default_name' arguement to PyXForms 'create_survey_from_xls' function and use SELECT_BIND_TYPE and MULTIPLE_SELECT_TYPE common tags instead of static values. More info: https://github.com/XLSForm/pyxform/pull/375 --- .../libs/tests/utils/test_export_builder.py | 68 +++++++++++++------ 1 file changed, 46 insertions(+), 22 deletions(-) diff --git a/onadata/libs/tests/utils/test_export_builder.py b/onadata/libs/tests/utils/test_export_builder.py index 974be49c0d..fea02c79e1 100644 --- a/onadata/libs/tests/utils/test_export_builder.py +++ b/onadata/libs/tests/utils/test_export_builder.py @@ -31,6 +31,8 @@ from onadata.apps.viewer.tests.export_helpers import viewer_fixture_path from onadata.libs.utils.csv_builder import (CSVDataFrameBuilder, get_labels_from_columns) +from onadata.libs.utils.common_tags import (SELECT_BIND_TYPE, + MULTIPLE_SELECT_TYPE) from onadata.libs.utils.export_builder import ( decode_mongo_encoded_section_names, dict_to_joined_export, @@ -238,7 +240,7 @@ class TestExportBuilder(TestBase): def _create_childrens_survey(self, filename="childrens_survey.xls"): survey = create_survey_from_xls(_logger_fixture_path( filename - )) + ), default_name=filename.split('.')[0]) self.dd = DataDictionary() self.dd._survey = survey return survey @@ -438,7 +440,8 @@ def test_zipped_csv_export_works_with_unicode(self): cvs writer doesnt handle unicode we we have to encode to ascii """ survey = create_survey_from_xls(_logger_fixture_path( - 'childrens_survey_unicode.xls')) + 'childrens_survey_unicode.xls'), + default_name='childrens_survey_unicode') export_builder = ExportBuilder() export_builder.set_survey(survey) temp_zip_file = NamedTemporaryFile(suffix='.zip') @@ -933,7 +936,8 @@ def test_zipped_sav_export_with_duplicate_column_name(self): def test_xls_export_works_with_unicode(self): survey = create_survey_from_xls(_logger_fixture_path( - 'childrens_survey_unicode.xls')) + 'childrens_survey_unicode.xls'), + default_name='childrenss_survey_unicode') export_builder = ExportBuilder() export_builder.set_survey(survey) temp_xls_file = NamedTemporaryFile(suffix='.xlsx') @@ -953,7 +957,9 @@ def test_xls_export_with_hxl_adds_extra_row(self): xlsform_path = os.path.join( settings.PROJECT_ROOT, "apps", "main", "tests", "fixtures", "hxl_test", "hxl_example.xlsx") - survey = create_survey_from_xls(xlsform_path) + survey = create_survey_from_xls( + xlsform_path, + default_name=xlsform_path.split('/')[-1].split('.')[0]) export_builder = ExportBuilder() export_builder.INCLUDE_HXL = True export_builder.set_survey(survey) @@ -1483,7 +1489,8 @@ def test_get_valid_sheet_name_catches_long_duplicate_names(self): def test_to_xls_export_generates_valid_sheet_names(self): survey = create_survey_from_xls(_logger_fixture_path( - 'childrens_survey_with_a_very_long_name.xls')) + 'childrens_survey_with_a_very_long_name.xls'), + default_name='childrens_survey_with_a_very_long_name') export_builder = ExportBuilder() export_builder.set_survey(survey) xls_file = NamedTemporaryFile(suffix='.xls') @@ -1502,7 +1509,8 @@ def test_to_xls_export_generates_valid_sheet_names(self): def test_child_record_parent_table_is_updated_when_sheet_is_renamed(self): survey = create_survey_from_xls(_logger_fixture_path( - 'childrens_survey_with_a_very_long_name.xls')) + 'childrens_survey_with_a_very_long_name.xls'), + default_name='childrens_survey_with_a_very_long_name') export_builder = ExportBuilder() export_builder.set_survey(survey) xls_file = NamedTemporaryFile(suffix='.xlsx') @@ -1564,7 +1572,8 @@ def test_type_conversion(self): } survey = create_survey_from_xls(viewer_fixture_path( - 'test_data_types/test_data_types.xls')) + 'test_data_types/test_data_types.xls'), + default_name='test_data_types') export_builder = ExportBuilder() export_builder.set_survey(survey) # format submission 1 for export @@ -1589,7 +1598,8 @@ def test_type_conversion(self): def test_xls_convert_dates_before_1900(self): survey = create_survey_from_xls(viewer_fixture_path( - 'test_data_types/test_data_types.xls')) + 'test_data_types/test_data_types.xls'), + default_name='test_data_types') export_builder = ExportBuilder() export_builder.set_survey(survey) data = [ @@ -1759,7 +1769,8 @@ def test_generate_field_title_truncated_titles_select_multiple(self): def test_xls_export_remove_group_name(self): survey = create_survey_from_xls(_logger_fixture_path( - 'childrens_survey_unicode.xls')) + 'childrens_survey_unicode.xls'), + default_name='childrens_survey_unicode') export_builder = ExportBuilder() export_builder.TRUNCATE_GROUP_TITLE = True export_builder.set_survey(survey) @@ -1780,7 +1791,8 @@ def test_zipped_csv_export_remove_group_name(self): cvs writer doesnt handle unicode we we have to encode to ascii """ survey = create_survey_from_xls(_logger_fixture_path( - 'childrens_survey_unicode.xls')) + 'childrens_survey_unicode.xls'), + default_name='childrens_survey_unicode') export_builder = ExportBuilder() export_builder.TRUNCATE_GROUP_TITLE = True export_builder.set_survey(survey) @@ -1825,7 +1837,8 @@ def test_zipped_csv_export_remove_group_name(self): def test_xls_export_with_labels(self): survey = create_survey_from_xls(_logger_fixture_path( - 'childrens_survey_unicode.xls')) + 'childrens_survey_unicode.xls'), + default_name='childrens_survey_unicode') export_builder = ExportBuilder() export_builder.TRUNCATE_GROUP_TITLE = True export_builder.INCLUDE_LABELS = True @@ -1854,7 +1867,8 @@ def test_xls_export_with_labels(self): def test_xls_export_with_labels_only(self): survey = create_survey_from_xls(_logger_fixture_path( - 'childrens_survey_unicode.xls')) + 'childrens_survey_unicode.xls'), + default_name='childrens_survey_unicode') export_builder = ExportBuilder() export_builder.TRUNCATE_GROUP_TITLE = True export_builder.INCLUDE_LABELS_ONLY = True @@ -1878,7 +1892,8 @@ def test_zipped_csv_export_with_labels(self): cvs writer doesnt handle unicode we we have to encode to ascii """ survey = create_survey_from_xls(_logger_fixture_path( - 'childrens_survey_unicode.xls')) + 'childrens_survey_unicode.xls'), + default_name='childrens_survey_unicode') export_builder = ExportBuilder() export_builder.TRUNCATE_GROUP_TITLE = True export_builder.INCLUDE_LABELS = True @@ -1944,7 +1959,8 @@ def test_zipped_csv_export_with_labels_only(self): cvs writer doesnt handle unicode we we have to encode to ascii """ survey = create_survey_from_xls(_logger_fixture_path( - 'childrens_survey_unicode.xls')) + 'childrens_survey_unicode.xls'), + default_name='childrens_survey_unicode') export_builder = ExportBuilder() export_builder.TRUNCATE_GROUP_TITLE = True export_builder.INCLUDE_LABELS_ONLY = True @@ -2064,7 +2080,8 @@ def _test_sav_file(section): def test_xls_export_with_english_labels(self): survey = create_survey_from_xls(_logger_fixture_path( - 'childrens_survey_en.xls')) + 'childrens_survey_en.xls'), + default_name='childrens_survey_en') # no default_language is not set self.assertEqual( survey.to_json_dict().get('default_language'), 'default' @@ -2092,7 +2109,8 @@ def test_xls_export_with_english_labels(self): def test_xls_export_with_swahili_labels(self): survey = create_survey_from_xls(_logger_fixture_path( - 'childrens_survey_sw.xls')) + 'childrens_survey_sw.xls'), + default_name='childrens_survey_sw') # default_language is set to swahili self.assertEqual( survey.to_json_dict().get('default_language'), 'swahili' @@ -2120,7 +2138,8 @@ def test_xls_export_with_swahili_labels(self): def test_csv_export_with_swahili_labels(self): survey = create_survey_from_xls(_logger_fixture_path( - 'childrens_survey_sw.xls')) + 'childrens_survey_sw.xls'), + default_name='childrens_survey_sw') # default_language is set to swahili self.assertEqual( survey.to_json_dict().get('default_language'), 'swahili' @@ -2137,7 +2156,8 @@ def test_csv_export_with_swahili_labels(self): def test_select_multiples_choices(self): survey = create_survey_from_xls(_logger_fixture_path( - 'childrens_survey_sw.xls')) + 'childrens_survey_sw.xls'), + default_name='childrens_survey_sw') dd = DataDictionary() dd._survey = survey export_builder = ExportBuilder() @@ -2145,7 +2165,8 @@ def test_select_multiples_choices(self): export_builder.INCLUDE_LABELS = True export_builder.set_survey(survey) child = [e for e in dd.get_survey_elements_with_choices() - if e.bind.get('type') == 'select'][0] + if e.bind.get('type') == SELECT_BIND_TYPE + and e.type == MULTIPLE_SELECT_TYPE][0] self.assertNotEqual(child.children, []) choices = export_builder._get_select_mulitples_choices( child, dd, ExportBuilder.GROUP_DELIMITER, @@ -2191,7 +2212,7 @@ def test_select_multiples_choices(self): def test_select_multiples_choices_with_choice_filter(self): survey = create_survey_from_xls(_logger_fixture_path( 'choice_filter.xlsx' - )) + ), default_name='choice_filter') dd = DataDictionary() dd._survey = survey export_builder = ExportBuilder() @@ -2199,7 +2220,8 @@ def test_select_multiples_choices_with_choice_filter(self): export_builder.INCLUDE_LABELS = True export_builder.set_survey(survey) child = [e for e in dd.get_survey_elements_with_choices() - if e.bind.get('type') == 'select'][0] + if e.bind.get('type') == SELECT_BIND_TYPE + and e.type == MULTIPLE_SELECT_TYPE][0] choices = export_builder._get_select_mulitples_choices( child, dd, ExportBuilder.GROUP_DELIMITER, ExportBuilder.TRUNCATE_GROUP_TITLE @@ -2283,7 +2305,9 @@ def _create_osm_survey(self): for filename in filenames] submission_path = os.path.join(osm_fixtures_dir, 'instance_a.xml') self._make_submission_w_attachment(submission_path, paths) - survey = create_survey_from_xls(xlsform_path) + survey = create_survey_from_xls( + xlsform_path, + default_name=xlsform_path.split('/')[-1].split('.')[0]) return survey def test_zip_csv_export_has_comment_and_status_field(self): From 694830a63c2a722f0dd8c75876b83c617cd8c378 Mon Sep 17 00:00:00 2001 From: Davis Raymond Muro Date: Wed, 26 Feb 2020 11:11:05 +0300 Subject: [PATCH 4/9] Modify _get_sav_options function Modify _get_sav_options function to work with the new string binding for select one elements --- onadata/libs/utils/export_builder.py | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/onadata/libs/utils/export_builder.py b/onadata/libs/utils/export_builder.py index 529f29ab3e..665c254860 100644 --- a/onadata/libs/utils/export_builder.py +++ b/onadata/libs/utils/export_builder.py @@ -1056,25 +1056,22 @@ def _is_numeric(xpath, element_type, data_dictionary): # check if it is a choice part of multiple choice # type is likely empty string, split multi select is binary element = data_dictionary.get_element(xpath) + if element.type == SELECT_ONE: + # Determine if all select1 choices are numeric in nature. + # If the choices are numeric in nature have the field type + # in spss be numeric + choices = list(all_value_labels[var_name]) + if len(choices) == 0: + return False + return is_all_numeric(choices) if element and element.type == '' and value_select_multiples: return is_all_numeric([element.name]) parent_xpath = '/'.join(xpath.split('/')[:-1]) parent = data_dictionary.get_element(parent_xpath) return (parent and parent.type == MULTIPLE_SELECT_TYPE) - elif element_type != 'select1': - return False - - if var_name not in all_value_labels: - return False - - # Determine if all select1 choices are numeric in nature - # and as such have the field type in spss be numeric - choices = list(all_value_labels[var_name]) - if len(choices) == 0: + else: return False - return is_all_numeric(choices) - value_select_multiples = self.VALUE_SELECT_MULTIPLES _var_types = {} value_labels = {} From 022fa843f425e06037a27bd9853644c669472148 Mon Sep 17 00:00:00 2001 From: Davis Raymond Muro Date: Thu, 27 Feb 2020 13:55:18 +0300 Subject: [PATCH 5/9] Update error raised when an id_string is invalid Update the error raised when an id_string is invalid. PyXForm now utilizes the filename as the form_id if it's not explicitly set in the settings sheet. More Info: https://github.com/XLSForm/pyxform/pull/389 --- onadata/apps/api/tests/viewsets/test_xform_viewset.py | 8 ++++++-- onadata/apps/logger/models/xform.py | 8 ++++++-- onadata/apps/main/tests/test_form_errors.py | 10 +++++----- 3 files changed, 17 insertions(+), 9 deletions(-) diff --git a/onadata/apps/api/tests/viewsets/test_xform_viewset.py b/onadata/apps/api/tests/viewsets/test_xform_viewset.py index bbe71920bc..e75203cb9f 100644 --- a/onadata/apps/api/tests/viewsets/test_xform_viewset.py +++ b/onadata/apps/api/tests/viewsets/test_xform_viewset.py @@ -1381,8 +1381,12 @@ def test_publish_invalid_xls_form(self): response = view(request) self.assertEqual(response.status_code, 400) self.assertEqual(response.get('Cache-Control'), None) - error_msg = 'In strict mode, the XForm ID must be a valid slug'\ - ' and contain no spaces.' + error_msg = ('In strict mode, the XForm ID must be ' + 'a valid slug and contain no spaces.' + ' Please ensure that you have set an' + ' id_string in the settings sheet or ' + 'have modified the filename to not ' + 'contain any spaces.') self.assertEqual(response.data.get('text'), error_msg) path = os.path.join( diff --git a/onadata/apps/logger/models/xform.py b/onadata/apps/logger/models/xform.py index fedfeac54b..85e005ae1f 100644 --- a/onadata/apps/logger/models/xform.py +++ b/onadata/apps/logger/models/xform.py @@ -164,7 +164,8 @@ def check_version_set(survey): def _expand_select_all_that_apply(d, key, e): - if e and e.bind.get(u"type") == u"select": + if e and e.bind.get(u"type") == u"string"\ + and e.type == MULTIPLE_SELECT_TYPE: options_selected = d[key].split() for child in e.children: new_key = child.get_abbreviated_xpath() @@ -864,7 +865,10 @@ def save(self, *args, **kwargs): not re.search(r"^[\w-]+$", self.id_string): raise XLSFormError( _(u'In strict mode, the XForm ID must be a ' - 'valid slug and contain no spaces.')) + 'valid slug and contain no spaces. Please ensure' + ' that you have set an id_string in the settings sheet ' + 'or have modified the filename to not contain' + ' any spaces.')) if not self.sms_id_string and (update_fields is None or 'id_string' in update_fields): diff --git a/onadata/apps/main/tests/test_form_errors.py b/onadata/apps/main/tests/test_form_errors.py index 346f7117dc..1600e7d70e 100644 --- a/onadata/apps/main/tests/test_form_errors.py +++ b/onadata/apps/main/tests/test_form_errors.py @@ -93,12 +93,12 @@ def test_spaced_xlsform(self): self.xform.save() xls_path = os.path.join(self.this_directory, "fixtures", "transportation", "tutorial .xls") - msg = ("The name 'tutorial ' is an invalid XML tag, it contains an" - " invalid character ' '. Names must begin with a letter, colon," - " or underscore, subsequent characters can include numbers, " - "dashes, and periods") + msg = ("In strict mode, the XForm ID must be a valid slug" + " and contain no spaces. Please ensure that you " + "have set an id_string in the settings sheet or" + " have modified the filename to not contain any spaces.") self.assertRaisesMessage( - PyXFormError, msg, self._publish_xls_file, xls_path) + XLSFormError, msg, self._publish_xls_file, xls_path) self.assertEquals(XForm.objects.count(), count) def test_choice_duplicate_error(self): From 1641216367243a27406f62b5a0b8beb19fffa020 Mon Sep 17 00:00:00 2001 From: Davis Raymond Muro Date: Thu, 27 Feb 2020 14:12:10 +0300 Subject: [PATCH 6/9] Update tests to use 'data' as the default xml root node As of PyXForm v1.0.0 the name of the file is no longer used as the root node. More Info: https://github.com/XLSForm/pyxform/pull/375 --- .../tests/fixtures/Transportation Form.xml | 80 ++++++++--------- .../tests/viewsets/test_dataview_viewset.py | 2 +- .../api/tests/viewsets/test_xform_viewset.py | 10 +-- .../transportation/Transportation Form.xml | 85 ++++++++++--------- .../transportation/transportation.xml | 80 ++++++++--------- onadata/apps/main/tests/test_csv_export.py | 10 +-- onadata/apps/main/tests/test_process.py | 4 +- onadata/apps/viewer/tests/test_exports.py | 2 +- onadata/libs/tests/utils/fixtures/single.xml | 2 +- onadata/libs/tests/utils/test_viewer_tools.py | 6 +- 10 files changed, 143 insertions(+), 138 deletions(-) diff --git a/onadata/apps/api/tests/fixtures/Transportation Form.xml b/onadata/apps/api/tests/fixtures/Transportation Form.xml index a4ef8631a0..76ff4058ea 100644 --- a/onadata/apps/api/tests/fixtures/Transportation Form.xml +++ b/onadata/apps/api/tests/fixtures/Transportation Form.xml @@ -2,9 +2,9 @@ transportation_2011_07_25 - + - + @@ -45,28 +45,28 @@ - + - - - - - - - - - - - - - - + + + + + + + + + + + + + + - + - @@ -109,13 +109,13 @@ other - + - - + + - + @@ -135,9 +135,9 @@ - + - + @@ -157,9 +157,9 @@ - + - + @@ -179,9 +179,9 @@ - + - + @@ -201,9 +201,9 @@ - + - + @@ -223,9 +223,9 @@ - + - + @@ -245,9 +245,9 @@ - + - + @@ -267,9 +267,9 @@ - + - + @@ -289,9 +289,9 @@ - + - + @@ -313,7 +313,7 @@ - + diff --git a/onadata/apps/api/tests/viewsets/test_dataview_viewset.py b/onadata/apps/api/tests/viewsets/test_dataview_viewset.py index 8474bf7f69..542c8afe44 100644 --- a/onadata/apps/api/tests/viewsets/test_dataview_viewset.py +++ b/onadata/apps/api/tests/viewsets/test_dataview_viewset.py @@ -105,7 +105,7 @@ def test_get_dataview_form_definition(self): self._create_dataview() data = { - "name": "tutorial", + "name": "data", "title": "tutorial", "default_language": "default", "id_string": "tutorial", diff --git a/onadata/apps/api/tests/viewsets/test_xform_viewset.py b/onadata/apps/api/tests/viewsets/test_xform_viewset.py index e75203cb9f..3b6a2b5cda 100644 --- a/onadata/apps/api/tests/viewsets/test_xform_viewset.py +++ b/onadata/apps/api/tests/viewsets/test_xform_viewset.py @@ -572,7 +572,7 @@ def test_form_format(self): }) formid = self.xform.pk data = { - "name": "transportation", + "name": "data", "title": "transportation_2011_07_25", "default_language": "default", "id_string": "transportation_2011_07_25", @@ -634,7 +634,7 @@ def test_form_format(self): uuid_nodes = [ node for node in model_node.childNodes if node.nodeType == Node.ELEMENT_NODE and - node.getAttribute("nodeset") == "/transportation/formhub/uuid"] + node.getAttribute("nodeset") == "/data/formhub/uuid"] self.assertEqual(len(uuid_nodes), 1) uuid_node = uuid_nodes[0] uuid_node.setAttribute("calculate", "''") @@ -2200,7 +2200,7 @@ def test_manager_can_update_xform_xls_file(self): fhuuid = xml.find('formhub/uuid') self.assertEqual( xml[xml[:fhuuid].rfind('=') + 2:fhuuid], - '/transportation/' + '/data/' ) view = XFormViewSet.as_view({ @@ -2237,7 +2237,7 @@ def test_manager_can_update_xform_xls_file(self): fhuuid = xml.find('formhub/uuid') self.assertEqual( xml[xml[:fhuuid].rfind('=') + 2:fhuuid], - '/transportation/' + '/data/' ) def test_update_xform_with_different_id_string_form_with_sub(self): @@ -2346,7 +2346,7 @@ def test_update_xform_xls_file_with_different_model_name(self): response = view(request, pk=form_id) self.assertEqual(response.status_code, 200) xform = XForm.objects.get(pk=form_id) - self.assertEqual('transportation', + self.assertEqual('data', xform.survey.xml_instance().tagName) def test_id_strings_should_be_unique_in_each_account(self): diff --git a/onadata/apps/main/tests/fixtures/transportation/Transportation Form.xml b/onadata/apps/main/tests/fixtures/transportation/Transportation Form.xml index 5288295eca..76ff4058ea 100644 --- a/onadata/apps/main/tests/fixtures/transportation/Transportation Form.xml +++ b/onadata/apps/main/tests/fixtures/transportation/Transportation Form.xml @@ -1,10 +1,10 @@ - - + + transportation_2011_07_25 - + - + @@ -41,30 +41,32 @@ + - + - - - - - - - - - - - - - + + + + + + + + + + + + + + - + - @@ -107,13 +109,13 @@ other - + - - + + - + @@ -133,9 +135,9 @@ - + - + @@ -155,9 +157,9 @@ - + - + @@ -177,9 +179,9 @@ - + - + @@ -199,9 +201,9 @@ - + - + @@ -221,9 +223,9 @@ - + - + @@ -243,9 +245,9 @@ - + - + @@ -265,9 +267,9 @@ - + - + @@ -287,9 +289,9 @@ - + - + @@ -311,5 +313,8 @@ + + + diff --git a/onadata/apps/main/tests/fixtures/transportation/transportation.xml b/onadata/apps/main/tests/fixtures/transportation/transportation.xml index 8e29952e8f..bf8d6ca5a0 100644 --- a/onadata/apps/main/tests/fixtures/transportation/transportation.xml +++ b/onadata/apps/main/tests/fixtures/transportation/transportation.xml @@ -2,9 +2,9 @@ transportation_2011_07_25 - + - + @@ -45,28 +45,28 @@ - + - - - - - - - - - - - - - - + + + + + + + + + + + + + + - + - @@ -109,13 +109,13 @@ other - + - - + + - + @@ -135,9 +135,9 @@ - + - + @@ -157,9 +157,9 @@ - + - + @@ -179,9 +179,9 @@ - + - + @@ -201,9 +201,9 @@ - + - + @@ -223,9 +223,9 @@ - + - + @@ -245,9 +245,9 @@ - + - + @@ -267,9 +267,9 @@ - + - + @@ -289,9 +289,9 @@ - + - + @@ -313,7 +313,7 @@ - + diff --git a/onadata/apps/main/tests/test_csv_export.py b/onadata/apps/main/tests/test_csv_export.py index 86ad462165..868265bf82 100644 --- a/onadata/apps/main/tests/test_csv_export.py +++ b/onadata/apps/main/tests/test_csv_export.py @@ -67,11 +67,11 @@ def test_csv_nested_repeat_output(self): self.maxDiff = None data_dictionary = DataDictionary.objects.all()[0] xpaths = [ - u'/double_repeat/bed_net[1]/member[1]/name', - u'/double_repeat/bed_net[1]/member[2]/name', - u'/double_repeat/bed_net[2]/member[1]/name', - u'/double_repeat/bed_net[2]/member[2]/name', - u'/double_repeat/meta/instanceID' + u'/data/bed_net[1]/member[1]/name', + u'/data/bed_net[1]/member[2]/name', + u'/data/bed_net[2]/member[1]/name', + u'/data/bed_net[2]/member[2]/name', + u'/data/meta/instanceID' ] self.assertEquals(data_dictionary.xpaths(repeat_iterations=2), xpaths) # test csv diff --git a/onadata/apps/main/tests/test_process.py b/onadata/apps/main/tests/test_process.py index 50e7b104e8..e46df8e9bc 100644 --- a/onadata/apps/main/tests/test_process.py +++ b/onadata/apps/main/tests/test_process.py @@ -246,7 +246,7 @@ def _download_xform(self): uuid_nodes = [node for node in model_node.childNodes if node.nodeType == Node.ELEMENT_NODE and node.getAttribute("nodeset") == - "/transportation/formhub/uuid"] + "/data/formhub/uuid"] self.assertEqual(len(uuid_nodes), 1) uuid_node = uuid_nodes[0] uuid_node.setAttribute("calculate", "''") @@ -560,7 +560,7 @@ def test_uuid_injection_in_cascading_select(self): node.nodeType == Node.ELEMENT_NODE and node.tagName == "bind" and node.getAttribute("nodeset") == - "/%s/formhub/uuid" % file_name] + "/data/formhub/uuid"] self.assertEqual(len(calculate_bind_nodes), 1) calculate_bind_node = calculate_bind_nodes[0] self.assertEqual( diff --git a/onadata/apps/viewer/tests/test_exports.py b/onadata/apps/viewer/tests/test_exports.py index 692a1700be..387c30e708 100644 --- a/onadata/apps/viewer/tests/test_exports.py +++ b/onadata/apps/viewer/tests/test_exports.py @@ -824,7 +824,7 @@ def _get_xls_data(self, filepath): storage = get_storage_class()() with storage.open(filepath) as f: workbook = open_workbook(file_contents=f.read()) - transportation_sheet = workbook.sheet_by_name("transportation") + transportation_sheet = workbook.sheet_by_name("data") self.assertTrue(transportation_sheet.nrows > 1) headers = transportation_sheet.row_values(0) column1 = transportation_sheet.row_values(1) diff --git a/onadata/libs/tests/utils/fixtures/single.xml b/onadata/libs/tests/utils/fixtures/single.xml index 77d818bd30..37a376be32 100644 --- a/onadata/libs/tests/utils/fixtures/single.xml +++ b/onadata/libs/tests/utils/fixtures/single.xml @@ -1 +1 @@ -102014-09-04T15:07:17+03:00 a55d89f9483a45c8a896d45de94499a9maleenketo.org:2gnoXEilHRGn6V5i83.3595 -32.8601 0 1 uuid:fa7f34af-8e28-4d05-9085-b495f0bd9491Name_1no phonenumber property in enketoNAno2014-09-04T15:06:01+03:0083.3595 -32.8601 0 1083.3595-32.8601121.22474 -10.5601 50000 2005000021.22474-10.56012002014-09-04 +102014-09-04T15:07:17+03:00 a55d89f9483a45c8a896d45de94499a9maleenketo.org:2gnoXEilHRGn6V5i83.3595 -32.8601 0 1 uuid:fa7f34af-8e28-4d05-9085-b495f0bd9491Name_1no phonenumber property in enketoNAno2014-09-04T15:06:01+03:0083.3595 -32.8601 0 1083.3595-32.8601121.22474 -10.5601 50000 2005000021.22474-10.56012002014-09-04 diff --git a/onadata/libs/tests/utils/test_viewer_tools.py b/onadata/libs/tests/utils/test_viewer_tools.py index 5f5c7c10e1..28fa00591d 100644 --- a/onadata/libs/tests/utils/test_viewer_tools.py +++ b/onadata/libs/tests/utils/test_viewer_tools.py @@ -63,7 +63,7 @@ def test_get_enketo_defaults_with_right_xform(self): kwargs = {xform_variable_name: xform_variable_value} defaults = generate_enketo_form_defaults(self.xform, **kwargs) - key = "defaults[/transportation/transport/{}]".format( + key = "defaults[/data/transport/{}]".format( xform_variable_name) self.assertEqual(defaults, {key: xform_variable_value}) @@ -87,9 +87,9 @@ def test_get_enketo_defaults_with_multiple_params(self): defaults = generate_enketo_form_defaults(self.xform, **kwargs) transportation_types_key = \ - "defaults[/transportation/transport/{}]".format( + "defaults[/data/transport/{}]".format( transportation_types) - frequency_key = "defaults[/transportation/transport/"\ + frequency_key = "defaults[/data/transport/"\ "loop_over_transport_types_frequency/"\ "{}/{}]".format(transportation_types_value, frequency) self.assertIn(transportation_types_key, defaults) From 806095213621c8e8ae8dfad03a6c77acfb4e8529 Mon Sep 17 00:00:00 2001 From: Davis Raymond Muro Date: Fri, 28 Feb 2020 09:55:02 +0300 Subject: [PATCH 7/9] Update test fixtures to include 'list_name' field As of PyXForm v1.0.0 the 'list_name' field has been added to a forms generated JSON. More Info: https://github.com/XLSForm/pyxform/pull/357 --- .../fixtures/group_names_must_be_unique.xlsx | Bin 0 -> 10499 bytes .../serializers/test_merged_xform_serializer.py | 5 +++++ 2 files changed, 5 insertions(+) create mode 100644 onadata/apps/main/tests/fixtures/group_names_must_be_unique.xlsx diff --git a/onadata/apps/main/tests/fixtures/group_names_must_be_unique.xlsx b/onadata/apps/main/tests/fixtures/group_names_must_be_unique.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..890f26b8f6f24f7c3ebdce872c4c814c9096cbd6 GIT binary patch literal 10499 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 literal 0 HcmV?d00001 diff --git a/onadata/libs/tests/serializers/test_merged_xform_serializer.py b/onadata/libs/tests/serializers/test_merged_xform_serializer.py index c8f4018df1..77ffe00fc7 100644 --- a/onadata/libs/tests/serializers/test_merged_xform_serializer.py +++ b/onadata/libs/tests/serializers/test_merged_xform_serializer.py @@ -226,6 +226,7 @@ def test_get_merged_xform_survey(self): }], u'name': u'gender', u'label': u'Sex', + u'list_name': u'gender', u'type': u'select one' }, { u'control': { @@ -280,6 +281,7 @@ def test_group_merged_xform_survey(self): }], u'name': u'gender', u'label': u'Sex', + u'list_name': u'gender', u'type': u'select one' }], u'name': u'info', @@ -297,6 +299,7 @@ def test_group_merged_xform_survey(self): }], u'name': u'gender', u'label': u'Sex', + u'list_name': u'gender', u'type': u'select one' }], u'name': u'person', @@ -357,6 +360,7 @@ def test_repeat_merged_xform_survey(self): }], u'name': u'gender', u'label': u'Sex', + u'list_name': u'gender', u'type': u'select one' }], u'name': u'info', @@ -374,6 +378,7 @@ def test_repeat_merged_xform_survey(self): }], u'name': u'gender', u'label': u'Sex', + u'list_name': u'gender', u'type': u'select one' }], u'name': u'person', From 8762f1db4c0c565b10035ed1e06a91b831a86721 Mon Sep 17 00:00:00 2001 From: Davis Raymond Muro Date: Fri, 28 Feb 2020 10:20:41 +0300 Subject: [PATCH 8/9] Update 'test_choice_duplicate_error' test Update the 'test_choice_duplicate_error' test to expect the correct error message raised by PyXForm. --- onadata/apps/main/tests/test_form_errors.py | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/onadata/apps/main/tests/test_form_errors.py b/onadata/apps/main/tests/test_form_errors.py index 1600e7d70e..8b0fc360bf 100644 --- a/onadata/apps/main/tests/test_form_errors.py +++ b/onadata/apps/main/tests/test_form_errors.py @@ -111,13 +111,14 @@ def test_choice_duplicate_error(self): xls_path = os.path.join( self.this_directory, 'fixtures', 'cascading_selects', 'duplicate_choice_form.xls') - msg = ("There does not seem to be" - " a `allow_choice_duplicates`" - " column header defined in your settings sheet." - " You must have set `allow_choice_duplicates`" - " setting in your settings sheet" - " to have duplicate choice list names" - " in your choices sheet") + msg = ("The name column for the 'counties' choice list" + " contains these duplicates: 'king'. Duplicate " + "names will be impossible to identify in " + "analysis unless a previous value in a " + "cascading select differentiates them. If this " + "is intentional, you can set the " + "allow_choice_duplicates setting to 'yes'. " + "Read more: https://xlsform.org/#choice-names.") self.assertRaisesMessage( PyXFormError, msg, self._publish_xls_file, xls_path) self.assertEquals(XForm.objects.count(), count) From aae31418831d0813ad3890210c26a5e7c772d133 Mon Sep 17 00:00:00 2001 From: Davis Raymond Muro Date: Thu, 5 Mar 2020 17:17:23 +0300 Subject: [PATCH 9/9] Update 'test_uniqueness_of_group_names_enforced' test Update the test and add a docstring explaining when the error occurs --- .../fixtures/group_names_must_be_unique.xls | Bin 6144 -> 0 bytes .../fixtures/group_names_must_be_unique.xlsx | Bin 10499 -> 9125 bytes onadata/apps/main/tests/test_past_bugs.py | 11 +++++++++-- 3 files changed, 9 insertions(+), 2 deletions(-) delete mode 100644 onadata/apps/main/tests/fixtures/group_names_must_be_unique.xls diff --git a/onadata/apps/main/tests/fixtures/group_names_must_be_unique.xls b/onadata/apps/main/tests/fixtures/group_names_must_be_unique.xls deleted file mode 100644 index 5ebf7f588b7b672a08489c3e22a37803a92feba5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6144 zcmeHLUuc_E6hB|ubYK6hO}ln#=jOM%rR~~^+a8?gY`U&)1KX9hB91~$o3B}1n$)j} zT49)V-P;Dr1brCDpf4imM9~Kawr@U6l)+&7)cGRAA(<#LSQ~%8`+Xs4Y}QnYve6sP z{d2x^?z#8ebI&<9KYU+3fAO>W8q{+A1AP+3FD8a`Nd&DWlQ`|d%VtBoxz%iVwad*1(YKm}kUpb}68KnRd(Kn-9MpcYUE z*bI0G@G#&JKs{g!;8DOgKKiy%ix?4 zK;#o+9~x#P&uTuk_H(LkP<170O}fX%ApD6=U(q+~lo(og>KMKQBTg%bs!*kZ<=pS7C40LL6 zdrnE~xy9B)G8f;R2j7|pzbg;E^dI>1F5Ibvq}X~AMXIe%l&H2QQLNfci4Cf)O}JC9 zs2gww_WuhQc~d9i*6ZfvS=>zxzd20@hzy+5A}B2zNgD64IW>g#SIeOC);k*$HV9A@clY`y8aj3{#}_?F@bRblg1{;O*9ezn2GE$ z>>oD6pdL1Zp@?CbYZMaTS+);=>B5BseK@9sU`jyh>(h+BcK*B>+uZ|`X(U|Q8) zEM~7NH`^Pt`c3GcZo59!c0JkNoYlW54cJ-$z~7X#YOPwDKiz8bBIYialS+poC(9Yx z(PB)lFX}U67byEHGGm;a_MSs8E@lOG4q;~#x{J2MzVkTLs)RV&UM`MynTx~hpv~|u zD4Vl04-tE$;rKY8J#wkTv`55NVb1i3lsrCCYS>4Wdg*XP*;Oj;*&|Xi6xt(F(x^D% zY*p$7d`o)Kb0rT01EWcjf)XhLQj<@j3wg;Vg)dFonjk@@xTH++k%zCY=Ug@NrFw4r zGDOIiFdr?{7J!F#Du|01q(rCSE3*QQXzHsg8nUn=uyF>DPF*10s#>0B&ek0ov7!^v z(U{To=7?wmzKuQf8?oL2Bc5xF#5EKUI%v^E%V(3fSNoDVBY%yfF5QB!2I_TfD&&m*tsk% zzatW`aNWE8R=~6{W{#T=Pu@KMA3%Dnel|W&qq zl;OJe-L(r(Z1J3bANy~;^T|Qr+&Q>G;8b)#O98Z0@^Wwa@c6u59uN(z<@;aRPmT{+ zPEGWqKF3wPgnu6_IU&R9e~1&yk>3+n18b$d@*bzX;5`|fk5|=ehc@2{$zyoo9K{-5 zErfLm4drt`l+Ci_W1fKl{1NAy2DxD|^H8pgX8f`x+x5yEf~>%PtCQ9({SwFi$MEXm ze?Ld?FVLtu6Jla`4Ml;;Uz!~Gj9`WC|8daXa;9|4K}Z-;YcSP6P^(+dzJIa*M#zpi R^4FqSt^TwBfBC=V{|!W2Q+)sc diff --git a/onadata/apps/main/tests/fixtures/group_names_must_be_unique.xlsx b/onadata/apps/main/tests/fixtures/group_names_must_be_unique.xlsx index 890f26b8f6f24f7c3ebdce872c4c814c9096cbd6..62717f42c22b0d64463381e9015f2b58d0948534 100644 GIT binary patch delta 4538 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 LA3H7K12_KzZOr)} delta 5455 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