From 1e8aac2c13030a9c9eaa4c52908d90f10d6d4c45 Mon Sep 17 00:00:00 2001 From: Giulio Gratta Date: Thu, 14 Jul 2016 12:55:39 -0700 Subject: [PATCH] Initial commit with cookie cutter content --- .gitignore | 2 + .travis.yml | 26 +++++++++ README.md | 2 +- invideoquiz/__init__.py | 1 + invideoquiz/invideoquiz.py | 71 ++++++++++++++++++++++++ invideoquiz/settings.py | 14 +++++ invideoquiz/static/README.txt | 19 +++++++ invideoquiz/static/css/invideoquiz.css | 9 +++ invideoquiz/static/html/invideoquiz.html | 5 ++ invideoquiz/static/js/src/invideoquiz.js | 22 ++++++++ invideoquiz/tests.py | 0 invideoquiz/translations/README.txt | 4 ++ manage.py | 12 ++++ pylintrc | 8 +++ setup.cfg | 6 ++ setup.py | 58 +++++++++++++++++++ tox.ini | 67 ++++++++++++++++++++++ 17 files changed, 325 insertions(+), 1 deletion(-) create mode 100644 .gitignore create mode 100644 .travis.yml create mode 100644 invideoquiz/__init__.py create mode 100644 invideoquiz/invideoquiz.py create mode 100644 invideoquiz/settings.py create mode 100644 invideoquiz/static/README.txt create mode 100644 invideoquiz/static/css/invideoquiz.css create mode 100644 invideoquiz/static/html/invideoquiz.html create mode 100644 invideoquiz/static/js/src/invideoquiz.js create mode 100644 invideoquiz/tests.py create mode 100644 invideoquiz/translations/README.txt create mode 100644 manage.py create mode 100644 pylintrc create mode 100644 setup.cfg create mode 100644 setup.py create mode 100644 tox.ini diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4386b15 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +.coverage +.tox/ \ No newline at end of file diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..596249b --- /dev/null +++ b/.travis.yml @@ -0,0 +1,26 @@ +sudo: false +language: python +cache: pip +python: + - '2.7' +before_install: + - 'uname -a' + - 'python --version' +install: + - 'pip install tox' + - 'virtualenv --version' + - 'easy_install --version' + - 'pip --version' + - 'tox --version' +script: + - 'tox -v' +branches: + only: + - 'master' +env: + - TOXENV=py27-dj14 + - TOXENV=py27-dj18 + - TOXENV=coveralls + - TOXENV=pep8 + - TOXENV=pyflakes + - TOXENV=pylint \ No newline at end of file diff --git a/README.md b/README.md index e04f22e..b23b9bf 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,2 @@ -New XBlock +In Video Quiz XBlock ==================== diff --git a/invideoquiz/__init__.py b/invideoquiz/__init__.py new file mode 100644 index 0000000..8ff71bf --- /dev/null +++ b/invideoquiz/__init__.py @@ -0,0 +1 @@ +from .invideoquiz import InVideoQuizXBlock diff --git a/invideoquiz/invideoquiz.py b/invideoquiz/invideoquiz.py new file mode 100644 index 0000000..7558616 --- /dev/null +++ b/invideoquiz/invideoquiz.py @@ -0,0 +1,71 @@ +"""TO-DO: Write a description of what this XBlock is.""" + +import pkg_resources + +from xblock.core import XBlock +from xblock.fields import Scope, Integer +from xblock.fragment import Fragment + + +class InVideoQuizXBlock(XBlock): + """ + TO-DO: document what your XBlock does. + """ + + # Fields are defined on the class. You can access them in your code as + # self.. + + # TO-DO: delete count, and define your own fields. + count = Integer( + default=0, scope=Scope.user_state, + help="A simple counter, to show something happening", + ) + + def resource_string(self, path): + """Handy helper for getting resources from our kit.""" + data = pkg_resources.resource_string(__name__, path) + return data.decode("utf8") + + # TO-DO: change this view to display your data your own way. + def student_view(self, context=None): + """ + The primary view of the InVideoQuizXBlock, shown to students + when viewing courses. + """ + html = self.resource_string("static/html/invideoquiz.html") + frag = Fragment(html.format(self=self)) + frag.add_css(self.resource_string("static/css/invideoquiz.css")) + frag.add_javascript(self.resource_string("static/js/src/invideoquiz.js")) + frag.initialize_js('InVideoQuizXBlock') + return frag + + # TO-DO: change this handler to perform your own actions. You may need + # more than one handler, or you may not need any handlers at all. + @XBlock.json_handler + def increment_count(self, data, suffix=''): + """ + An example handler, which increments the data. + """ + # Just to show data coming in... + assert data['hello'] == 'world' + + self.count += 1 + return {"count": self.count} + + # TO-DO: change this to create the scenarios you'd like to see in the + # workbench while developing your XBlock. + @staticmethod + def workbench_scenarios(): + """A canned scenario for display in the workbench.""" + return [ + ("InVideoQuizXBlock", + """ + """), + ("Multiple InVideoQuizXBlock", + """ + + + + + """), + ] diff --git a/invideoquiz/settings.py b/invideoquiz/settings.py new file mode 100644 index 0000000..297c772 --- /dev/null +++ b/invideoquiz/settings.py @@ -0,0 +1,14 @@ +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + # 'NAME': 'intentionally-omitted', + }, +} + +TEST_RUNNER = 'django_nose.NoseTestSuiteRunner' + +INSTALLED_APPS = ( + 'django_nose', +) + +SECRET_KEY = 'invideoquiz_SECRET_KEY' diff --git a/invideoquiz/static/README.txt b/invideoquiz/static/README.txt new file mode 100644 index 0000000..0472ef6 --- /dev/null +++ b/invideoquiz/static/README.txt @@ -0,0 +1,19 @@ +This static directory is for files that should be included in your kit as plain +static files. + +You can ask the runtime for a URL that will retrieve these files with: + + url = self.runtime.local_resource_url(self, "static/js/lib.js") + +The default implementation is very strict though, and will not serve files from +the static directory. It will serve files from a directory named "public". +Create a directory alongside this one named "public", and put files there. +Then you can get a url with code like this: + + url = self.runtime.local_resource_url(self, "public/js/lib.js") + +The sample code includes a function you can use to read the content of files +in the static directory, like this: + + frag.add_javascript(self.resource_string("static/js/my_block.js")) + diff --git a/invideoquiz/static/css/invideoquiz.css b/invideoquiz/static/css/invideoquiz.css new file mode 100644 index 0000000..452cc0b --- /dev/null +++ b/invideoquiz/static/css/invideoquiz.css @@ -0,0 +1,9 @@ +/* CSS for InVideoQuizXBlock */ + +.invideoquiz_block .count { + font-weight: bold; +} + +.invideoquiz_block p { + cursor: pointer; +} diff --git a/invideoquiz/static/html/invideoquiz.html b/invideoquiz/static/html/invideoquiz.html new file mode 100644 index 0000000..83233f5 --- /dev/null +++ b/invideoquiz/static/html/invideoquiz.html @@ -0,0 +1,5 @@ +
+

InVideoQuizXBlock: count is now + {self.count} (click me to increment). +

+
diff --git a/invideoquiz/static/js/src/invideoquiz.js b/invideoquiz/static/js/src/invideoquiz.js new file mode 100644 index 0000000..ee98665 --- /dev/null +++ b/invideoquiz/static/js/src/invideoquiz.js @@ -0,0 +1,22 @@ +/* Javascript for InVideoQuizXBlock. */ +function InVideoQuizXBlock(runtime, element) { + + function updateCount(result) { + $('.count', element).text(result.count); + } + + var handlerUrl = runtime.handlerUrl(element, 'increment_count'); + + $('p', element).click(function(eventObject) { + $.ajax({ + type: "POST", + url: handlerUrl, + data: JSON.stringify({"hello": "world"}), + success: updateCount + }); + }); + + $(function ($) { + /* Here's where you'd do things on page load. */ + }); +} diff --git a/invideoquiz/tests.py b/invideoquiz/tests.py new file mode 100644 index 0000000..e69de29 diff --git a/invideoquiz/translations/README.txt b/invideoquiz/translations/README.txt new file mode 100644 index 0000000..0493bcc --- /dev/null +++ b/invideoquiz/translations/README.txt @@ -0,0 +1,4 @@ +Use this translations directory to provide internationalized strings for your XBlock project. + +For more information on how to enable translations, visit the Open edX XBlock tutorial on Internationalization: +http://edx.readthedocs.org/projects/xblock-tutorial/en/latest/edx_platform/edx_lms.html diff --git a/manage.py b/manage.py new file mode 100644 index 0000000..392fbae --- /dev/null +++ b/manage.py @@ -0,0 +1,12 @@ +#!/usr/bin/env python +""" +Manage the djangoapp +""" +import os +import sys + +from django.core.management import execute_from_command_line + +if __name__ == '__main__': + os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'invideoquiz.settings') + execute_from_command_line(sys.argv) \ No newline at end of file diff --git a/pylintrc b/pylintrc new file mode 100644 index 0000000..dd00f80 --- /dev/null +++ b/pylintrc @@ -0,0 +1,8 @@ +[VARIABLES] +dummy-variables-rgx=_|dummy + +[REPORTS] +reports=no + +[MESSAGES CONTROL] +disable=locally-disabled \ No newline at end of file diff --git a/setup.cfg b/setup.cfg new file mode 100644 index 0000000..cdb9a4b --- /dev/null +++ b/setup.cfg @@ -0,0 +1,6 @@ +[metadata] +description-file = README.markdown + +[nosetests] +cover-package=invideoquiz +cover-tests=1 \ No newline at end of file diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..cf033f7 --- /dev/null +++ b/setup.py @@ -0,0 +1,58 @@ +"""Setup for invideoquiz XBlock.""" + +import os +from setuptools import setup +from setuptools.command.test import test as TestCommand + +def package_data(pkg, roots): + """Generic function to find package_data. + + All of the files under each of the `roots` will be declared as package + data for package `pkg`. + + """ + data = [] + for root in roots: + for dirname, _, files in os.walk(os.path.join(pkg, root)): + for fname in files: + data.append(os.path.relpath(os.path.join(dirname, fname), pkg)) + + return {pkg: data} + +class Tox(TestCommand): + user_options = [('tox-args=', 'a', "Arguments to pass to tox")] + def initialize_options(self): + TestCommand.initialize_options(self) + self.tox_args = None + def finalize_options(self): + TestCommand.finalize_options(self) + self.test_args = [] + self.test_suite = True + def run_tests(self): + # import here, cause outside the eggs aren't loaded + import tox + import shlex + args = self.tox_args + if args: + args = shlex.split(self.tox_args) + errno = tox.cmdline(args=args) + sys.exit(errno) + +setup( + name='invideoquiz-xblock', + version='0.1', + description='invideoquiz XBlock', # TODO: write a better description. + license='UNKNOWN', # TODO: choose a license: 'AGPL v3' and 'Apache 2.0' are popular. + packages=[ + 'invideoquiz', + ], + install_requires=[ + 'XBlock', + ], + entry_points={ + 'xblock.v1': [ + 'invideoquiz = invideoquiz:InVideoQuizXBlock', + ] + }, + package_data=package_data("invideoquiz", ["static", "public"]), +) diff --git a/tox.ini b/tox.ini new file mode 100644 index 0000000..e3ae3f1 --- /dev/null +++ b/tox.ini @@ -0,0 +1,67 @@ + +[tox] +downloadcache = {toxworkdir}/_download/ +envlist = py27-dj{14,18},coverage,pep8,pylint,pyflakes + +[testenv] +commands = {envpython} manage.py test + +[testenv:py27-dj14] +deps = + django == 1.4.22 + edx-opaque-keys + mock + django_nose>=1.4 + +[testenv:py27-dj18] +deps = + django >= 1.8, < 1.9 + edx-opaque-keys + mock + django_nose>=1.4 + +[testenv:pep8] +deps = pep8 +commands = {envbindir}/pep8 invideoquiz/ + +[testenv:pylint] +deps = pylint +commands = {envbindir}/pylint invideoquiz/ + +[testenv:pyflakes] +deps = pyflakes +commands = {envbindir}/pyflakes invideoquiz/ + +[testenv:coverage] +deps = + coverage + django == 1.4.22 + edx-opaque-keys + mock + django_nose>=1.4 + +setenv = + NOSE_COVER_TESTS=1 + NOSE_WITH_COVERAGE=1 + +commands = + {envpython} manage.py test + +[testenv:coveralls] +deps = + coverage + coveralls + django == 1.4.22 + edx-opaque-keys + mock + django_nose>=1.4 + +setenv = + NOSE_COVER_TESTS=1 + NOSE_WITH_COVERAGE=1 + +passenv = TRAVIS TRAVIS_JOB_ID TRAVIS_BRANCH + +commands = + {envbindir}/coverage run --source=invideoquiz manage.py test + {envbindir}/coveralls \ No newline at end of file