From b813bceca6107e1a29800c50d4f7309033ef9ee9 Mon Sep 17 00:00:00 2001 From: Josh McLaughlin Date: Wed, 29 Jan 2020 20:54:51 -0800 Subject: [PATCH 01/29] Update requirements to support Django 2.2 --- README.md | 2 +- requirements-dev.txt | 6 +++--- requirements.txt | 4 ++-- xblock-sdk | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 0170ea86..26ca3f28 100644 --- a/README.md +++ b/README.md @@ -77,7 +77,7 @@ create its migrations: ```bash (venv) ~/xblock_development/problem-builder $ cd ../venv/src/xblock-sdk -(venv) ~/xblock_development/venv/src/xblock-sdk $ make pip +(venv) ~/xblock_development/venv/src/xblock-sdk $ make install (venv) ~/xblock_development/venv/src/xblock-sdk $ python manage.py makemigrations workbench ``` diff --git a/requirements-dev.txt b/requirements-dev.txt index 517e5c11..99251849 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -1,9 +1,9 @@ # Internationalization and Localization requirements --e git://github.com/edx/xblock-sdk.git@v0.1.4#egg=xblock-sdk==v0.1.4 -Django==1.11.23 +-e git://github.com/edx/xblock-sdk.git@v0.1.7#egg=xblock-sdk==v0.1.7 +Django~=2.2.10 django-statici18n==1.8.2 transifex-client==0.12.1 -edx-i18n-tools==0.4.7 +edx-i18n-tools==0.5.0 pycodestyle==2.4.0 pylint==0.28.0 django-babel-underscore==0.5.2 diff --git a/requirements.txt b/requirements.txt index 62959ce4..31ae73f4 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,7 +1,7 @@ XBlock>=1.2 ddt mock -unicodecsv==0.9.4 +unicodecsv==0.11.0 edx-opaque-keys>=0.4 --e git+https://github.com/edx/xblock-utils.git@v1.2.0#egg=xblock-utils +-e git+https://github.com/edx/xblock-utils.git@1.2.4#egg=xblock-utils -e . diff --git a/xblock-sdk b/xblock-sdk index 331e50be..74bf5d60 160000 --- a/xblock-sdk +++ b/xblock-sdk @@ -1 +1 @@ -Subproject commit 331e50bed2a3c9014d998cc4428e92bf658baf8d +Subproject commit 74bf5d6010b37e591a687e1e227263d689412279 From 8e02596bda8382b3b0dfe62efa540d0c6759f099 Mon Sep 17 00:00:00 2001 From: Josh McLaughlin Date: Wed, 26 Feb 2020 18:30:34 -0800 Subject: [PATCH 02/29] Update test_requirements.in as well --- Makefile | 2 +- test_requirements.in | 9 ++-- test_requirements.txt | 99 +++++++++++++++++++++---------------------- 3 files changed, 53 insertions(+), 57 deletions(-) diff --git a/Makefile b/Makefile index ac7f5836..ad6f3564 100644 --- a/Makefile +++ b/Makefile @@ -9,7 +9,7 @@ help: ## display this help message @perl -nle'print $& if m{^[a-zA-Z_-]+:.*?## .*$$}' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m %-25s\033[0m %s\n", $$1, $$2}' upgrade: - pip-compile --output-file test_requirements.txt test_requirements.in + pip-compile --upgrade --output-file test_requirements.txt test_requirements.in extract_translations: ## extract strings to be translated, outputting .po files cd $(WORKING_DIR) && i18n_tool extract diff --git a/test_requirements.in b/test_requirements.in index 24cb8291..fddc3662 100644 --- a/test_requirements.in +++ b/test_requirements.in @@ -1,19 +1,18 @@ -e xblock-sdk bok_choy==0.7.1 ddt -django_nose>=1.4.4 +django_nose>=1.4.6 -e git+https://github.com/edx/acid-block.git@e46f9cda8a03e121a00c7e347084d142d22ebfb7#egg=acid-xblock --e git+https://github.com/edx/django-pyfs.git@1.0.3#egg=django-pyfs==1.0.3 --e git+https://github.com/edx/xblock-utils.git@v1.2.2#egg=xblock-utils +-e git+https://github.com/edx/django-pyfs.git@2.1#egg=django-pyfs==2.1 +-e git+https://github.com/edx/xblock-utils.git@v1.2.3#egg=xblock-utils lazy lxml mock selenium==3.4.1 webob XBlock>=1.2 -Django>=1.11,<2.0 +Django~=2.2.10 pytest -coverage<5 pylint pycodestyle -r xblock-sdk/requirements/base.txt diff --git a/test_requirements.txt b/test_requirements.txt index f3107f2b..3d516bbf 100644 --- a/test_requirements.txt +++ b/test_requirements.txt @@ -5,83 +5,80 @@ # pip-compile --output-file=test_requirements.txt test_requirements.in # -e git+https://github.com/edx/acid-block.git@98aecba94ecbfa934e2d00262741c0ea9f557fc9#egg=acid-xblock --e git+https://github.com/edx/django-pyfs.git@1.0.3#egg=django-pyfs==1.0.3 --e xblock-sdk --e git+https://github.com/edx/xblock-utils.git@v1.2.2#egg=xblock-utils +-e git+https://github.com/edx/django-pyfs.git@2.1#egg=django-pyfs==2.1 +-e file:///home/josh/opencraft/devstack/src/problem-builder/xblock-sdk +-e git+https://github.com/edx/xblock-utils.git@v1.2.3#egg=xblock-utils appdirs==1.4.3 -astroid==1.6.6 # via pylint -atomicwrites==1.3.0 -attrs==19.2.0 -backports.functools-lru-cache==1.6.1 # via astroid, isort, pylint -backports.os==0.1.1 +astroid==2.3.3 # via pylint +attrs==19.3.0 binaryornot==0.4.4 bok_choy==0.7.1 -boto3==1.4.8 +boto3==1.12.8 boto==2.39.0 -botocore==1.8.50 +botocore==1.15.8 +certifi==2019.11.28 chardet==3.0.4 -configparser==4.0.2 -contextlib2==0.6.0 cookiecutter==0.9.0 -coverage==4.5.4 -ddt==1.2.1 +coverage==5.0.3 +ddt==1.2.2 +distlib==0.3.0 django-nose==1.4.6 -django==1.11.25 +django==2.2.10 docutils==0.15.2 -enum34==1.1.6 filelock==3.0.12 -fs-s3fs==0.1.5 +fs-s3fs==0.1.8 fs==2.0.27 -funcsigs==1.0.2 -future==0.17.1 -futures==3.3.0 ; python_version == "2.7" -importlib-metadata==0.23 +idna==2.8 +importlib-metadata==1.5.0 +importlib-resources==1.0.2 isort==4.3.21 # via pylint -jinja2==2.10.1 -jmespath==0.9.4 +jinja2==2.11.1 +jmespath==0.9.5 lazy-object-proxy==1.4.3 # via astroid lazy==1.1 lxml==3.8.0 -mako==1.1.0 +mako==1.1.1 markupsafe==1.1.1 mccabe==0.6.1 # via pylint mock==3.0.5 -more-itertools==5.0.0 +more-itertools==8.2.0 needle==0.5.0 nose==1.3.7 -packaging==19.2 +packaging==20.1 pathlib2==2.3.5 -pillow==6.1.0 -pluggy==0.13.0 -py==1.8.0 +pillow==7.0.0 +pluggy==0.13.1 +py==1.8.1 pycodestyle==2.5.0 -pylint==1.9.5 -pyparsing==2.4.2 +pylint==2.4.4 +pyparsing==2.4.6 pypng==0.0.20 -pytest-cov==2.7.1 -pytest-django==3.5.1 -pytest==4.6.5 -python-dateutil==2.8.0 -pytz==2019.2 -pyyaml==5.1.2 -requests==2.9.1 -s3transfer==0.1.13 -scandir==1.10.0 +pytest-cov==2.8.1 +pytest-django==3.8.0 +pytest-rerunfailures==8.0 +pytest==5.3.5 +python-dateutil==2.8.1 +pytz==2019.3 +pyyaml==5.3 +requests==2.22.0 +s3transfer==0.3.3 selenium==3.4.1 -simplejson==3.16.0 -singledispatch==3.4.0.3 # via astroid, pylint -six==1.10.0 +simplejson==3.17.0 +six==1.14.0 +sqlparse==0.3.0 toml==0.10.0 -tox-battery==0.5.1 -tox==3.14.0 +tox-battery==0.5.2 +tox==3.14.5 +typed-ast==1.4.1 # via astroid typing==3.7.4.1 -virtualenv==16.7.5 -wcwidth==0.1.7 -web-fragments==0.3.0 -webob==1.8.5 +urllib3==1.25.8 +virtualenv==20.0.7 +wcwidth==0.1.8 +web-fragments==0.3.1 +webob==1.8.6 wrapt==1.11.2 # via astroid -xblock==1.2.6 -zipp==0.6.0 +xblock==1.2.9 +zipp==1.2.0 # The following packages are considered to be unsafe in a requirements file: # setuptools From 1c056e30e7f2412ede88bec31f5c101e491694f8 Mon Sep 17 00:00:00 2001 From: Josh McLaughlin Date: Wed, 18 Mar 2020 00:58:57 -0700 Subject: [PATCH 03/29] Update xblock-sdk version --- test_requirements.txt | 139 +++++++++++++++++++++--------------------- xblock-sdk | 2 +- 2 files changed, 71 insertions(+), 70 deletions(-) diff --git a/test_requirements.txt b/test_requirements.txt index 3d516bbf..88ca2c7e 100644 --- a/test_requirements.txt +++ b/test_requirements.txt @@ -4,81 +4,82 @@ # # pip-compile --output-file=test_requirements.txt test_requirements.in # --e git+https://github.com/edx/acid-block.git@98aecba94ecbfa934e2d00262741c0ea9f557fc9#egg=acid-xblock --e git+https://github.com/edx/django-pyfs.git@2.1#egg=django-pyfs==2.1 --e file:///home/josh/opencraft/devstack/src/problem-builder/xblock-sdk --e git+https://github.com/edx/xblock-utils.git@v1.2.3#egg=xblock-utils -appdirs==1.4.3 +-e git+https://github.com/edx/acid-block.git@98aecba94ecbfa934e2d00262741c0ea9f557fc9#egg=acid-xblock # via -r xblock-sdk/requirements/test.txt +-e git+https://github.com/edx/django-pyfs.git@2.1#egg=django-pyfs==2.1 # via -r test_requirements.in +-e xblock-sdk # via -r test_requirements.in +-e git+https://github.com/edx/xblock-utils.git@v1.2.3#egg=xblock-utils # via -r test_requirements.in +appdirs==1.4.3 # via -r xblock-sdk/requirements/base.txt, -r xblock-sdk/requirements/test.txt, fs, virtualenv astroid==2.3.3 # via pylint -attrs==19.3.0 -binaryornot==0.4.4 -bok_choy==0.7.1 -boto3==1.12.8 -boto==2.39.0 -botocore==1.15.8 -certifi==2019.11.28 -chardet==3.0.4 -cookiecutter==0.9.0 -coverage==5.0.3 -ddt==1.2.2 -distlib==0.3.0 -django-nose==1.4.6 -django==2.2.10 -docutils==0.15.2 -filelock==3.0.12 -fs-s3fs==0.1.8 -fs==2.0.27 -idna==2.8 -importlib-metadata==1.5.0 -importlib-resources==1.0.2 +atomicwrites==1.3.0 # via -r xblock-sdk/requirements/test.txt, pytest +attrs==19.3.0 # via -r xblock-sdk/requirements/test.txt, pytest +binaryornot==0.4.4 # via -r xblock-sdk/requirements/base.txt, -r xblock-sdk/requirements/test.txt, cookiecutter +bok_choy==0.7.1 # via -r test_requirements.in, -r xblock-sdk/requirements/test.txt +boto3==1.12.9 # via -r xblock-sdk/requirements/base.txt, -r xblock-sdk/requirements/test.txt, fs-s3fs +boto==2.39.0 # via -r xblock-sdk/requirements/base.txt, -r xblock-sdk/requirements/test.txt +botocore==1.15.9 # via -r xblock-sdk/requirements/base.txt, -r xblock-sdk/requirements/test.txt, boto3, s3transfer +certifi==2019.11.28 # via -r xblock-sdk/requirements/base.txt, -r xblock-sdk/requirements/test.txt, requests +chardet==3.0.4 # via -r xblock-sdk/requirements/base.txt, -r xblock-sdk/requirements/test.txt, binaryornot, requests +cookiecutter==0.9.0 # via -r xblock-sdk/requirements/base.txt, -r xblock-sdk/requirements/test.txt +coverage==5.0.3 # via -r xblock-sdk/requirements/test.txt, pytest-cov +ddt==1.2.2 # via -r test_requirements.in, -r xblock-sdk/requirements/test.txt +distlib==0.3.0 # via -r xblock-sdk/requirements/test.txt, virtualenv +django-nose==1.4.6 # via -r test_requirements.in +django==2.2.10 # via -r test_requirements.in, -r xblock-sdk/requirements/base.txt, django-pyfs, xblock-sdk +docutils==0.15.2 # via -r xblock-sdk/requirements/base.txt, -r xblock-sdk/requirements/test.txt, botocore +filelock==3.0.12 # via -r xblock-sdk/requirements/test.txt, tox, virtualenv +fs-s3fs==0.1.8 # via -r xblock-sdk/requirements/base.txt, -r xblock-sdk/requirements/test.txt, django-pyfs +fs==2.0.27 # via -r xblock-sdk/requirements/base.txt, -r xblock-sdk/requirements/test.txt, django-pyfs, fs-s3fs, xblock +idna==2.8 # via -r xblock-sdk/requirements/base.txt, -r xblock-sdk/requirements/test.txt, requests +importlib-metadata==1.5.0 # via -r xblock-sdk/requirements/test.txt, pluggy, pytest, tox, virtualenv +importlib-resources==1.0.2 # via -r xblock-sdk/requirements/test.txt, virtualenv isort==4.3.21 # via pylint -jinja2==2.11.1 -jmespath==0.9.5 +jinja2==2.11.1 # via -r xblock-sdk/requirements/base.txt, -r xblock-sdk/requirements/test.txt, cookiecutter +jmespath==0.9.5 # via -r xblock-sdk/requirements/base.txt, -r xblock-sdk/requirements/test.txt, boto3, botocore lazy-object-proxy==1.4.3 # via astroid -lazy==1.1 -lxml==3.8.0 -mako==1.1.1 -markupsafe==1.1.1 +lazy==1.1 # via -r test_requirements.in, -r xblock-sdk/requirements/base.txt, -r xblock-sdk/requirements/test.txt, acid-xblock, bok-choy +lxml==3.8.0 # via -r test_requirements.in, -r xblock-sdk/requirements/base.txt, -r xblock-sdk/requirements/test.txt, xblock +mako==1.1.1 # via -r xblock-sdk/requirements/test.txt, acid-xblock, xblock-utils +markupsafe==1.1.1 # via -r xblock-sdk/requirements/base.txt, -r xblock-sdk/requirements/test.txt, jinja2, mako, xblock mccabe==0.6.1 # via pylint -mock==3.0.5 -more-itertools==8.2.0 -needle==0.5.0 -nose==1.3.7 -packaging==20.1 -pathlib2==2.3.5 -pillow==7.0.0 -pluggy==0.13.1 -py==1.8.1 -pycodestyle==2.5.0 -pylint==2.4.4 -pyparsing==2.4.6 -pypng==0.0.20 -pytest-cov==2.8.1 -pytest-django==3.8.0 -pytest-rerunfailures==8.0 -pytest==5.3.5 -python-dateutil==2.8.1 -pytz==2019.3 -pyyaml==5.3 -requests==2.22.0 -s3transfer==0.3.3 -selenium==3.4.1 -simplejson==3.17.0 -six==1.14.0 -sqlparse==0.3.0 -toml==0.10.0 -tox-battery==0.5.2 -tox==3.14.5 +mock==3.0.5 # via -r test_requirements.in, -r xblock-sdk/requirements/test.txt +more-itertools==5.0.0 # via -r xblock-sdk/requirements/test.txt, pytest +needle==0.5.0 # via -r xblock-sdk/requirements/test.txt, bok-choy +nose==1.3.7 # via -r xblock-sdk/requirements/test.txt, django-nose, needle +packaging==20.1 # via -r xblock-sdk/requirements/test.txt, pytest, tox +pathlib2==2.3.5 # via -r xblock-sdk/requirements/test.txt, pytest +pillow==6.2.2 # via -r xblock-sdk/requirements/test.txt, needle +pluggy==0.13.1 # via -r xblock-sdk/requirements/test.txt, pytest, tox +py==1.8.1 # via -r xblock-sdk/requirements/test.txt, pytest, tox +pycodestyle==2.5.0 # via -r test_requirements.in +pylint==2.4.4 # via -r test_requirements.in +pyparsing==2.4.6 # via -r xblock-sdk/requirements/test.txt, packaging +pypng==0.0.20 # via -r xblock-sdk/requirements/base.txt, -r xblock-sdk/requirements/test.txt +pytest-cov==2.8.1 # via -r xblock-sdk/requirements/test.txt +pytest-django==3.8.0 # via -r xblock-sdk/requirements/test.txt +pytest-rerunfailures==8.0 # via -r xblock-sdk/requirements/test.txt +pytest==4.6.9 # via -r test_requirements.in, -r xblock-sdk/requirements/test.txt, pytest-cov, pytest-django, pytest-rerunfailures +python-dateutil==2.8.1 # via -r xblock-sdk/requirements/base.txt, -r xblock-sdk/requirements/test.txt, botocore, xblock +pytz==2019.3 # via -r xblock-sdk/requirements/base.txt, -r xblock-sdk/requirements/test.txt, django, fs, xblock +pyyaml==5.3 # via -r xblock-sdk/requirements/base.txt, -r xblock-sdk/requirements/test.txt, cookiecutter, xblock +requests==2.22.0 # via -r xblock-sdk/requirements/base.txt, -r xblock-sdk/requirements/test.txt +s3transfer==0.3.3 # via -r xblock-sdk/requirements/base.txt, -r xblock-sdk/requirements/test.txt, boto3 +selenium==3.4.1 # via -r test_requirements.in, -r xblock-sdk/requirements/test.txt, bok-choy, needle +simplejson==3.17.0 # via -r xblock-sdk/requirements/base.txt, -r xblock-sdk/requirements/test.txt, xblock-utils +six==1.14.0 # via -r xblock-sdk/requirements/base.txt, -r xblock-sdk/requirements/test.txt, astroid, bok-choy, django-pyfs, fs, fs-s3fs, mock, more-itertools, packaging, pathlib2, pytest, python-dateutil, tox, virtualenv, xblock +sqlparse==0.3.0 # via -r xblock-sdk/requirements/base.txt, -r xblock-sdk/requirements/test.txt, django +toml==0.10.0 # via -r xblock-sdk/requirements/test.txt, tox +tox-battery==0.5.2 # via -r xblock-sdk/requirements/test.txt +tox==3.14.5 # via -r xblock-sdk/requirements/test.txt, tox-battery typed-ast==1.4.1 # via astroid -typing==3.7.4.1 -urllib3==1.25.8 -virtualenv==20.0.7 -wcwidth==0.1.8 -web-fragments==0.3.1 -webob==1.8.6 +typing==3.7.4.1 # via -r xblock-sdk/requirements/base.txt, -r xblock-sdk/requirements/test.txt, fs +urllib3==1.25.8 # via -r xblock-sdk/requirements/base.txt, -r xblock-sdk/requirements/test.txt, botocore, requests +virtualenv==20.0.7 # via -r xblock-sdk/requirements/test.txt, tox +wcwidth==0.1.8 # via -r xblock-sdk/requirements/test.txt, pytest +web-fragments==0.3.1 # via -r xblock-sdk/requirements/base.txt, -r xblock-sdk/requirements/test.txt, xblock +webob==1.8.6 # via -r test_requirements.in, -r xblock-sdk/requirements/base.txt, -r xblock-sdk/requirements/test.txt, xblock wrapt==1.11.2 # via astroid -xblock==1.2.9 -zipp==1.2.0 +xblock==1.2.9 # via -r test_requirements.in, -r xblock-sdk/requirements/base.txt, -r xblock-sdk/requirements/test.txt, acid-xblock, xblock-utils +zipp==1.2.0 # via -r xblock-sdk/requirements/test.txt, importlib-metadata # The following packages are considered to be unsafe in a requirements file: # setuptools diff --git a/xblock-sdk b/xblock-sdk index 74bf5d60..e3d8f2a5 160000 --- a/xblock-sdk +++ b/xblock-sdk @@ -1 +1 @@ -Subproject commit 74bf5d6010b37e591a687e1e227263d689412279 +Subproject commit e3d8f2a505660bc5c3710c955576a5fefdcc4eaf From cb19c23c86252c9c57bb617033f50256cbece5a7 Mon Sep 17 00:00:00 2001 From: Josh McLaughlin Date: Wed, 18 Mar 2020 03:04:53 -0700 Subject: [PATCH 04/29] Update ForeignKeys for Django 2.2 support --- problem_builder/models.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/problem_builder/models.py b/problem_builder/models.py index be1c226e..ce236fd3 100644 --- a/problem_builder/models.py +++ b/problem_builder/models.py @@ -68,10 +68,10 @@ class Share(models.Model): to query for arbitrary anonymous user IDs. In order to make sharing work, we have to store them here. """ - shared_by = models.ForeignKey(User, related_name='problem_builder_shared_by') + shared_by = models.ForeignKey(User, on_delete=models.CASCADE, related_name='problem_builder_shared_by') submission_uid = models.CharField(max_length=32) block_id = models.CharField(max_length=255, db_index=True) - shared_with = models.ForeignKey(User, related_name='problem_builder_shared_with') + shared_with = models.ForeignKey(User, on_delete=models.CASCADE, related_name='problem_builder_shared_with') notified = models.BooleanField(default=False, db_index=True) class Meta(object): From 389cffecd4952bb7eefc97ad051a90f3014c8208 Mon Sep 17 00:00:00 2001 From: Josh McLaughlin Date: Wed, 18 Mar 2020 03:35:20 -0700 Subject: [PATCH 05/29] Add on_delete to migrations --- problem_builder/migrations/0002_auto_20160121_1525.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/problem_builder/migrations/0002_auto_20160121_1525.py b/problem_builder/migrations/0002_auto_20160121_1525.py index 0de9475c..b6f8be44 100644 --- a/problem_builder/migrations/0002_auto_20160121_1525.py +++ b/problem_builder/migrations/0002_auto_20160121_1525.py @@ -20,8 +20,8 @@ class Migration(migrations.Migration): ('submission_uid', models.CharField(max_length=32)), ('block_id', models.CharField(max_length=255, db_index=True)), ('notified', models.BooleanField(default=False, db_index=True)), - ('shared_by', models.ForeignKey(related_name='problem_builder_shared_by', to=settings.AUTH_USER_MODEL)), - ('shared_with', models.ForeignKey(related_name='problem_builder_shared_with', to=settings.AUTH_USER_MODEL)), + ('shared_by', models.ForeignKey(related_name='problem_builder_shared_by', on_delete=models.CASCADE, to=settings.AUTH_USER_MODEL)), + ('shared_with', models.ForeignKey(related_name='problem_builder_shared_with', on_delete=models.CASCADE, to=settings.AUTH_USER_MODEL)), ], ), migrations.AlterUniqueTogether( From 1cd5769939183b432fff24161ff9a8b919a37a75 Mon Sep 17 00:00:00 2001 From: Josh McLaughlin Date: Sun, 22 Mar 2020 00:00:19 -0700 Subject: [PATCH 06/29] Fix pylint issues --- problem_builder/dashboard.py | 4 ++-- problem_builder/dashboard_visual.py | 2 +- problem_builder/mentoring.py | 4 ++-- problem_builder/message.py | 4 ++-- problem_builder/mixins.py | 14 +++++++------- problem_builder/models.py | 2 +- problem_builder/step.py | 2 +- problem_builder/sub_api.py | 2 +- problem_builder/tests/integration/base_test.py | 6 +++--- .../tests/integration/test_completion.py | 2 +- .../tests/integration/test_dashboard.py | 2 +- .../tests/integration/test_instructor_tool.py | 4 ++-- problem_builder/tests/integration/test_slider.py | 2 +- .../tests/integration/test_step_builder.py | 14 +++++++------- problem_builder/tests/unit/test_mixins.py | 6 +++--- problem_builder/tests/unit/test_step.py | 2 +- problem_builder/tests/unit/utils.py | 4 ++-- problem_builder/utils.py | 4 ++-- problem_builder/v1/xml_changes.py | 2 +- pylintrc | 3 ++- 20 files changed, 43 insertions(+), 42 deletions(-) diff --git a/problem_builder/dashboard.py b/problem_builder/dashboard.py index 1f661a44..1f4e6ff0 100644 --- a/problem_builder/dashboard.py +++ b/problem_builder/dashboard.py @@ -59,7 +59,7 @@ def _(text): # Classes ########################################################### -class ExportMixin(object): +class ExportMixin: """ Used by blocks which need to provide a downloadable export. """ @@ -92,7 +92,7 @@ def _get_course_name(self): return "" -class ColorRule(object): +class ColorRule: """ A rule used to conditionally set colors diff --git a/problem_builder/dashboard_visual.py b/problem_builder/dashboard_visual.py index 4e5e51b7..dc3887dc 100644 --- a/problem_builder/dashboard_visual.py +++ b/problem_builder/dashboard_visual.py @@ -29,7 +29,7 @@ """ -class DashboardVisualData(object): +class DashboardVisualData: """ Data about the visual representation of a dashboard. """ diff --git a/problem_builder/mentoring.py b/problem_builder/mentoring.py index 22e0feb6..f513a90e 100644 --- a/problem_builder/mentoring.py +++ b/problem_builder/mentoring.py @@ -609,7 +609,7 @@ def submit(self, submissions, suffix=''): # server-side check that the user is allowed to submit: if self.max_attempts_reached: raise JsonHandlerError(403, "Maximum number of attempts already reached.") - elif self.has_missing_dependency: + if self.has_missing_dependency: raise JsonHandlerError( 403, "You need to complete all previous steps before being able to complete the current one." @@ -851,7 +851,7 @@ def active_step_safe(self): added/deleted. """ active_step = self.active_step - if active_step >= 0 and active_step < len(self.step_ids): + if 0 <= active_step < len(self.step_ids): return active_step if active_step == -1 and self.has_review_step: return active_step # -1 indicates the review step diff --git a/problem_builder/message.py b/problem_builder/message.py index a0128f4e..10896ddb 100644 --- a/problem_builder/message.py +++ b/problem_builder/message.py @@ -168,12 +168,12 @@ def parse_xml(cls, node, runtime, keys, id_generator): return block -class CompletedMentoringMessageShim(object): +class CompletedMentoringMessageShim: CATEGORY = 'pb-message' STUDIO_LABEL = _("Message (Complete)") -class IncompleteMentoringMessageShim(object): +class IncompleteMentoringMessageShim: CATEGORY = 'pb-message' STUDIO_LABEL = _("Message (Incomplete)") diff --git a/problem_builder/mixins.py b/problem_builder/mixins.py index ce9b8e9d..3d85c1fb 100644 --- a/problem_builder/mixins.py +++ b/problem_builder/mixins.py @@ -31,7 +31,7 @@ def _normalize_id(key): return key -class XBlockWithTranslationServiceMixin(object): +class XBlockWithTranslationServiceMixin: """ Mixin providing access to i18n service """ @@ -80,7 +80,7 @@ def display_name_with_default(self): return self._(self.CAPTION) -class StepParentMixin(object): +class StepParentMixin: """ An XBlock mixin for a parent block containing Step children """ @@ -100,7 +100,7 @@ def steps(self): return [self.runtime.get_block(child_id) for child_id in self.step_ids] -class MessageParentMixin(object): +class MessageParentMixin: """ An XBlock mixin for a parent block containing MentoringMessageBlock children """ @@ -167,7 +167,7 @@ def author_preview_view(self, context): return self.student_view(context) -class NoSettingsMixin(object): +class NoSettingsMixin: """ Mixin for an XBlock that has no settings """ def studio_view(self, _context=None): @@ -175,7 +175,7 @@ def studio_view(self, _context=None): return Fragment(u'

{}

'.format(self._("This XBlock does not have any settings."))) -class StudentViewUserStateMixin(object): +class StudentViewUserStateMixin: """ Mixin to provide student_view_user_state view. @@ -234,7 +234,7 @@ def student_view_user_state(self, context=None, suffix=''): ) -class StudentViewUserStateResultsTransformerMixin(object): +class StudentViewUserStateResultsTransformerMixin: """ A convenient way for MentoringBlock and MentoringStepBlock to share student_results transform code. @@ -267,7 +267,7 @@ def delete_key(self, dictionary, key): return dictionary -class ExpandStaticURLMixin(object): +class ExpandStaticURLMixin: def expand_static_url(self, text): """ diff --git a/problem_builder/models.py b/problem_builder/models.py index ce236fd3..e005b6f9 100644 --- a/problem_builder/models.py +++ b/problem_builder/models.py @@ -74,7 +74,7 @@ class Share(models.Model): shared_with = models.ForeignKey(User, on_delete=models.CASCADE, related_name='problem_builder_shared_with') notified = models.BooleanField(default=False, db_index=True) - class Meta(object): + class Meta: # Since problem_builder isn't added to INSTALLED_APPS until it's imported, # specify the app_label here. app_label = 'problem_builder' diff --git a/problem_builder/step.py b/problem_builder/step.py index 9f4e2a16..691535f5 100644 --- a/problem_builder/step.py +++ b/problem_builder/step.py @@ -67,7 +67,7 @@ def _normalize_id(key): return key -class Correctness(object): +class Correctness: CORRECT = 'correct' PARTIAL = 'partial' INCORRECT = 'incorrect' diff --git a/problem_builder/sub_api.py b/problem_builder/sub_api.py index e5403c77..529d15aa 100644 --- a/problem_builder/sub_api.py +++ b/problem_builder/sub_api.py @@ -30,7 +30,7 @@ sub_api = None # We are probably in the workbench. Don't use the submissions API -class SubmittingXBlockMixin(object): +class SubmittingXBlockMixin: """ Simplifies use of the submissions API by an XBlock. """ diff --git a/problem_builder/tests/integration/base_test.py b/problem_builder/tests/integration/base_test.py index a71240ec..1ca94433 100644 --- a/problem_builder/tests/integration/base_test.py +++ b/problem_builder/tests/integration/base_test.py @@ -36,7 +36,7 @@ CORRECT, INCORRECT, PARTIAL = "correct", "incorrect", "partially-correct" -class PopupCheckMixin(object): +class PopupCheckMixin: """ Code used by MentoringBaseTest and MentoringAssessmentBaseTest """ @@ -190,7 +190,7 @@ def go_to_assessment(self): """ Navigates to assessment page """ mentoring = self.go_to_view("student_view") - class Namespace(object): + class Namespace: pass controls = Namespace() @@ -328,7 +328,7 @@ def _assert_checkmark(self, mentoring, result): self.assertEqual(len(mentoring.find_elements_by_css_selector(".submit .checkmark-{}".format(name))), count) -class GetChoices(object): +class GetChoices: """ Helper class for interacting with MCQ options """ def __init__(self, question, selector=".choices"): self._mcq = question.find_element_by_css_selector(selector) diff --git a/problem_builder/tests/integration/test_completion.py b/problem_builder/tests/integration/test_completion.py index 54cda865..eb809a66 100644 --- a/problem_builder/tests/integration/test_completion.py +++ b/problem_builder/tests/integration/test_completion.py @@ -28,7 +28,7 @@ # Classes ########################################################### -class CompletionBlockTestMixin(object): +class CompletionBlockTestMixin: """ Mixin for testing completion blocks. """ diff --git a/problem_builder/tests/integration/test_dashboard.py b/problem_builder/tests/integration/test_dashboard.py index e78f32de..7bd9fdd0 100644 --- a/problem_builder/tests/integration/test_dashboard.py +++ b/problem_builder/tests/integration/test_dashboard.py @@ -27,7 +27,7 @@ from .base_test import ProblemBuilderBaseTest -class MockSubmissionsAPI(object): +class MockSubmissionsAPI: """ Mock the submissions API, since it's not available in the test environment. """ diff --git a/problem_builder/tests/integration/test_instructor_tool.py b/problem_builder/tests/integration/test_instructor_tool.py index 4fa3bdf0..b7a625cf 100644 --- a/problem_builder/tests/integration/test_instructor_tool.py +++ b/problem_builder/tests/integration/test_instructor_tool.py @@ -13,7 +13,7 @@ from problem_builder.instructor_tool import PAGE_SIZE, InstructorToolBlock -class MockTasksModule(object): +class MockTasksModule: """Mock for the tasks module, which can only be meaningfully import in the LMS.""" def __init__(self, successful=True, display_data=[]): @@ -36,7 +36,7 @@ def __init__(self, successful=True, display_data=[]): self.export_data.delay.return_value = async_result -class MockInstructorTaskModelsModule(object): +class MockInstructorTaskModelsModule: def __init__(self): self.ReportStore = Mock() diff --git a/problem_builder/tests/integration/test_slider.py b/problem_builder/tests/integration/test_slider.py index f8623ea3..39ee167a 100644 --- a/problem_builder/tests/integration/test_slider.py +++ b/problem_builder/tests/integration/test_slider.py @@ -26,7 +26,7 @@ # Classes ########################################################### -class SliderBlockTestMixins(object): +class SliderBlockTestMixins: """ Mixins for testing slider blocks. Assumes only one slider block is on the page. """ def get_slider_value(self): diff --git a/problem_builder/tests/integration/test_step_builder.py b/problem_builder/tests/integration/test_step_builder.py index 21f5dfaa..9885ea10 100644 --- a/problem_builder/tests/integration/test_step_builder.py +++ b/problem_builder/tests/integration/test_step_builder.py @@ -12,7 +12,7 @@ from .test_dashboard import MockSubmissionsAPI -class HTMLColors(object): +class HTMLColors: GREEN = 'rgb(0, 128, 0)' BLUE = 'rgb(0, 0, 255)' RED = 'rgb(255, 0, 0)' @@ -757,7 +757,7 @@ def submit_and_go_to_next_step(self, controls, last=False, no_questions=False): self.wait_until_disabled(controls.next_question) def plot_controls(self, step_builder): - class Namespace(object): + class Namespace: pass plot_controls = Namespace() @@ -769,7 +769,7 @@ class Namespace(object): return plot_controls def additional_plot_controls(self, step_builder): - class Namespace(object): + class Namespace: pass additional_plot_controls = Namespace() @@ -893,14 +893,14 @@ def check_overlays(self, step_builder, total_num_points, overlays): ] self.assertTrue(all(pc == overlay['point_color'] for pc in point_colors)) # Check tooltips for points - tooltips = set([ + tooltips = { point.get_attribute('data-tooltip') for point in points - ]) + } self.assertEquals(tooltips, set(overlay['tooltips'])) # Check positions - point_positions = set([ + point_positions = { (point.get_attribute('cx'), point.get_attribute('cy')) for point in points - ]) + } self.assertEquals(point_positions, set(overlay['positions'])) def test_plot(self): diff --git a/problem_builder/tests/unit/test_mixins.py b/problem_builder/tests/unit/test_mixins.py index dc55e529..7d0aba55 100644 --- a/problem_builder/tests/unit/test_mixins.py +++ b/problem_builder/tests/unit/test_mixins.py @@ -11,13 +11,13 @@ from problem_builder.mixins import StudentViewUserStateMixin -class NoUserStateFieldsMixin(object): +class NoUserStateFieldsMixin: scope_settings = String(name="Field1", scope=Scope.settings) scope_content = String(name="Field1", scope=Scope.content) user_state_summary = String(name="Not in the output", scope=Scope.user_state_summary) -class UserStateFieldsMixin(object): +class UserStateFieldsMixin: answer_1 = String(name="state1", scope=Scope.user_state) answer_2 = Boolean(name="state2", scope=Scope.user_state) @@ -28,7 +28,7 @@ class UserStateFieldsMixin(object): user_info_2 = DateTime(name="info2", scope=Scope.user_info) -class ChildrenMixin(object): +class ChildrenMixin: # overriding children for ease of testing _children = [] has_children = True diff --git a/problem_builder/tests/unit/test_step.py b/problem_builder/tests/unit/test_step.py index b3bb8695..ca27626b 100644 --- a/problem_builder/tests/unit/test_step.py +++ b/problem_builder/tests/unit/test_step.py @@ -38,7 +38,7 @@ def __init__(self): pass -class NotAStep(object): +class NotAStep: pass diff --git a/problem_builder/tests/unit/utils.py b/problem_builder/tests/unit/utils.py index 69263e9d..172cc16d 100644 --- a/problem_builder/tests/unit/utils.py +++ b/problem_builder/tests/unit/utils.py @@ -8,7 +8,7 @@ from xblock.field_data import DictFieldData -class ScoresTestMixin(object): +class ScoresTestMixin: """ Mixin for tests that involve scores (grades) """ @@ -23,7 +23,7 @@ def assert_produces_scores(self, block): self.assertIsInstance(block.max_score(), (int, float)) -class BlockWithChildrenTestMixin(object): +class BlockWithChildrenTestMixin: """ Mixin for tests targeting blocks that contain nested child blocks. """ diff --git a/problem_builder/utils.py b/problem_builder/utils.py index ebff0d61..cade2132 100644 --- a/problem_builder/utils.py +++ b/problem_builder/utils.py @@ -15,7 +15,7 @@ def ngettext_fallback(text_singular, text_plural, number): return text_plural -class DummyTranslationService(object): +class DummyTranslationService: """ Dummy drop-in replacement for i18n XBlock service """ @@ -24,7 +24,7 @@ class DummyTranslationService(object): ngettext = ngettext_fallback -class I18NService(object): +class I18NService: """ Add i18n_service attribute to XBlocks """ diff --git a/problem_builder/v1/xml_changes.py b/problem_builder/v1/xml_changes.py index 743011c1..5356483a 100644 --- a/problem_builder/v1/xml_changes.py +++ b/problem_builder/v1/xml_changes.py @@ -27,7 +27,7 @@ from lxml import etree -class Change(object): +class Change: @staticmethod def applies_to(node): """ diff --git a/pylintrc b/pylintrc index d371e599..53887a89 100644 --- a/pylintrc +++ b/pylintrc @@ -362,7 +362,8 @@ disable=blacklisted-name, xreadlines-attribute, deprecated-sys-function, exception-escape, - comprehension-escape + comprehension-escape, + import-outside-toplevel # Enable the message, report, category or checker with the given id(s). You can # either give multiple identifier separated by comma (,) or put this option From 5309c95c56bd61c58a53a2284a8a3c5142aa13b9 Mon Sep 17 00:00:00 2001 From: Josh McLaughlin Date: Tue, 7 Apr 2020 22:12:19 -0700 Subject: [PATCH 07/29] Update xblock-utils requirement to 2.0.0 --- requirements.txt | 2 +- test_requirements.in | 2 +- test_requirements.txt | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/requirements.txt b/requirements.txt index 31ae73f4..1c323b8f 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,5 +3,5 @@ ddt mock unicodecsv==0.11.0 edx-opaque-keys>=0.4 --e git+https://github.com/edx/xblock-utils.git@1.2.4#egg=xblock-utils +-e git+https://github.com/edx/xblock-utils.git@2.0.0#egg=xblock-utils -e . diff --git a/test_requirements.in b/test_requirements.in index fddc3662..0d3a623f 100644 --- a/test_requirements.in +++ b/test_requirements.in @@ -4,7 +4,7 @@ ddt django_nose>=1.4.6 -e git+https://github.com/edx/acid-block.git@e46f9cda8a03e121a00c7e347084d142d22ebfb7#egg=acid-xblock -e git+https://github.com/edx/django-pyfs.git@2.1#egg=django-pyfs==2.1 --e git+https://github.com/edx/xblock-utils.git@v1.2.3#egg=xblock-utils +-e git+https://github.com/edx/xblock-utils.git@2.0.0#egg=xblock-utils lazy lxml mock diff --git a/test_requirements.txt b/test_requirements.txt index 88ca2c7e..f76ba075 100644 --- a/test_requirements.txt +++ b/test_requirements.txt @@ -7,7 +7,7 @@ -e git+https://github.com/edx/acid-block.git@98aecba94ecbfa934e2d00262741c0ea9f557fc9#egg=acid-xblock # via -r xblock-sdk/requirements/test.txt -e git+https://github.com/edx/django-pyfs.git@2.1#egg=django-pyfs==2.1 # via -r test_requirements.in -e xblock-sdk # via -r test_requirements.in --e git+https://github.com/edx/xblock-utils.git@v1.2.3#egg=xblock-utils # via -r test_requirements.in +-e git+https://github.com/edx/xblock-utils.git@2.0.0#egg=xblock-utils # via -r test_requirements.in appdirs==1.4.3 # via -r xblock-sdk/requirements/base.txt, -r xblock-sdk/requirements/test.txt, fs, virtualenv astroid==2.3.3 # via pylint atomicwrites==1.3.0 # via -r xblock-sdk/requirements/test.txt, pytest @@ -75,7 +75,7 @@ typing==3.7.4.1 # via -r xblock-sdk/requirements/base.txt, -r xblock-s urllib3==1.25.8 # via -r xblock-sdk/requirements/base.txt, -r xblock-sdk/requirements/test.txt, botocore, requests virtualenv==20.0.7 # via -r xblock-sdk/requirements/test.txt, tox wcwidth==0.1.8 # via -r xblock-sdk/requirements/test.txt, pytest -web-fragments==0.3.1 # via -r xblock-sdk/requirements/base.txt, -r xblock-sdk/requirements/test.txt, xblock +web-fragments==0.3.1 # via -r xblock-sdk/requirements/base.txt, -r xblock-sdk/requirements/test.txt, xblock, xblock-utils webob==1.8.6 # via -r test_requirements.in, -r xblock-sdk/requirements/base.txt, -r xblock-sdk/requirements/test.txt, xblock wrapt==1.11.2 # via astroid xblock==1.2.9 # via -r test_requirements.in, -r xblock-sdk/requirements/base.txt, -r xblock-sdk/requirements/test.txt, acid-xblock, xblock-utils From e4ab6d8fbd837aaf5cdf1f8fb30a9b870629bf02 Mon Sep 17 00:00:00 2001 From: Josh McLaughlin Date: Wed, 8 Apr 2020 02:00:20 -0700 Subject: [PATCH 08/29] Switch to mock from unittest --- problem_builder/tests/integration/base_test.py | 2 +- problem_builder/tests/integration/test_dashboard.py | 2 +- problem_builder/tests/integration/test_instructor_tool.py | 2 +- problem_builder/tests/integration/test_mentoring.py | 2 +- problem_builder/tests/integration/test_step_builder.py | 2 +- problem_builder/tests/integration/test_table.py | 2 +- problem_builder/tests/integration/test_titles.py | 2 +- problem_builder/tests/unit/test_instructor_tool.py | 2 +- problem_builder/tests/unit/test_migration.py | 2 +- problem_builder/tests/unit/test_mixins.py | 2 +- problem_builder/tests/unit/test_models.py | 2 +- problem_builder/tests/unit/test_problem_builder.py | 2 +- problem_builder/tests/unit/test_step.py | 2 +- problem_builder/tests/unit/test_step_builder.py | 2 +- problem_builder/tests/unit/test_swipe.py | 2 +- problem_builder/tests/unit/utils.py | 2 +- requirements.txt | 1 - 17 files changed, 16 insertions(+), 17 deletions(-) diff --git a/problem_builder/tests/integration/base_test.py b/problem_builder/tests/integration/base_test.py index 1ca94433..b9b809c9 100644 --- a/problem_builder/tests/integration/base_test.py +++ b/problem_builder/tests/integration/base_test.py @@ -19,7 +19,7 @@ # import time -import mock +from unittest import mock from xblock.fields import String from xblockutils.base_test import SeleniumBaseTest, SeleniumXBlockTest from xblockutils.resources import ResourceLoader diff --git a/problem_builder/tests/integration/test_dashboard.py b/problem_builder/tests/integration/test_dashboard.py index 7bd9fdd0..3533d710 100644 --- a/problem_builder/tests/integration/test_dashboard.py +++ b/problem_builder/tests/integration/test_dashboard.py @@ -21,7 +21,7 @@ from functools import wraps from textwrap import dedent -from mock import Mock, patch +from unittest.mock import Mock, patch from selenium.common.exceptions import NoSuchElementException from .base_test import ProblemBuilderBaseTest diff --git a/problem_builder/tests/integration/test_instructor_tool.py b/problem_builder/tests/integration/test_instructor_tool.py index b7a625cf..78225208 100644 --- a/problem_builder/tests/integration/test_instructor_tool.py +++ b/problem_builder/tests/integration/test_instructor_tool.py @@ -6,7 +6,7 @@ import re import time -from mock import Mock, patch +from unittest.mock import Mock, patch from selenium.common.exceptions import NoSuchElementException from xblockutils.base_test import SeleniumXBlockTest diff --git a/problem_builder/tests/integration/test_mentoring.py b/problem_builder/tests/integration/test_mentoring.py index 373f0f81..d53730af 100644 --- a/problem_builder/tests/integration/test_mentoring.py +++ b/problem_builder/tests/integration/test_mentoring.py @@ -18,7 +18,7 @@ # "AGPLv3". If not, see . # import ddt -import mock +from unittest import mock from selenium.common.exceptions import NoSuchElementException from selenium.webdriver.support.ui import WebDriverWait diff --git a/problem_builder/tests/integration/test_step_builder.py b/problem_builder/tests/integration/test_step_builder.py index 9885ea10..99c32435 100644 --- a/problem_builder/tests/integration/test_step_builder.py +++ b/problem_builder/tests/integration/test_step_builder.py @@ -1,7 +1,7 @@ import time from ddt import data, ddt, unpack -from mock import patch +from unittest.mock import patch from selenium.common.exceptions import NoSuchElementException from selenium.webdriver.support.ui import WebDriverWait diff --git a/problem_builder/tests/integration/test_table.py b/problem_builder/tests/integration/test_table.py index f7be6948..14131e8e 100644 --- a/problem_builder/tests/integration/test_table.py +++ b/problem_builder/tests/integration/test_table.py @@ -20,7 +20,7 @@ # Imports ########################################################### -from mock import patch +from unittest.mock import patch from workbench.runtime import WorkbenchRuntime diff --git a/problem_builder/tests/integration/test_titles.py b/problem_builder/tests/integration/test_titles.py index 3083de88..3156fdd1 100644 --- a/problem_builder/tests/integration/test_titles.py +++ b/problem_builder/tests/integration/test_titles.py @@ -23,7 +23,7 @@ # Imports ########################################################### import ddt -from mock import patch +from unittest.mock import patch from xblockutils.base_test import SeleniumXBlockTest # Classes ########################################################### diff --git a/problem_builder/tests/unit/test_instructor_tool.py b/problem_builder/tests/unit/test_instructor_tool.py index 8d6648b4..24f13f3e 100644 --- a/problem_builder/tests/unit/test_instructor_tool.py +++ b/problem_builder/tests/unit/test_instructor_tool.py @@ -4,7 +4,7 @@ import unittest import ddt -from mock import Mock, patch +from unittest.mock import Mock, patch from xblock.field_data import DictFieldData from problem_builder.instructor_tool import (COURSE_BLOCKS_API, diff --git a/problem_builder/tests/unit/test_migration.py b/problem_builder/tests/unit/test_migration.py index 8202d172..cbabc56c 100644 --- a/problem_builder/tests/unit/test_migration.py +++ b/problem_builder/tests/unit/test_migration.py @@ -1,7 +1,7 @@ import copy import unittest -from mock import MagicMock, Mock +from unittest.mock import MagicMock, Mock from xblock.field_data import DictFieldData from problem_builder.mentoring import MentoringBlock diff --git a/problem_builder/tests/unit/test_mixins.py b/problem_builder/tests/unit/test_mixins.py index 7d0aba55..0d2d10af 100644 --- a/problem_builder/tests/unit/test_mixins.py +++ b/problem_builder/tests/unit/test_mixins.py @@ -3,7 +3,7 @@ from datetime import datetime import pytz -from mock import MagicMock, Mock +from unittest.mock import MagicMock, Mock from xblock.core import XBlock from xblock.field_data import DictFieldData from xblock.fields import Boolean, DateTime, Integer, Scope, String diff --git a/problem_builder/tests/unit/test_models.py b/problem_builder/tests/unit/test_models.py index e4fd5773..90bcb5d8 100644 --- a/problem_builder/tests/unit/test_models.py +++ b/problem_builder/tests/unit/test_models.py @@ -2,7 +2,7 @@ Unit tests for models. """ from django.test import TestCase -from mock import MagicMock, PropertyMock +from unittest.mock import MagicMock, PropertyMock from problem_builder.models import Answer, delete_anonymous_user_answers diff --git a/problem_builder/tests/unit/test_problem_builder.py b/problem_builder/tests/unit/test_problem_builder.py index e2875fc4..d7b5aa5b 100644 --- a/problem_builder/tests/unit/test_problem_builder.py +++ b/problem_builder/tests/unit/test_problem_builder.py @@ -2,7 +2,7 @@ from random import random import ddt -from mock import MagicMock, Mock, PropertyMock, patch +from unittest.mock import MagicMock, Mock, PropertyMock, patch from xblock.field_data import DictFieldData from problem_builder.answer import AnswerRecapBlock diff --git a/problem_builder/tests/unit/test_step.py b/problem_builder/tests/unit/test_step.py index ca27626b..0e86f4f8 100644 --- a/problem_builder/tests/unit/test_step.py +++ b/problem_builder/tests/unit/test_step.py @@ -1,6 +1,6 @@ import unittest -from mock import Mock +from unittest.mock import Mock from xblock.field_data import DictFieldData from problem_builder.mixins import QuestionMixin, StepParentMixin diff --git a/problem_builder/tests/unit/test_step_builder.py b/problem_builder/tests/unit/test_step_builder.py index 69f3d634..bb053bf0 100644 --- a/problem_builder/tests/unit/test_step_builder.py +++ b/problem_builder/tests/unit/test_step_builder.py @@ -1,6 +1,6 @@ import unittest -from mock import Mock +from unittest.mock import Mock from xblock.field_data import DictFieldData from problem_builder.mentoring import MentoringWithExplicitStepsBlock diff --git a/problem_builder/tests/unit/test_swipe.py b/problem_builder/tests/unit/test_swipe.py index 2ed3d37e..d48d5974 100644 --- a/problem_builder/tests/unit/test_swipe.py +++ b/problem_builder/tests/unit/test_swipe.py @@ -1,7 +1,7 @@ import unittest import ddt -from mock import Mock +from unittest.mock import Mock from xblock.field_data import DictFieldData from problem_builder.swipe import SwipeBlock diff --git a/problem_builder/tests/unit/utils.py b/problem_builder/tests/unit/utils.py index 172cc16d..6fdfda95 100644 --- a/problem_builder/tests/unit/utils.py +++ b/problem_builder/tests/unit/utils.py @@ -4,7 +4,7 @@ import json from datetime import date, datetime -from mock import MagicMock, Mock, patch +from unittest.mock import MagicMock, Mock, patch from xblock.field_data import DictFieldData diff --git a/requirements.txt b/requirements.txt index 1c323b8f..89d4ce10 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,6 +1,5 @@ XBlock>=1.2 ddt -mock unicodecsv==0.11.0 edx-opaque-keys>=0.4 -e git+https://github.com/edx/xblock-utils.git@2.0.0#egg=xblock-utils From ae85b3fd3278144dcb0777d2de4184c57e100294 Mon Sep 17 00:00:00 2001 From: Josh McLaughlin Date: Wed, 8 Apr 2020 02:45:00 -0700 Subject: [PATCH 09/29] Remove Python 2.7 test jobs --- circle.yml | 54 ------------------------------------------------------ 1 file changed, 54 deletions(-) diff --git a/circle.yml b/circle.yml index 8d233dcd..f8ef0304 100644 --- a/circle.yml +++ b/circle.yml @@ -125,60 +125,6 @@ workflows: version: 2 build_and_deploy: jobs: - - build: - name: py27-quality - test_command: make quality - docker_image: circleci/python:2.7-buster-browsers - filters: - tags: - only: /.*/ - - build: - name: py27-unit - test_command: make test.unit - docker_image: circleci/python:2.7-buster-browsers - filters: - tags: - only: /.*/ - - build: - name: py27-integration - test_command: make test.integration - docker_image: circleci/python:2.7-buster-browsers - filters: - tags: - only: /.*/ - - coverage: - name: py27-coverage - docker_image: circleci/python:2.7-buster - filters: - tags: - only: /.*/ - requires: - - py27-quality - - py27-unit - - py27-integration - - deploy: - name: py27-deploy-sdist - docker_image: circleci/python:2.7-buster - dist_type: sdist - requires: - - py27-coverage - filters: - tags: - only: /v[0-9]+(\.[0-9]+)*/ - branches: - ignore: /.*/ - - deploy: - name: py27-deploy-bdist_wheel - docker_image: circleci/python:2.7-buster - dist_type: bdist_wheel - requires: - - py27-coverage - filters: - tags: - only: /v[0-9]+(\.[0-9]+)*/ - branches: - ignore: /.*/ - - build: name: py35-quality test_command: make quality From 5e60999be8bca4c8663c4c4cd3d954526067c39d Mon Sep 17 00:00:00 2001 From: Josh McLaughlin Date: Wed, 8 Apr 2020 13:26:50 -0700 Subject: [PATCH 10/29] Fix i18n service mocking in unit tests --- problem_builder/tests/unit/test_problem_builder.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/problem_builder/tests/unit/test_problem_builder.py b/problem_builder/tests/unit/test_problem_builder.py index d7b5aa5b..5f38eb4c 100644 --- a/problem_builder/tests/unit/test_problem_builder.py +++ b/problem_builder/tests/unit/test_problem_builder.py @@ -4,6 +4,7 @@ import ddt from unittest.mock import MagicMock, Mock, PropertyMock, patch from xblock.field_data import DictFieldData +from xblock.runtime import NullI18nService from problem_builder.answer import AnswerRecapBlock from problem_builder.mcq import MCQBlock @@ -56,6 +57,7 @@ def test_sends_progress_event_when_rendered_student_view_with_display_submit_fal with patch.object(block, 'runtime') as patched_runtime: patched_runtime.publish = Mock() + patched_runtime.service = lambda _, service: NullI18nService() if service == 'i18n' else MagicMock() block.student_view(context={}) @@ -68,6 +70,7 @@ def test_does_not_send_progress_event_when_rendered_student_view_with_display_su with patch.object(block, 'runtime') as patched_runtime: patched_runtime.publish = Mock() + patched_runtime.service = lambda _, service: NullI18nService() if service == 'i18n' else MagicMock() block.student_view(context={}) @@ -95,7 +98,7 @@ def test_does_not_crash_when_get_child_is_broken(self): with patch.object(block, 'runtime') as patched_runtime: patched_runtime.publish = Mock() - patched_runtime.service().ugettext = lambda str: str + patched_runtime.service = lambda _, service: NullI18nService() if service == 'i18n' else MagicMock() patched_runtime.get_block = lambda block_id: None patched_runtime.load_block_type = lambda block_id: Mock From d271b161bc22152bbed3cc4e964b0f7605266acd Mon Sep 17 00:00:00 2001 From: Josh McLaughlin Date: Wed, 8 Apr 2020 14:10:04 -0700 Subject: [PATCH 11/29] Update version string to 4.0.0 --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 8a3a31ee..1dec85bc 100644 --- a/setup.py +++ b/setup.py @@ -28,7 +28,7 @@ # Constants ######################################################### -VERSION = '3.4.14' +VERSION = '4.0.0' # Functions ######################################################### From 281b3c2f1cb0ddc7a2cbb7be52977db845d66069 Mon Sep 17 00:00:00 2001 From: Josh McLaughlin Date: Wed, 8 Apr 2020 14:19:37 -0700 Subject: [PATCH 12/29] Update README.md with version stipulations --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 26ca3f28..f9e24e2b 100644 --- a/README.md +++ b/README.md @@ -221,6 +221,9 @@ Problem Builder releases are tagged with a version number, e.g. [`v2.6.5`](https://github.com/open-craft/problem-builder/tree/v2.6.5). We recommend installing the most recently tagged version, with the exception of the following compatibility issues: +* `edx-platform` version `open-release/ironwood.2` and earlier must use + ≤[v3.4.14](https://github.com/open-craft/problem-builder/tree/v3.4.14). See + [PR 262](https://github.com/open-craft/problem-builder/pull/262) for details. * `edx-platform` version `open-release/eucalyptus.2` and earlier must use ≤[v2.6.0](https://github.com/open-craft/problem-builder/tree/v2.6.0). See [PR 128](https://github.com/open-craft/problem-builder/pull/128) for details. From 463fa5c28a3f704b33873fb927b85f3b63ded4d2 Mon Sep 17 00:00:00 2001 From: Josh McLaughlin Date: Thu, 9 Apr 2020 22:06:27 -0700 Subject: [PATCH 13/29] Fix ResourceLoader.render_template deprecation warnings --- problem_builder/answer.py | 4 ++-- problem_builder/completion.py | 2 +- problem_builder/dashboard.py | 4 ++-- problem_builder/instructor_tool.py | 2 +- problem_builder/mcq.py | 6 +++--- problem_builder/mentoring.py | 6 +++--- problem_builder/mrq.py | 2 +- problem_builder/plot.py | 6 +++--- problem_builder/questionnaire.py | 2 +- problem_builder/slider.py | 4 ++-- problem_builder/step_review.py | 2 +- problem_builder/table.py | 12 ++++++------ problem_builder/tests/integration/base_test.py | 4 ++-- problem_builder/tests/unit/test_instructor_tool.py | 4 ++-- problem_builder/tip.py | 2 +- 15 files changed, 31 insertions(+), 31 deletions(-) diff --git a/problem_builder/answer.py b/problem_builder/answer.py index 52dafcc8..2d1a0e0a 100644 --- a/problem_builder/answer.py +++ b/problem_builder/answer.py @@ -184,7 +184,7 @@ def mentoring_view(self, context=None): context['answer_editable_id'] = uuid.uuid4().hex[:15] context['self'] = self context['hide_header'] = context.get('hide_header', False) or not self.show_title - html = loader.render_template('templates/html/answer_editable.html', context) + html = loader.render_django_template('templates/html/answer_editable.html', context) fragment = Fragment(html) fragment.add_css_url(self.runtime.local_resource_url(self, 'public/css/answer.css')) @@ -332,7 +332,7 @@ def mentoring_view(self, context=None): context['student_input'] = None else: context['student_input'] = self.student_input - html = loader.render_template('templates/html/answer_read_only.html', context) + html = loader.render_django_template('templates/html/answer_read_only.html', context) fragment = Fragment(html) fragment.add_css_url(self.runtime.local_resource_url(self, self.css_path)) diff --git a/problem_builder/completion.py b/problem_builder/completion.py index d97a375c..3931b6d3 100644 --- a/problem_builder/completion.py +++ b/problem_builder/completion.py @@ -144,7 +144,7 @@ def mentoring_view(self, context): context['title'] = self.display_name_with_default context['hide_header'] = context.get('hide_header', False) or not self.show_title - html = loader.render_template('templates/html/completion.html', context) + html = loader.render_django_template('templates/html/completion.html', context) fragment = Fragment(html) fragment.add_javascript_url(self.runtime.local_resource_url(self, 'public/js/completion.js')) diff --git a/problem_builder/dashboard.py b/problem_builder/dashboard.py index 1f4e6ff0..20f8fb13 100644 --- a/problem_builder/dashboard.py +++ b/problem_builder/dashboard.py @@ -457,14 +457,14 @@ def student_view(self, context=None): # pylint: disable=unused-argument blocks, rules_parsed, self.color_for_value, self.visual_title, self.visual_desc ) - report_template = loader.render_template('templates/html/dashboard_report.html', { + report_template = loader.render_django_template('templates/html/dashboard_report.html', { 'title': self.display_name, 'css': loader.load_unicode(self.css_path), 'student_name': self._get_user_full_name(), 'course_name': self._get_course_name(), }) - html = loader.render_template('templates/html/dashboard.html', { + html = loader.render_django_template('templates/html/dashboard.html', { 'blocks': blocks, 'display_name': self.display_name, 'visual_repr': visual_repr, diff --git a/problem_builder/instructor_tool.py b/problem_builder/instructor_tool.py index 37696deb..e0652d67 100644 --- a/problem_builder/instructor_tool.py +++ b/problem_builder/instructor_tool.py @@ -142,7 +142,7 @@ def student_view(self, context=None): _('Long Answer'): 'AnswerBlock', } - html = loader.render_template('templates/html/instructor_tool.html', { + html = loader.render_django_template('templates/html/instructor_tool.html', { 'block_choices': block_choices, 'course_blocks_api': COURSE_BLOCKS_API, 'root_block_id': six.text_type(getattr(self.runtime, 'course_id', 'course_id')), diff --git a/problem_builder/mcq.py b/problem_builder/mcq.py index 1b0325a2..4ba60dd2 100644 --- a/problem_builder/mcq.py +++ b/problem_builder/mcq.py @@ -101,7 +101,7 @@ def calculate_results(self, submission): formatted_tips = None if tips_html: - formatted_tips = loader.render_template('templates/html/tip_choice_group.html', { + formatted_tips = loader.render_django_template('templates/html/tip_choice_group.html', { 'tips_html': tips_html, }) @@ -239,7 +239,7 @@ def get_author_edit_view_fragment(self, context): show them in the author edit view, for clarity. """ fragment = Fragment() - fragment.add_content(loader.render_template('templates/html/ratingblock_edit_preview.html', { + fragment.add_content(loader.render_django_template('templates/html/ratingblock_edit_preview.html', { 'question': self.question, 'low': self.low, 'high': self.high, @@ -265,7 +265,7 @@ def student_view(self, context): if context: # Workbench does not provide context rendering_for_studio = context.get('author_edit_view') if rendering_for_studio: - fragment.add_content(loader.render_template('templates/html/rating_edit_footer.html', { + fragment.add_content(loader.render_django_template('templates/html/rating_edit_footer.html', { "url_name": self.url_name })) return fragment diff --git a/problem_builder/mentoring.py b/problem_builder/mentoring.py index f513a90e..c1f0ebcb 100644 --- a/problem_builder/mentoring.py +++ b/problem_builder/mentoring.py @@ -214,7 +214,7 @@ def author_preview_view(self, context): authors in Studio when not editing this block's children. """ fragment = self.student_view(context) - fragment.add_content(loader.render_template('templates/html/mentoring_url_name.html', { + fragment.add_content(loader.render_django_template('templates/html/mentoring_url_name.html', { "url_name": self.url_name })) fragment.add_css_url(self.runtime.local_resource_url(self, 'public/css/problem-builder-edit.css')) @@ -742,7 +742,7 @@ def author_edit_view(self, context): local_context = context.copy() local_context['author_edit_view'] = True fragment = super(MentoringBlock, self).author_edit_view(local_context) - fragment.add_content(loader.render_template('templates/html/mentoring_url_name.html', { + fragment.add_content(loader.render_django_template('templates/html/mentoring_url_name.html', { 'url_name': self.url_name })) fragment.add_css_url(self.runtime.local_resource_url(self, 'public/css/problem-builder.css')) @@ -1107,7 +1107,7 @@ def author_edit_view(self, context): Add some HTML to the author view that allows authors to add child blocks. """ fragment = super(MentoringWithExplicitStepsBlock, self).author_edit_view(context) - fragment.add_content(loader.render_template('templates/html/mentoring_url_name.html', { + fragment.add_content(loader.render_django_template('templates/html/mentoring_url_name.html', { "url_name": self.url_name })) fragment.add_css_url(self.runtime.local_resource_url(self, 'public/css/problem-builder.css')) diff --git a/problem_builder/mrq.py b/problem_builder/mrq.py index bb6f3cdf..e487b9d4 100644 --- a/problem_builder/mrq.py +++ b/problem_builder/mrq.py @@ -157,7 +157,7 @@ def calculate_results(self, submissions): loader = ResourceLoader(__name__) choice_result['completed'] = choice_completed - choice_result['tips'] = loader.render_template('templates/html/tip_choice_group.html', { + choice_result['tips'] = loader.render_django_template('templates/html/tip_choice_group.html', { 'tips_html': choice_tips_html, }) diff --git a/problem_builder/plot.py b/problem_builder/plot.py index 92fc6b3b..0aa8ac53 100644 --- a/problem_builder/plot.py +++ b/problem_builder/plot.py @@ -327,7 +327,7 @@ def claims_display(self): def author_preview_view(self, context): context['self'] = self fragment = Fragment() - fragment.add_content(loader.render_template('templates/html/plot_preview.html', context)) + fragment.add_content(loader.render_django_template('templates/html/plot_preview.html', context)) fragment.add_css_url(self.runtime.local_resource_url(self, 'public/css/plot-preview.css')) if self.overlay_ids: fragment.add_content( @@ -349,7 +349,7 @@ def student_view(self, context=None): context['hide_header'] = True context['self'] = self fragment = Fragment() - fragment.add_content(loader.render_template('templates/html/plot.html', context)) + fragment.add_content(loader.render_django_template('templates/html/plot.html', context)) fragment.add_css_url(self.runtime.local_resource_url(self, 'public/css/plot.css')) fragment.add_javascript_url(self.runtime.local_resource_url(self, 'public/js/vendor/d3.min.js')) fragment.add_javascript_url(self.runtime.local_resource_url(self, 'public/js/plot.js')) @@ -481,6 +481,6 @@ def mentoring_view(self, context): def student_view(self, context): context['self'] = self fragment = Fragment() - fragment.add_content(loader.render_template('templates/html/overlay.html', context)) + fragment.add_content(loader.render_django_template('templates/html/overlay.html', context)) fragment.add_css_url(self.runtime.local_resource_url(self, 'public/css/overlay.css')) return fragment diff --git a/problem_builder/questionnaire.py b/problem_builder/questionnaire.py index 9deece32..aa255888 100644 --- a/problem_builder/questionnaire.py +++ b/problem_builder/questionnaire.py @@ -171,7 +171,7 @@ def author_edit_view(self, context): self.get_parent().get_parent() if self.get_parent() else None, MentoringWithExplicitStepsBlock ) - fragment.add_content(loader.render_template('templates/html/questionnaire_add_buttons.html', { + fragment.add_content(loader.render_django_template('templates/html/questionnaire_add_buttons.html', { 'show_review': show_review })) fragment.add_css_url(self.runtime.local_resource_url(self, 'public/css/problem-builder.css')) diff --git a/problem_builder/slider.py b/problem_builder/slider.py index d820fe83..0e88db78 100644 --- a/problem_builder/slider.py +++ b/problem_builder/slider.py @@ -115,7 +115,7 @@ def mentoring_view(self, context): context['instructions_string'] = self._("Select a value from {min_label} to {max_label}").format( min_label=self.min_label, max_label=self.max_label ) - html = loader.render_template('templates/html/slider.html', context) + html = loader.render_django_template('templates/html/slider.html', context) fragment = Fragment(html) fragment.add_javascript_url(self.runtime.local_resource_url(self, 'public/js/slider.js')) @@ -145,7 +145,7 @@ def author_view(self, context): """ context['hide_header'] = True # Header is already shown in the Studio wrapper fragment = self.student_view(context) - fragment.add_content(loader.render_template('templates/html/slider_edit_footer.html', { + fragment.add_content(loader.render_django_template('templates/html/slider_edit_footer.html', { "url_name": self.url_name })) return fragment diff --git a/problem_builder/step_review.py b/problem_builder/step_review.py index 4a3b1aed..3d5d701c 100644 --- a/problem_builder/step_review.py +++ b/problem_builder/step_review.py @@ -213,7 +213,7 @@ def student_view(self, context=None): """ Render the per-question feedback, if any. """ review_tips = (context or {}).get("score_summary", {}).get("review_tips") if review_tips: - html = loader.render_template("templates/html/sb-review-per-question-feedback.html", { + html = loader.render_django_template("templates/html/sb-review-per-question-feedback.html", { 'tips': review_tips, }) else: diff --git a/problem_builder/table.py b/problem_builder/table.py index ea529a38..2669465c 100644 --- a/problem_builder/table.py +++ b/problem_builder/table.py @@ -130,7 +130,7 @@ def table_render(self, data, suffix=''): content_values.append(child_frag.content) context['header_values'] = header_values if any(header_values) else None context['content_values'] = content_values - html = loader.render_template('templates/html/mentoring-table.html', context) + html = loader.render_django_template('templates/html/mentoring-table.html', context) return {'content': html} @property @@ -147,7 +147,7 @@ def get_shared_list(self, data, suffix=''): ).values_list('shared_with__username', flat=True) } return { - 'content': loader.render_template('templates/html/mentoring-table-shared-list.html', context) + 'content': loader.render_django_template('templates/html/mentoring-table-shared-list.html', context) } @XBlock.json_handler @@ -266,14 +266,14 @@ def student_view(self, context): else: raise - report_template = loader.render_template('templates/html/mentoring-table-report.html', { + report_template = loader.render_django_template('templates/html/mentoring-table-report.html', { 'title': self.display_name, 'css': loader.load_unicode(AnswerRecapBlock.css_path) + loader.load_unicode(self.css_path), 'student_name': self._get_user_full_name(), 'course_name': self._get_course_name(), }) - fragment.add_content(loader.render_template('templates/html/mentoring-table-container.html', context)) + fragment.add_content(loader.render_django_template('templates/html/mentoring-table-container.html', context)) fragment.add_css_url(self.runtime.local_resource_url(self, 'public/css/mentoring-table.css')) fragment.add_javascript_url(self.runtime.local_resource_url(self, 'public/js/vendor/jquery-shorten.js')) fragment.add_javascript_url(self.runtime.local_resource_url(self, self.js_path)) @@ -295,7 +295,7 @@ def author_edit_view(self, context): Add some HTML to the author view that allows authors to add choices and tips. """ fragment = super(MentoringTableBlock, self).author_edit_view(context) - fragment.add_content(loader.render_template('templates/html/mentoring-table-add-button.html', {})) + fragment.add_content(loader.render_django_template('templates/html/mentoring-table-add-button.html', {})) # Share styles with the questionnaire edit CSS: fragment.add_css_url(self.runtime.local_resource_url(self, 'public/css/questionnaire-edit.css')) return fragment @@ -345,7 +345,7 @@ def author_edit_view(self, context): """ fragment = super(MentoringTableColumn, self).author_edit_view(context) fragment.content = u"
{}
".format(self.header) + fragment.content - fragment.add_content(loader.render_template('templates/html/mentoring-column-add-button.html', {})) + fragment.add_content(loader.render_django_template('templates/html/mentoring-column-add-button.html', {})) # Share styles with the questionnaire edit CSS: fragment.add_css_url(self.runtime.local_resource_url(self, 'public/css/questionnaire-edit.css')) return fragment diff --git a/problem_builder/tests/integration/base_test.py b/problem_builder/tests/integration/base_test.py index b9b809c9..78aad9f2 100644 --- a/problem_builder/tests/integration/base_test.py +++ b/problem_builder/tests/integration/base_test.py @@ -89,7 +89,7 @@ def load_scenario(self, xml_file, params=None, load_immediately=True): Given the name of an XML file in the xml_templates folder, load it into the workbench. """ params = params or {} - scenario = loader.render_template("xml_templates/{}".format(xml_file), params) + scenario = loader.render_django_template("xml_templates/{}".format(xml_file), params) self.set_scenario_xml(scenario) if load_immediately: return self.go_to_view("student_view") @@ -182,7 +182,7 @@ def question_text(number): def load_assessment_scenario(self, xml_file, params=None): """ Loads an assessment scenario from an XML template """ params = params or {} - scenario = loader.render_template("xml_templates/{}".format(xml_file), params) + scenario = loader.render_django_template("xml_templates/{}".format(xml_file), params) self.set_scenario_xml(scenario) return self.go_to_assessment() diff --git a/problem_builder/tests/unit/test_instructor_tool.py b/problem_builder/tests/unit/test_instructor_tool.py index 24f13f3e..098f3c41 100644 --- a/problem_builder/tests/unit/test_instructor_tool.py +++ b/problem_builder/tests/unit/test_instructor_tool.py @@ -57,9 +57,9 @@ def test_student_view_template_args(self): } with patch('problem_builder.instructor_tool.loader') as patched_loader: - patched_loader.render_template.return_value = u'' + patched_loader.render_django_template.return_value = u'' self.block.student_view() - patched_loader.render_template.assert_called_once_with('templates/html/instructor_tool.html', { + patched_loader.render_django_template.assert_called_once_with('templates/html/instructor_tool.html', { 'block_choices': block_choices, 'course_blocks_api': COURSE_BLOCKS_API, 'root_block_id': self.course_id, diff --git a/problem_builder/tip.py b/problem_builder/tip.py index b33a0557..858d44af 100644 --- a/problem_builder/tip.py +++ b/problem_builder/tip.py @@ -89,7 +89,7 @@ def display_name_with_default(self): def mentoring_view(self, context=None): """ Render this XBlock within a mentoring block. """ - html = loader.render_template("templates/html/tip.html", { + html = loader.render_django_template("templates/html/tip.html", { 'content': self.content, 'width': self.width, 'height': self.height, From 2c4df752d3fe5787cebad58a8955bd1df2b133f7 Mon Sep 17 00:00:00 2001 From: Josh McLaughlin Date: Thu, 9 Apr 2020 23:25:59 -0700 Subject: [PATCH 14/29] Switch CircleCI to use MySQL --- circle.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/circle.yml b/circle.yml index f8ef0304..e44efdf5 100644 --- a/circle.yml +++ b/circle.yml @@ -3,6 +3,7 @@ jobs: build: docker: - image: <> + - image: circleci/mysql:5.6 parameters: test_command: type: string @@ -10,6 +11,11 @@ jobs: type: string environment: MOZ_HEADLESS: 1 + MYSQL_ROOT_PASSWORD: rootpw + MYSQL_DATABASE: test_db + MYSQL_USER: user + MYSQL_PASSWORD: passw0rd + WORKBENCH_DATABASES: '{"default": {"ENGINE": "django.db.backends.mysql", "NAME": "test_db", "USER": "user", "PASSWORD": "passw0rd", "HOST": "127.0.0.1"}}' steps: - checkout - run: From 48b687cc53573b68377d864790791636b0bda4b9 Mon Sep 17 00:00:00 2001 From: Josh McLaughlin Date: Thu, 9 Apr 2020 23:32:36 -0700 Subject: [PATCH 15/29] Add mysql package for CircleCi --- circle.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/circle.yml b/circle.yml index e44efdf5..a0cc4805 100644 --- a/circle.yml +++ b/circle.yml @@ -22,7 +22,7 @@ jobs: name: Update system command: | sudo apt-get update - sudo apt-get install -y libgtk3.0-cil-dev libasound2 libasound2 libdbus-glib-1-2 libdbus-1-3 libgtk2.0-0 + sudo apt-get install -y libgtk3.0-cil-dev libasound2 libasound2 libdbus-glib-1-2 libdbus-1-3 libgtk2.0-0 libmysqlclient-dev - run: name: Install geckodriver command: | From dd244bfee1c4a4eb8b19fea5e1467a3b4d56822c Mon Sep 17 00:00:00 2001 From: Josh McLaughlin Date: Thu, 9 Apr 2020 23:35:12 -0700 Subject: [PATCH 16/29] Add mysql requirements to test_requirements --- test_requirements.in | 2 ++ test_requirements.txt | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/test_requirements.in b/test_requirements.in index 0d3a623f..ab4750cd 100644 --- a/test_requirements.in +++ b/test_requirements.in @@ -15,5 +15,7 @@ Django~=2.2.10 pytest pylint pycodestyle +django-mysql +mysqlclient -r xblock-sdk/requirements/base.txt -r xblock-sdk/requirements/test.txt diff --git a/test_requirements.txt b/test_requirements.txt index f76ba075..b1eada07 100644 --- a/test_requirements.txt +++ b/test_requirements.txt @@ -23,8 +23,9 @@ cookiecutter==0.9.0 # via -r xblock-sdk/requirements/base.txt, -r xblock-s coverage==5.0.3 # via -r xblock-sdk/requirements/test.txt, pytest-cov ddt==1.2.2 # via -r test_requirements.in, -r xblock-sdk/requirements/test.txt distlib==0.3.0 # via -r xblock-sdk/requirements/test.txt, virtualenv +django-mysql==2.4.1 # via -r test_requirements.in django-nose==1.4.6 # via -r test_requirements.in -django==2.2.10 # via -r test_requirements.in, -r xblock-sdk/requirements/base.txt, django-pyfs, xblock-sdk +django==2.2.10 # via -r test_requirements.in, -r xblock-sdk/requirements/base.txt, django-mysql, django-pyfs, xblock-sdk docutils==0.15.2 # via -r xblock-sdk/requirements/base.txt, -r xblock-sdk/requirements/test.txt, botocore filelock==3.0.12 # via -r xblock-sdk/requirements/test.txt, tox, virtualenv fs-s3fs==0.1.8 # via -r xblock-sdk/requirements/base.txt, -r xblock-sdk/requirements/test.txt, django-pyfs @@ -43,6 +44,7 @@ markupsafe==1.1.1 # via -r xblock-sdk/requirements/base.txt, -r xblock-s mccabe==0.6.1 # via pylint mock==3.0.5 # via -r test_requirements.in, -r xblock-sdk/requirements/test.txt more-itertools==5.0.0 # via -r xblock-sdk/requirements/test.txt, pytest +mysqlclient==1.4.6 # via -r test_requirements.in needle==0.5.0 # via -r xblock-sdk/requirements/test.txt, bok-choy nose==1.3.7 # via -r xblock-sdk/requirements/test.txt, django-nose, needle packaging==20.1 # via -r xblock-sdk/requirements/test.txt, pytest, tox From b749419b8676a3f9e6697a15de52b8a8e2d0c012 Mon Sep 17 00:00:00 2001 From: Guruprasad Lakshmi Narayanan Date: Fri, 10 Apr 2020 12:10:52 +0530 Subject: [PATCH 17/29] Use 'default-libmysqlclient-dev' package on CircleCI --- circle.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/circle.yml b/circle.yml index a0cc4805..8bcd3305 100644 --- a/circle.yml +++ b/circle.yml @@ -22,7 +22,7 @@ jobs: name: Update system command: | sudo apt-get update - sudo apt-get install -y libgtk3.0-cil-dev libasound2 libasound2 libdbus-glib-1-2 libdbus-1-3 libgtk2.0-0 libmysqlclient-dev + sudo apt-get install -y libgtk3.0-cil-dev libasound2 libasound2 libdbus-glib-1-2 libdbus-1-3 libgtk2.0-0 default-libmysqlclient-dev - run: name: Install geckodriver command: | From 2f43551985031abc1ed3511588802983df979dfe Mon Sep 17 00:00:00 2001 From: Guruprasad Lakshmi Narayanan Date: Fri, 10 Apr 2020 12:21:55 +0530 Subject: [PATCH 18/29] Move the MySQL environment variables to the mysql image section --- circle.yml | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/circle.yml b/circle.yml index 8bcd3305..bfb89cfa 100644 --- a/circle.yml +++ b/circle.yml @@ -4,6 +4,11 @@ jobs: docker: - image: <> - image: circleci/mysql:5.6 + environment: + MYSQL_ROOT_PASSWORD: rootpw + MYSQL_DATABASE: test_db + MYSQL_USER: user + MYSQL_PASSWORD: passw0rd parameters: test_command: type: string @@ -11,10 +16,6 @@ jobs: type: string environment: MOZ_HEADLESS: 1 - MYSQL_ROOT_PASSWORD: rootpw - MYSQL_DATABASE: test_db - MYSQL_USER: user - MYSQL_PASSWORD: passw0rd WORKBENCH_DATABASES: '{"default": {"ENGINE": "django.db.backends.mysql", "NAME": "test_db", "USER": "user", "PASSWORD": "passw0rd", "HOST": "127.0.0.1"}}' steps: - checkout From d64c7a90f8a0df8d69699cc33ce80f68a9c6198b Mon Sep 17 00:00:00 2001 From: Josh McLaughlin Date: Thu, 9 Apr 2020 23:55:06 -0700 Subject: [PATCH 19/29] Fix test database name --- circle.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/circle.yml b/circle.yml index bfb89cfa..355db5d9 100644 --- a/circle.yml +++ b/circle.yml @@ -16,7 +16,7 @@ jobs: type: string environment: MOZ_HEADLESS: 1 - WORKBENCH_DATABASES: '{"default": {"ENGINE": "django.db.backends.mysql", "NAME": "test_db", "USER": "user", "PASSWORD": "passw0rd", "HOST": "127.0.0.1"}}' + WORKBENCH_DATABASES: '{"default": {"ENGINE": "django.db.backends.mysql", "NAME": "db", "USER": "user", "PASSWORD": "passw0rd", "HOST": "127.0.0.1"}}' steps: - checkout - run: From db948c2ba4f9c7dc0b5d35f4802abef9ec770511 Mon Sep 17 00:00:00 2001 From: Josh McLaughlin Date: Thu, 9 Apr 2020 23:58:38 -0700 Subject: [PATCH 20/29] Update credentials for MySQL test database --- circle.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/circle.yml b/circle.yml index 355db5d9..f7a9ea0d 100644 --- a/circle.yml +++ b/circle.yml @@ -7,8 +7,6 @@ jobs: environment: MYSQL_ROOT_PASSWORD: rootpw MYSQL_DATABASE: test_db - MYSQL_USER: user - MYSQL_PASSWORD: passw0rd parameters: test_command: type: string @@ -16,7 +14,7 @@ jobs: type: string environment: MOZ_HEADLESS: 1 - WORKBENCH_DATABASES: '{"default": {"ENGINE": "django.db.backends.mysql", "NAME": "db", "USER": "user", "PASSWORD": "passw0rd", "HOST": "127.0.0.1"}}' + WORKBENCH_DATABASES: '{"default": {"ENGINE": "django.db.backends.mysql", "NAME": "db", "USER": "root", "PASSWORD": "rootpw", "HOST": "127.0.0.1"}}' steps: - checkout - run: From 534b81164444dbd140e94d9d911306934adf688b Mon Sep 17 00:00:00 2001 From: Josh McLaughlin Date: Fri, 10 Apr 2020 00:01:39 -0700 Subject: [PATCH 21/29] Remove auto-created database from test MySQL --- circle.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/circle.yml b/circle.yml index f7a9ea0d..58d33cb0 100644 --- a/circle.yml +++ b/circle.yml @@ -6,7 +6,6 @@ jobs: - image: circleci/mysql:5.6 environment: MYSQL_ROOT_PASSWORD: rootpw - MYSQL_DATABASE: test_db parameters: test_command: type: string From a55807caf5546e084b21ea7c1e7fe05a1aa6d1be Mon Sep 17 00:00:00 2001 From: Josh McLaughlin Date: Fri, 10 Apr 2020 00:18:43 -0700 Subject: [PATCH 22/29] Set charset to utf8mb4 for MySQL --- circle.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/circle.yml b/circle.yml index 58d33cb0..5ddf9165 100644 --- a/circle.yml +++ b/circle.yml @@ -13,7 +13,7 @@ jobs: type: string environment: MOZ_HEADLESS: 1 - WORKBENCH_DATABASES: '{"default": {"ENGINE": "django.db.backends.mysql", "NAME": "db", "USER": "root", "PASSWORD": "rootpw", "HOST": "127.0.0.1"}}' + WORKBENCH_DATABASES: '{"default": {"ENGINE": "django.db.backends.mysql", "NAME": "db", "USER": "root", "PASSWORD": "rootpw", "HOST": "127.0.0.1", "OPTIONS": {"charset": "utf8mb4"}}}' steps: - checkout - run: From 6c8bb82df4fc371919c239d0e228883ce46ca72c Mon Sep 17 00:00:00 2001 From: Guruprasad Lakshmi Narayanan Date: Fri, 10 Apr 2020 13:06:50 +0530 Subject: [PATCH 23/29] Try enabling large key prefixes --- circle.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/circle.yml b/circle.yml index 5ddf9165..6a5e6fa8 100644 --- a/circle.yml +++ b/circle.yml @@ -4,6 +4,7 @@ jobs: docker: - image: <> - image: circleci/mysql:5.6 + command: mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_bin --innodb-large-prefix=true --innodb-file-format=Barracuda environment: MYSQL_ROOT_PASSWORD: rootpw parameters: From 0a25f37cddd16f92a9aefb73baa7ac6c2b3c87cc Mon Sep 17 00:00:00 2001 From: Guruprasad Lakshmi Narayanan Date: Fri, 10 Apr 2020 13:24:49 +0530 Subject: [PATCH 24/29] Try additional MySQL flags --- circle.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/circle.yml b/circle.yml index 6a5e6fa8..7965d3cd 100644 --- a/circle.yml +++ b/circle.yml @@ -4,7 +4,7 @@ jobs: docker: - image: <> - image: circleci/mysql:5.6 - command: mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_bin --innodb-large-prefix=true --innodb-file-format=Barracuda + command: mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_bin --innodb-large-prefix=true --innodb-file-format=Barracuda --innodb-file-per-table=true innodb-default-row-format=dynamic environment: MYSQL_ROOT_PASSWORD: rootpw parameters: From 9e5e26fe7f423833a2cd1911e30f3340aa4ef3b2 Mon Sep 17 00:00:00 2001 From: Guruprasad Lakshmi Narayanan Date: Fri, 10 Apr 2020 13:35:58 +0530 Subject: [PATCH 25/29] Tweak mysqld flags --- circle.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/circle.yml b/circle.yml index 7965d3cd..1bb4410f 100644 --- a/circle.yml +++ b/circle.yml @@ -4,7 +4,7 @@ jobs: docker: - image: <> - image: circleci/mysql:5.6 - command: mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_bin --innodb-large-prefix=true --innodb-file-format=Barracuda --innodb-file-per-table=true innodb-default-row-format=dynamic + command: mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_bin --innodb-large-prefix=true --innodb-file-format=Barracuda --innodb-file-per-table=true environment: MYSQL_ROOT_PASSWORD: rootpw parameters: From 205c95ee57ca7ef5f8bc955704a47a8ffc7d330c Mon Sep 17 00:00:00 2001 From: Guruprasad Lakshmi Narayanan Date: Fri, 10 Apr 2020 14:05:59 +0530 Subject: [PATCH 26/29] Fix mysqld flags --- circle.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/circle.yml b/circle.yml index 1bb4410f..b7c88602 100644 --- a/circle.yml +++ b/circle.yml @@ -4,7 +4,7 @@ jobs: docker: - image: <> - image: circleci/mysql:5.6 - command: mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_bin --innodb-large-prefix=true --innodb-file-format=Barracuda --innodb-file-per-table=true + command: mysqld --character-set-server=latin1 --collation-server=latin1_swedish_ci environment: MYSQL_ROOT_PASSWORD: rootpw parameters: From 5669be5746e4339750f328b321613d2f15e72ddd Mon Sep 17 00:00:00 2001 From: Guruprasad Lakshmi Narayanan Date: Fri, 10 Apr 2020 21:12:07 +0530 Subject: [PATCH 27/29] Try adding a wait before asserting --- problem_builder/tests/integration/test_completion.py | 1 + 1 file changed, 1 insertion(+) diff --git a/problem_builder/tests/integration/test_completion.py b/problem_builder/tests/integration/test_completion.py index eb809a66..040e30f2 100644 --- a/problem_builder/tests/integration/test_completion.py +++ b/problem_builder/tests/integration/test_completion.py @@ -47,6 +47,7 @@ def completion_checkboxes(self): def expect_checkmarks_visible(self, first_visible, second_visible): first_checkmark, second_checkmark = self.checkmarks + time.sleep(3) self.assertEqual(first_checkmark.is_displayed(), first_visible) self.assertEqual(second_checkmark.is_displayed(), second_visible) From 7348b36dd11e1c23dcab82e1056ddc11ea83595f Mon Sep 17 00:00:00 2001 From: Guruprasad Lakshmi Narayanan Date: Fri, 10 Apr 2020 22:15:05 +0530 Subject: [PATCH 28/29] Update coverage and django-babel-underscore versions --- circle.yml | 2 +- requirements-dev.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/circle.yml b/circle.yml index b7c88602..b09601e4 100644 --- a/circle.yml +++ b/circle.yml @@ -73,7 +73,7 @@ jobs: sudo apt-get update virtualenv venv source venv/bin/activate - pip install 'coverage<5' + pip install 'coverage==5.0.3' - attach_workspace: at: /tmp/workspace - run: diff --git a/requirements-dev.txt b/requirements-dev.txt index 99251849..0a2e0966 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -6,4 +6,4 @@ transifex-client==0.12.1 edx-i18n-tools==0.5.0 pycodestyle==2.4.0 pylint==0.28.0 -django-babel-underscore==0.5.2 +-e git://github.com/edx/django-babel-underscore@37705f7377a4d0a4e673f1431895ce28a8860cd7#egg=xblock-sdk==0.6.0 From e8bd9a0b73309dd53d0473c6104b029f68928368 Mon Sep 17 00:00:00 2001 From: Guruprasad Lakshmi Narayanan Date: Fri, 10 Apr 2020 22:27:10 +0530 Subject: [PATCH 29/29] Fix typo --- requirements-dev.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-dev.txt b/requirements-dev.txt index 0a2e0966..7c741288 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -6,4 +6,4 @@ transifex-client==0.12.1 edx-i18n-tools==0.5.0 pycodestyle==2.4.0 pylint==0.28.0 --e git://github.com/edx/django-babel-underscore@37705f7377a4d0a4e673f1431895ce28a8860cd7#egg=xblock-sdk==0.6.0 +git+https://github.com/edx/django-babel-underscore.git@37705f7377a4d0a4e673f1431895ce28a8860cd7#egg=django-babel-underscore==0.6.0