From 7218d93636df5013fe25ba634e0e32c19e922e53 Mon Sep 17 00:00:00 2001 From: Eric Fischer Date: Tue, 11 Jul 2017 16:39:01 -0400 Subject: [PATCH] Prepare for django 1.11 As of this commit, tests are running against django 1.11 and we're ready for the upgrade. --- .travis.yml | 1 + Makefile | 2 +- requirements/base.txt | 4 +-- setup.py | 2 +- workbench/runtime.py | 35 +++++++++++++----------- workbench/settings.py | 32 ++++++++++++++-------- workbench/templates/workbench/block.html | 2 +- workbench/templates/workbench/index.html | 2 +- workbench/test/test_filethumbs.py | 15 ++++++++-- workbench/test/test_thumbs.py | 11 ++++++-- workbench/test/test_views.py | 2 +- workbench/urls.py | 30 ++++++++++---------- 12 files changed, 85 insertions(+), 53 deletions(-) diff --git a/.travis.yml b/.travis.yml index 6a8ae3b5..3cd94f3b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -22,6 +22,7 @@ before_install: - "mkdir geckodriver" - "tar -xzf geckodriver-v0.15.0-linux64.tar.gz -C geckodriver" - "export PATH=$PATH:$PWD/geckodriver" + - "pip install -U pip" install: - "make install" diff --git a/Makefile b/Makefile index 5388cd4d..aaa96ce8 100755 --- a/Makefile +++ b/Makefile @@ -21,7 +21,7 @@ var: $(SQLITE_DB): var # The --noinput flag is for non-interactive runs, e.g. TravisCI. - python manage.py syncdb --noinput + python manage.py migrate --noinput .PHONY: test test: diff --git a/requirements/base.txt b/requirements/base.txt index 6a85db32..b82a8436 100644 --- a/requirements/base.txt +++ b/requirements/base.txt @@ -1,5 +1,5 @@ cookiecutter==0.9.0 -Django>=1.8,<1.9 +Django>=1.8,<2.0 lxml requests webob @@ -12,7 +12,7 @@ pypng # Strictly speaking, this is only for testing, but is in the INSTALLED_APPS, # and it's easier just to install it. -django_nose==1.4.1 +django_nose>=1.4.4 #install all sample xblocks -e . diff --git a/setup.py b/setup.py index 28ce41ad..fd029dc5 100644 --- a/setup.py +++ b/setup.py @@ -55,7 +55,7 @@ def load_requirements(*requirements_paths): setup( name='xblock-sdk', - version='0.1.2', + version='0.1.4', description='XBlock SDK', packages=[ 'sample_xblocks', diff --git a/workbench/runtime.py b/workbench/runtime.py index 3d0ec084..84c2677b 100644 --- a/workbench/runtime.py +++ b/workbench/runtime.py @@ -18,9 +18,7 @@ import django.utils.translation from django.core.urlresolvers import reverse from django.templatetags.static import static -from django.template import loader as django_template_loader, \ - Context as DjangoContext - +from django.template import loader as django_template_loader from xblock.runtime import ( KvsFieldData, KeyValueStore, Runtime, NoSuchViewError, IdReader, IdGenerator ) @@ -164,6 +162,7 @@ def get_block_type(self, def_id): raise NoSuchDefinition(repr(def_id)) def create_aside(self, definition_id, usage_id, aside_type): + """Create asides""" aside_def_id = u"{}.{}".format(definition_id, aside_type) aside_usage_id = u"{}.{}".format(usage_id, aside_type) self._aside_defs[aside_def_id] = (definition_id, aside_type) @@ -242,7 +241,7 @@ class WorkbenchRuntime(Runtime): """ - def __init__(self, user_id=None): + def __init__(self, user_id=None): # pylint: disable=super-on-old-class # TODO: Add params for user, runtime, etc. to service initialization # Move to stevedor services = { @@ -264,7 +263,8 @@ def __init__(self, user_id=None): self.id_generator = ID_MANAGER self.user_id = user_id - def render(self, block, view_name, context=None): + def render(self, block, view_name, context=None): # pylint: disable=super-on-old-class + """Renders using parent class render() method""" try: return super(WorkbenchRuntime, self).render(block, view_name, context) except NoSuchViewError: @@ -276,9 +276,9 @@ def render(self, block, view_name, context=None): def render_template(self, template_name, **kwargs): """Loads the django template for `template_name`""" template = django_template_loader.get_template(template_name) - return template.render(DjangoContext(kwargs)) + return template.render(kwargs) - def _wrap_ele(self, block, view, frag, extra_data=None): + def _wrap_ele(self, block, view, frag, extra_data=None): # pylint: disable=super-on-old-class """ Add javascript to the wrapped element """ @@ -297,6 +297,7 @@ def _wrap_ele(self, block, view, frag, extra_data=None): return wrapped def handler_url(self, block, handler_name, suffix='', query='', thirdparty=False): + """Helper to get the correct url for the given handler""" # Be sure this really is a handler. func = getattr(block, handler_name, None) if not func: @@ -325,23 +326,25 @@ def handler_url(self, block, handler_name, suffix='', query='', thirdparty=False return url def resource_url(self, resource): + """The url of the resource""" return static("workbench/" + resource) def local_resource_url(self, block, uri): + """The url of the local resource""" return reverse("package_resource", args=(block.scope_ids.block_type, uri)) def publish(self, block, event_type, event_data): + """Mocks a publish event by logging args""" log.info( - "XBlock event {event_type} for {block_type} (usage_id={usage_id}):" - .format( - event_type=event_type, - block_type=block.scope_ids.block_type, - usage_id=block.scope_ids.usage_id - ) + "XBlock event %s for %s (usage_id=%s):", + event_type, + block.scope_ids.block_type, + block.scope_ids.usage_id ) log.info(event_data) def query(self, block): + """Return a BlockSet query on block""" return _BlockSet(self, [block]) def _load_service(self, service_path): @@ -362,7 +365,7 @@ def _load_service(self, service_path): return service_instance except (ImportError, ValueError, AttributeError): log.info('Could not find service class defined at "%s"', service_path) - except: + except: # pylint: disable=bare-except log.exception('Could not initialize service defined at "%s"', service_path) @@ -458,7 +461,7 @@ class WorkBenchUserService(UserService): An implementation of xblock.reference.user_service.UserService """ - def __init__(self, uid): + def __init__(self, uid): # pylint: disable=super-on-old-class """ Initialize user """ @@ -474,7 +477,7 @@ def get_current_user(self): """ Returns user created by init """ - return self._user + return self._user # pylint: disable=no-member def reset_global_state(): diff --git a/workbench/settings.py b/workbench/settings.py index b4442473..1a59d516 100644 --- a/workbench/settings.py +++ b/workbench/settings.py @@ -11,8 +11,27 @@ DEBUG = True TEMPLATE_DEBUG = DEBUG -# The variable doesn't seem to actually get interpolated in -TEMPLATE_STRING_IF_INVALID = "" +TEMPLATES = [ + { + 'BACKEND': 'django.template.backends.django.DjangoTemplates', + 'DIRS': [ + os.path.join(BASE_DIR, 'workbench', 'templates'), + os.path.join(BASE_DIR, 'sample_xblocks' ,'basic', 'templates'), + ], + 'APP_DIRS': True, + 'OPTIONS': { + 'context_processors': [ + 'django.contrib.auth.context_processors.auth', + 'django.template.context_processors.debug', + 'django.template.context_processors.i18n', + 'django.template.context_processors.media', + 'django.template.context_processors.static', + 'django.template.context_processors.tz', + 'django.contrib.messages.context_processors.messages', + ], + }, + }, +] ADMINS = ( # ('Your Name', 'your_email@example.com'), @@ -97,13 +116,6 @@ # Make this unique, and don't share it with anybody. SECRET_KEY = '5ftdd9(@p)tg&bqv$(^d!63psz9+g+_i5om_e%!32%po2_+%l7' -# List of callables that know how to import templates from various sources. -TEMPLATE_LOADERS = ( - 'django.template.loaders.filesystem.Loader', - 'django.template.loaders.app_directories.Loader', - # 'django.template.loaders.eggs.Loader', -) - MIDDLEWARE_CLASSES = ( 'django.middleware.common.CommonMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', @@ -120,8 +132,6 @@ WSGI_APPLICATION = 'workbench.wsgi.application' TEMPLATE_DIRS = ( - os.path.join(BASE_DIR, 'workbench/templates'), - os.path.join(BASE_DIR, 'sample_xblocks/basic/templates'), ) INSTALLED_APPS = ( diff --git a/workbench/templates/workbench/block.html b/workbench/templates/workbench/block.html index 0406e0d3..1acddc4c 100644 --- a/workbench/templates/workbench/block.html +++ b/workbench/templates/workbench/block.html @@ -36,7 +36,7 @@

XBlock: {{scenario.description}}

>Scenario State
-
+
diff --git a/workbench/templates/workbench/index.html b/workbench/templates/workbench/index.html index e128d216..44602c69 100644 --- a/workbench/templates/workbench/index.html +++ b/workbench/templates/workbench/index.html @@ -19,7 +19,7 @@

XBlock scenarios

-
+
diff --git a/workbench/test/test_filethumbs.py b/workbench/test/test_filethumbs.py index d6052901..41cf0901 100644 --- a/workbench/test/test_filethumbs.py +++ b/workbench/test/test_filethumbs.py @@ -1,4 +1,5 @@ """Tests for the thumbs module""" +from bok_choy.promise import EmptyPromise from workbench import scenarios from workbench.test.selenium_test import SeleniumTest @@ -54,9 +55,19 @@ def test_three_thumbs_initial_state(self): down_count = thumb.find_element_by_css_selector(down_count_css) initial_up = int(up_count.text) initial_down = int(down_count.text) + + # upvote thumb.find_element_by_css_selector('span.upvote').click() - self.assertEqual(initial_up + 1, int(thumb.find_element_by_css_selector(up_count_css).text)) + _ = EmptyPromise( + lambda: int(thumb.find_element_by_css_selector(up_count_css).text) == initial_up +1, + "upvote action succeeded" + ).fulfill() self.assertEqual(initial_down, int(thumb.find_element_by_css_selector(down_count_css).text)) + + # downvote thumb.find_element_by_css_selector('span.downvote').click() + _ = EmptyPromise( + lambda: int(thumb.find_element_by_css_selector(down_count_css).text) == initial_down +1, + "downvote action succeeded" + ).fulfill() self.assertEqual(initial_up + 1, int(thumb.find_element_by_css_selector(up_count_css).text)) - self.assertEqual(initial_down + 1, int(thumb.find_element_by_css_selector(down_count_css).text)) diff --git a/workbench/test/test_thumbs.py b/workbench/test/test_thumbs.py index 0b3a055b..6dcc82d4 100644 --- a/workbench/test/test_thumbs.py +++ b/workbench/test/test_thumbs.py @@ -1,4 +1,5 @@ """Tests for the thumbs module""" +from bok_choy.promise import EmptyPromise from workbench import scenarios from workbench.test.selenium_test import SeleniumTest @@ -77,7 +78,10 @@ def test_three_upvoting(self): thumbs[0].find_element_by_css_selector('span.upvote').click() # Only the first thumb's upcount should increase - self.assertEqual('1', thumbs[0].find_element_by_css_selector(up_count_css).text) + _ = EmptyPromise( + lambda: int(thumbs[0].find_element_by_css_selector(up_count_css).text) == 1, + "upvote action succeeded" + ).fulfill() self.assertEqual('0', thumbs[1].find_element_by_css_selector(up_count_css).text) self.assertEqual('0', thumbs[2].find_element_by_css_selector(up_count_css).text) @@ -108,7 +112,10 @@ def test_three_downvoting(self): thumbs[0].find_element_by_css_selector('span.downvote').click() # Only the first thumb's downcount should increase - self.assertEqual('1', thumbs[0].find_element_by_css_selector(down_count_css).text) + _ = EmptyPromise( + lambda: int(thumbs[0].find_element_by_css_selector(down_count_css).text) == 1, + "downvote action succeeded" + ).fulfill() self.assertEqual('0', thumbs[1].find_element_by_css_selector(down_count_css).text) self.assertEqual('0', thumbs[2].find_element_by_css_selector(down_count_css).text) diff --git a/workbench/test/test_views.py b/workbench/test/test_views.py index ec9bb166..93094384 100644 --- a/workbench/test/test_views.py +++ b/workbench/test/test_views.py @@ -99,7 +99,7 @@ def test_xblock_with_handler(): # Initially, the data is the default. response = client.get("/view/testit/") - assert_true("The data: 'def'." in response.content) + assert_true("The data: u'def'." in response.content) parsed = response.content.split(':::') assert_equals(len(parsed), 3) handler_url = parsed[1] diff --git a/workbench/urls.py b/workbench/urls.py index b8e1c6a4..980c93a1 100644 --- a/workbench/urls.py +++ b/workbench/urls.py @@ -1,65 +1,65 @@ """Provide XBlock urls""" -from django.conf.urls import include, patterns, url +from django.conf.urls import include, url from django.contrib.staticfiles.urls import staticfiles_urlpatterns from django.contrib import admin +from workbench import views admin.autodiscover() -urlpatterns = patterns( - 'workbench.views', - url(r'^$', 'index', name='workbench_index'), +urlpatterns = [ + url(r'^$', views.index, name='workbench_index'), url( r'^scenario/(?P[^/]+)/(?P[^/]+)/$', - 'show_scenario', + views.show_scenario, name='scenario' ), url(r'^userlist/$', - 'user_list', + views.user_list, name='userlist'), url( r'^scenario/(?P[^/]+)/$', - 'show_scenario', + views.show_scenario, name='workbench_show_scenario' ), url( r'^view/(?P[^/]+)/(?P[^/]+)/$', - 'show_scenario', + views.show_scenario, {'template': 'workbench/blockview.html'} ), url( r'^view/(?P[^/]+)/$', - 'show_scenario', + views.show_scenario, {'template': 'workbench/blockview.html'} ), url( r'^handler/(?P[^/]+)/(?P[^/]*)(?:/(?P.*))?$', - 'handler', {'authenticated': True}, + views.handler, {'authenticated': True}, name='handler' ), url( r'^aside_handler/(?P[^/]+)/(?P[^/]*)(?:/(?P.*))?$', - 'aside_handler', {'authenticated': True}, + views.aside_handler, {'authenticated': True}, name='aside_handler' ), url( r'^unauth_handler/(?P[^/]+)/(?P[^/]*)(?:/(?P.*))?$', - 'handler', {'authenticated': False}, + views.handler, {'authenticated': False}, name='unauth_handler' ), url( r'^resource/(?P[^/]+)/(?P.*)$', - 'package_resource', + views.package_resource, name='package_resource' ), url( r'^reset_state$', - 'reset_state', + views.reset_state, name='reset_state' ), url(r'^admin/', include(admin.site.urls)), -) +] urlpatterns += staticfiles_urlpatterns()