GithubHelp home page GithubHelp logo

learningequality / kolibri Goto Github PK

View Code? Open in Web Editor NEW
744.0 42.0 627.0 123.42 MB

Kolibri Learning Platform: the offline app for universal education

Home Page: https://learningequality.org/kolibri/

License: MIT License

Makefile 0.09% Python 31.11% HTML 0.19% JavaScript 19.72% Vue 18.59% Shell 0.03% CSS 22.93% Dockerfile 0.03% Gherkin 7.21% SCSS 0.11%
education edtech offline-first oer

kolibri's Introduction

Kolibri

Python test status JS test status Developer docs Developer chat PyPI Demo User docs Discourse topics

This repository is for software developers wishing to contribute to Kolibri. If you are looking for help installing, configuring and using Kolibri, please refer to the User Guide.

What is Kolibri?

Kolibri Learning Platform: the offline-first platform for teaching and learning with technology without requiring the Internet.

Developed with and for the community by Learning Equality.

How can I use it?

Kolibri is available for download from our website.

How do I get help or give feedback?

You can ask questions, make suggestions, and report issues in the community forums.

If you have found a bug and are comfortable using Github and Markdown, you can create a Github issue following the instructions in the issue template.

How can I contribute?

  1. ๐Ÿ“™ Skim through the Developer documentation to understand where to refer later on.
  2. ๐Ÿ’ป Follow the Getting started to set up your development server. Some of the How To Guides may be handy too.
  3. ๐Ÿ” Search for issues tagged as help wanted or good first issue.
  4. ๐Ÿ—ฃ๏ธ Ask us for an assignment in the comments of an issue you've chosen. Please request assignment of a reasonable amount of issues at a time. Once you finish your current issue or two, you are welcome to ask for more.

โ“ Where to ask questions

  • For anything development related, refer to the Developer documentation at first. Some answers may already be there.
  • For questions related to a specific issue or assignment requests, use the corresponding issue's comments section.
  • Visit GitHub Discussions to ask about anything related to contributing or to troubleshoot development server issues.

๐Ÿ‘ฅ How to connect

  • We encourage you to visit GitHub Discussions to connect with the Learning Equality team as well as with other contributors.
  • If you'd like to contribute on a regular basis, we are happy to invite you to our open-source community Slack channel. Get in touch with us at [email protected] to receive an invitation.

๐Ÿ•– Please allow us a few days to reply to your comments. If you don't hear from us within a week, reach out via GitHub Discussions.

As soon as you open a pull request, it may take us a week or two to review it as we're a small team. We appreciate your contribution and will provide feedback.


Thank you for your interest in contributing! Learning Equality was founded by volunteers dedicated to helping make educational materials more accessible to those in need, and every contribution makes a difference.

kolibri's People

Contributors

66eli77 avatar akolson avatar alexvelezll avatar allanoxdi avatar aronasorman avatar benjaoming avatar bjester avatar christianmemije avatar dependabot[bot] avatar dxcanas avatar indirectlylit avatar jamalex avatar jonboiser avatar jredrejo avatar jtamiace avatar lianaharris360 avatar lyw07 avatar marcellamaki avatar mcgallaspy avatar misrob avatar mrpau-richard avatar nucleogenesis avatar pcenov avatar pyup-bot avatar radinamatic avatar ralphiee22 avatar rtibbles avatar sairina avatar vkweb avatar whitzhu avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

kolibri's Issues

Best way for a plugin to define new content?

Hi,

Kolibri looks exciting! In the future, I'm wondering how external contributors can create plugins to add new content. For a concrete example, let's say I want to bundle ipython notebooks and view them using nbviewer.

  1. How can I create my own channel, and upload the files necesary to view 1 content node?
  2. How can a plugin declare that it now handles the new content from that channel?
  3. How can I integrate with the download interface to have it retrieve the files necessary to view the content?

Thanks for the help!

Kolibri 'core' apps not namespaced under 'core'.

At the moment we have an inconsistent naming scheme with the core app PRs that are being proposed (#22, #25, #26, #28).

These apps have been put into the base 'kolibri' directory, rather than inside the 'core' directory. This seems misaligned to the then separate 'plugins' directory which should store 'non-core' apps.

@benjaoming, @MCGallaspy, @aronasorman, @jamalex, @66eli77 please input below - my main concern is to be idiomatic and clear in the way we structure our core vs non-core codebase.

Standard installer icon base

All installers must have the following icons as the base for their GUI launcher:

  1. Kolibri not started systray icon.
  2. Kolibri starting up systray icon.
  3. Kolibri started systray icon.
  4. Kolibri application menu icon.

Installers across different platforms may make derivations of this as their platform's standard practices dictate.

@jtamiace or @66eli77 would you or someone else be able to make these icons?

Here are the platforms we've indicated that we'll support (2/4/2016):

  • Android (version?)
  • OS X Yosemite
  • Windows XP, 7, 8, 10
  • Ubuntu 14.04 and above

Minimum browser support

I'd like to concretize the browsers we're willing to support for Kolibri to the following:

  • Internet Explorer 10+
  • Firefox 35+
  • Chrome 40+
  • Android browser 4.2+
  • iOS 6.0+
  • Safari 5+
  • Opera (latest ones use the same rendering engine as Chrome)

The versions given above are meant to be negotiated. But we need to commit to supporting certain versions soon as that will determine what external dependencies we'll be bundling in (see Kolibri Frontend Architecture doc).

To answer this realistically, we'll need to look at our most important partners and deployments, and see what technologies they're using. Here's a list of people we need to contact:

  • FUNSEPA
  • Nalanda
  • WCH
  • UNICEF
  • Aflatoun
  • World Bank (Premature to contact, according to Liz)
  • {{ add more here @jamalex and @jeepurs }}

`kolibri -h` is out-of-date

Running kolibri -h does not mention the --webpack and --karma flags.

It also says that everything following the -- are "passed on to the django manage command", but this isn't true for those flags.

Implement get_all_related as property of ContentMetadata Models

get_all_related is currently implemented as an API function, but it would seem to make sense to implement this method as a computed property of the models.

However, this also makes me think - are the API methods that deal with a single model better implemented as Model properties/methods?

kolibri command not working properly

"kolibri manage dumpdata content --exclude=contenttypes" won't work,
as well as "kolibri manage dumpdata -- content --exclude=contenttypes"
and "kolibri manage dumpdata -- --exclude=contenttypes content"

Feature Request - User Accessibility Settings

Feature Request - User Accessibility Settings - opening for Kolibri as original KA Lite issue is not going to happen within the scope of KA Lite.

Examples of possible options

  • High Contrast & Background (see the original issue for screenshots) @jtamiace @66eli77
    It would be awesome to have, but if the contrast is setup properly from the get go, can be an enhancement feature.
  • Show only videos with available subtitles (old issue, turns out it's a feature regression)
    Very useful for DHOH (deaf and hard on hearing) who must have subtitles.
  • Show videos in English with subtitles in user's target language
    See the original KA Lite issue for details. In KA Lite this is valid for DHOH users who would use non-English UI, but would be better served if they view the original video in English, with the translated subs in their own language. Implementation for other channels would depend on how the video content is transcribed & translated.
  • More to come...

Plugin system wishlist

I propose we iterate on the plugin system by creating successively more elaborate examples. Here are some motivating examples.

As I understand it we want a plugin system that does the following:

  • Allow plugins to insert their own javascript in existing pages, for instance to view content or add a new coach report type.
  • Allow plugins to define new views and urls.
  • Allow plugins to override base templates (for a custom look-and-feel).
  • Has good documentation with examples for all features.
  • Has documentation of core hooks.

Additionally I'm guessing we want the following features:

  • Plugin mixins to cut down on boilerplate. For example, we might have a NavItemPluginMixin that can be thrown in to painlessly add new nav menu items by simply implementing one function.
  • Easily allow an app to register multiple callbacks to a hook.
  • Allows users to define new hooks.

What do you all think?

Get rid of warning: 'DeviceOwner.username' is named as the 'USERNAME_FIELD', but it is not unique

Since even anticipated warnings are going to misguide devs to investigate them, we need to figure out a solution for this:

  • Should the username field be unique

or

  • Should we suppress the warning somewhere explicit?
โžœ  kolibri git:(deps-for-setup-py) python -m kolibri manage runserver -- 0.0.0.0:12345
Performing system checks...

System check identified some issues:

WARNINGS:
kolibriauth.DeviceOwner: (auth.W004) 'DeviceOwner.username' is named as the 'USERNAME_FIELD', but it is not unique.
    HINT: Ensure that your authentication backend(s) can handle non-unique usernames.

System check identified 1 issue (0 silenced).
May 20, 2016 - 15:50:24
Django version 1.9.1, using settings 'kolibri.deployment.default.settings.base'
Starting development server at http://0.0.0.0:12345/
Quit the server with CONTROL-C.

@jamalex which solution would you advice?

`django-mptt` dependency missing from Kolibri setup

Issue

In the setup instructions, pip install -e . is used to install Django and other dependencies. However running kolibri manage runserver on a fresh installations gives:

vagrant@kolibri ~> kolibri manage runserver
Unhandled exception in thread started by <function wrapper at 0x7fba4bb75938>
Traceback (most recent call last):
  File "/usr/local/lib/python2.7/dist-packages/django/utils/autoreload.py", line 226, in wrapper
    fn(*args, **kwargs)
  File "/usr/local/lib/python2.7/dist-packages/django/core/management/commands/runserver.py", line 109, in inner_run
    autoreload.raise_last_exception()
  File "/usr/local/lib/python2.7/dist-packages/django/utils/autoreload.py", line 249, in raise_last_exception
    six.reraise(*_exception)
  File "/usr/local/lib/python2.7/dist-packages/django/utils/autoreload.py", line 226, in wrapper
    fn(*args, **kwargs)
  File "/usr/local/lib/python2.7/dist-packages/django/__init__.py", line 18, in setup
    apps.populate(settings.INSTALLED_APPS)
  File "/usr/local/lib/python2.7/dist-packages/django/apps/registry.py", line 108, in populate
    app_config.import_models(all_models)
  File "/usr/local/lib/python2.7/dist-packages/django/apps/config.py", line 202, in import_models
    self.models_module = import_module(models_module_name)
  File "/usr/lib/python2.7/importlib/__init__.py", line 37, in import_module
    __import__(name)
  File "/kolibri/kolibri/auth/models.py", line 28, in <module>
    from mptt.models import MPTTModel, TreeForeignKey
ImportError: No module named mptt.models
^Cfish: Job 1, โ€œkolibri manage runserverโ€ terminated by signal SIGINT (Quit request from job control (^C))

Work-around

The correct dependencies can be installed using

pip install -r requirements.txt

Analysis

If we're using pip install -e . as the canonical way to install Kolibri's dependencies, all required packages should be included in the install_requires field in setup.py.

We should clarify how these differ from the dependencies listed the various requirements files, and potentially clean these up if there is redundancy.

tests fail on fresh install

Issue

Following the getting started instructions, I tried running the tests and saw the error below.

This is on a fresh Ubuntu 14.04 installation with Python 2.7.6, and dependencies installed via pip install -e .

vagrant@kolibri /kolibri> python setup.py test
running pytest
Searching for flake8
Reading https://pypi.python.org/simple/flake8/
Best match: flake8 2.5.4
Downloading https://pypi.python.org/packages/source/f/flake8/flake8-2.5.4.tar.gz#md5=a4585b3569b95c3f66acb8294a7f06ef
Processing flake8-2.5.4.tar.gz
Writing /tmp/easy_install-Akd7nR/flake8-2.5.4/setup.cfg
Running flake8-2.5.4/setup.py -q bdist_egg --dist-dir /tmp/easy_install-Akd7nR/flake8-2.5.4/egg-dist-tmp-PqVP6S
zip_safe flag not set; analyzing archive contents...
flake8.reporter: module references __file__
flake8.tests._test_warnings: module references __file__
flake8.tests.test_integration: module references __file__

Installed /kolibri/flake8-2.5.4-py2.7.egg
Searching for tox
Reading https://pypi.python.org/simple/tox/
Best match: tox 2.3.1
Downloading https://pypi.python.org/packages/source/t/tox/tox-2.3.1.tar.gz#md5=9371b3d3e25c03751a0372e19602dfb9
Processing tox-2.3.1.tar.gz
Writing /tmp/easy_install-_LJppS/tox-2.3.1/setup.cfg
Running tox-2.3.1/setup.py -q bdist_egg --dist-dir /tmp/easy_install-_LJppS/tox-2.3.1/egg-dist-tmp-tBoN9N
zip_safe flag not set; analyzing archive contents...
tox._pytestplugin: module references __file__
tox.session: module references __file__
tox.config: module references __file__
tox.interpreters: module MAY be using inspect.getsource

Installed /kolibri/tox-2.3.1-py2.7.egg
Searching for pytest
Reading https://pypi.python.org/simple/pytest/
Best match: pytest 2.9.1
Downloading https://pypi.python.org/packages/source/p/pytest/pytest-2.9.1.tar.gz#md5=05165740ea50928e4e971378630163ec
Processing pytest-2.9.1.tar.gz
Writing /tmp/easy_install-Vc9ufB/pytest-2.9.1/setup.cfg
Running pytest-2.9.1/setup.py -q bdist_egg --dist-dir /tmp/easy_install-Vc9ufB/pytest-2.9.1/egg-dist-tmp-kjigd5
warning: no previously-included files found matching '_pytest/impl'
warning: no previously-included files matching '*.pyc' found under directory '*'
warning: no previously-included files matching '*.pyo' found under directory '*'
warning: no previously-included files found matching 'appveyor/install.ps1'
warning: no previously-included files found matching 'appveyor.yml'
warning: no previously-included files found matching 'appveyor'
warning: no previously-included files found matching 'ISSUES.txt'
warning: no previously-included files found matching 'HOWTORELEASE.rst'

Installed /kolibri/pytest-2.9.1-py2.7.egg
Searching for mccabe>=0.2.1,<0.5
Reading https://pypi.python.org/simple/mccabe/
Best match: mccabe 0.4.0
Downloading https://pypi.python.org/packages/source/m/mccabe/mccabe-0.4.0.tar.gz#md5=8c425db05f310adcd4bb174b991f26f5
Processing mccabe-0.4.0.tar.gz
Writing /tmp/easy_install-a3vSDa/mccabe-0.4.0/setup.cfg
Running mccabe-0.4.0/setup.py -q bdist_egg --dist-dir /tmp/easy_install-a3vSDa/mccabe-0.4.0/egg-dist-tmp-BLgqG4

Installed /kolibri/mccabe-0.4.0-py2.7.egg
Searching for pep8>=1.5.7,!=1.6.0,!=1.6.1,!=1.6.2
Reading https://pypi.python.org/simple/pep8/
Best match: pep8 1.7.0
Downloading https://pypi.python.org/packages/source/p/pep8/pep8-1.7.0.tar.gz#md5=2b03109b0618afe3b04b3e63b334ac9d
Processing pep8-1.7.0.tar.gz
Writing /tmp/easy_install-AvZSUQ/pep8-1.7.0/setup.cfg
Running pep8-1.7.0/setup.py -q bdist_egg --dist-dir /tmp/easy_install-AvZSUQ/pep8-1.7.0/egg-dist-tmp-rlTC3A
warning: no previously-included files matching '*.pyc' found under directory 'docs'
warning: no previously-included files matching '*.pyo' found under directory 'docs'
warning: no previously-included files matching '*.pyc' found under directory 'testsuite'
warning: no previously-included files matching '*.pyo' found under directory 'testsuite'
no previously-included directories found matching 'docs/_build'

Installed /kolibri/pep8-1.7.0-py2.7.egg
Searching for pyflakes>=0.8.1,<1.1
Reading https://pypi.python.org/simple/pyflakes/
Best match: pyflakes 1.0.0
Downloading https://pypi.python.org/packages/source/p/pyflakes/pyflakes-1.0.0.tar.gz#md5=914621d4c9546248419b435dd358eb6a
Processing pyflakes-1.0.0.tar.gz
Writing /tmp/easy_install-WsAaLq/pyflakes-1.0.0/setup.cfg
Running pyflakes-1.0.0/setup.py -q bdist_egg --dist-dir /tmp/easy_install-WsAaLq/pyflakes-1.0.0/egg-dist-tmp-7wKIdb
zip_safe flag not set; analyzing archive contents...
pyflakes.checker: module references __file__
pyflakes.checker: module references __path__
pyflakes.test.test_api: module references __file__
pyflakes.test.test_undefined_names: module references __file__
pyflakes.test.test_undefined_names: module references __path__

Installed /kolibri/pyflakes-1.0.0-py2.7.egg
Searching for pluggy>=0.3.0,<0.4.0
Reading https://pypi.python.org/simple/pluggy/
Best match: pluggy 0.3.1
Downloading https://pypi.python.org/packages/source/p/pluggy/pluggy-0.3.1.tar.gz#md5=ecdd791e309f60668b66fec97c2ee7db
Processing pluggy-0.3.1.tar.gz
Writing /tmp/easy_install-pGfmIc/pluggy-0.3.1/setup.cfg
Running pluggy-0.3.1/setup.py -q bdist_egg --dist-dir /tmp/easy_install-pGfmIc/pluggy-0.3.1/egg-dist-tmp-5DksnS
warning: no files found matching 'test_pluggy.py'
zip_safe flag not set; analyzing archive contents...
pluggy: module MAY be using inspect.trace

Installed /kolibri/pluggy-0.3.1-py2.7.egg
Searching for py>=1.4.17
Reading https://pypi.python.org/simple/py/
Best match: py 1.4.31
Downloading https://pypi.python.org/packages/source/p/py/py-1.4.31.tar.gz#md5=5d2c63c56dc3f2115ec35c066ecd582b
Processing py-1.4.31.tar.gz
Writing /tmp/easy_install-LfAA0I/py-1.4.31/setup.cfg
Running py-1.4.31/setup.py -q bdist_egg --dist-dir /tmp/easy_install-LfAA0I/py-1.4.31/egg-dist-tmp-7a6X7I

Installed /kolibri/py-1.4.31-py2.7.egg
Searching for virtualenv>=1.11.2
Reading https://pypi.python.org/simple/virtualenv/
Best match: virtualenv 15.0.1
Downloading https://pypi.python.org/packages/source/v/virtualenv/virtualenv-15.0.1.tar.gz#md5=28d76a0d9cbd5dc42046dd14e76a6ecc
Processing virtualenv-15.0.1.tar.gz
Writing /tmp/easy_install-95PsDv/virtualenv-15.0.1/setup.cfg
Running virtualenv-15.0.1/setup.py -q bdist_egg --dist-dir /tmp/easy_install-95PsDv/virtualenv-15.0.1/egg-dist-tmp-lrFrQR
warning: no previously-included files matching '*' found under directory 'docs/_templates'
warning: no previously-included files matching '*' found under directory 'docs/_build'

Installed /kolibri/virtualenv-15.0.1-py2.7.egg
running egg_info
writing requirements to kolibri.egg-info/requires.txt
writing kolibri.egg-info/PKG-INFO
writing top-level names to kolibri.egg-info/top_level.txt
writing dependency_links to kolibri.egg-info/dependency_links.txt
writing entry points to kolibri.egg-info/entry_points.txt
reading manifest file 'kolibri.egg-info/SOURCES.txt'
reading manifest template 'MANIFEST.in'
writing manifest file 'kolibri.egg-info/SOURCES.txt'
running build_ext
========================================== test session starts ==========================================
platform linux2 -- Python 2.7.6, pytest-2.9.1, py-1.4.31, pluggy-0.3.1
rootdir: /kolibri, inifile: pytest.ini
collected 5 items / 5 errors 

test/test_cli.py ..
kolibri/plugins/test/test_base_plugins.py ..
kolibri/test/test_basic.py .

================================================ ERRORS =================================================
__________________________ ERROR collecting kolibri/auth/test/test_backend.py ___________________________
kolibri/auth/test/test_backend.py:5: in <module>
    from kolibri.auth.models import FacilityUser, DeviceOwner, Facility
kolibri/auth/models.py:21: in <module>
    from django.contrib.auth.models import AbstractBaseUser
/usr/local/lib/python2.7/dist-packages/django/contrib/auth/models.py:4: in <module>
    from django.contrib.auth.base_user import AbstractBaseUser, BaseUserManager
/usr/local/lib/python2.7/dist-packages/django/contrib/auth/base_user.py:49: in <module>
    class AbstractBaseUser(models.Model):
/usr/local/lib/python2.7/dist-packages/django/db/models/base.py:94: in __new__
    app_config = apps.get_containing_app_config(module)
/usr/local/lib/python2.7/dist-packages/django/apps/registry.py:239: in get_containing_app_config
    self.check_apps_ready()
/usr/local/lib/python2.7/dist-packages/django/apps/registry.py:124: in check_apps_ready
    raise AppRegistryNotReady("Apps aren't loaded yet.")
E   AppRegistryNotReady: Apps aren't loaded yet.
___________________ ERROR collecting kolibri/auth/test/test_collections_and_roles.py ____________________
kolibri/auth/test/test_collections_and_roles.py:7: in <module>
    from kolibri.auth.models import FacilityUser, Facility, Classroom, LearnerGroup, Role, Collection, DeviceOwner, FacilityDataset
kolibri/auth/models.py:21: in <module>
    from django.contrib.auth.models import AbstractBaseUser
/usr/local/lib/python2.7/dist-packages/django/contrib/auth/models.py:4: in <module>
    from django.contrib.auth.base_user import AbstractBaseUser, BaseUserManager
/usr/local/lib/python2.7/dist-packages/django/contrib/auth/base_user.py:49: in <module>
    class AbstractBaseUser(models.Model):
/usr/local/lib/python2.7/dist-packages/django/db/models/base.py:94: in __new__
    app_config = apps.get_containing_app_config(module)
/usr/local/lib/python2.7/dist-packages/django/apps/registry.py:239: in get_containing_app_config
    self.check_apps_ready()
/usr/local/lib/python2.7/dist-packages/django/apps/registry.py:124: in check_apps_ready
    raise AppRegistryNotReady("Apps aren't loaded yet.")
E   AppRegistryNotReady: Apps aren't loaded yet.
___________________________ ERROR collecting kolibri/auth/test/test_users.py ____________________________
kolibri/auth/test/test_users.py:6: in <module>
    from kolibri.auth.models import DeviceOwner, Facility, FacilityUser  # , KolibriValidationError
kolibri/auth/models.py:21: in <module>
    from django.contrib.auth.models import AbstractBaseUser
/usr/local/lib/python2.7/dist-packages/django/contrib/auth/models.py:4: in <module>
    from django.contrib.auth.base_user import AbstractBaseUser, BaseUserManager
/usr/local/lib/python2.7/dist-packages/django/contrib/auth/base_user.py:49: in <module>
    class AbstractBaseUser(models.Model):
/usr/local/lib/python2.7/dist-packages/django/db/models/base.py:94: in __new__
    app_config = apps.get_containing_app_config(module)
/usr/local/lib/python2.7/dist-packages/django/apps/registry.py:239: in get_containing_app_config
    self.check_apps_ready()
/usr/local/lib/python2.7/dist-packages/django/apps/registry.py:124: in check_apps_ready
    raise AppRegistryNotReady("Apps aren't loaded yet.")
E   AppRegistryNotReady: Apps aren't loaded yet.
_______________________ ERROR collecting kolibri/content/test/test_content_app.py _______________________
kolibri/content/test/test_content_app.py:10: in <module>
    from kolibri.content import models as content
kolibri/content/models.py:19: in <module>
    from mptt.models import MPTTModel, TreeForeignKey
/usr/local/lib/python2.7/dist-packages/mptt/models.py:379: in <module>
    class MPTTModel(six.with_metaclass(MPTTModelBase, models.Model)):
/usr/local/lib/python2.7/dist-packages/django/utils/six.py:808: in __new__
    return meta(name, bases, d)
/usr/local/lib/python2.7/dist-packages/mptt/models.py:262: in __new__
    cls = super_new(meta, class_name, bases, class_dict)
/usr/local/lib/python2.7/dist-packages/django/db/models/base.py:94: in __new__
    app_config = apps.get_containing_app_config(module)
/usr/local/lib/python2.7/dist-packages/django/apps/registry.py:239: in get_containing_app_config
    self.check_apps_ready()
/usr/local/lib/python2.7/dist-packages/django/apps/registry.py:124: in check_apps_ready
    raise AppRegistryNotReady("Apps aren't loaded yet.")
E   AppRegistryNotReady: Apps aren't loaded yet.
_______________________ ERROR collecting kolibri/utils/test/test_webpack_utils.py _______________________
kolibri/utils/test/test_webpack_utils.py:11: in <module>
    from mock import patch
E   ImportError: No module named mock
=================================== 5 passed, 5 error in 3.89 seconds ===================================
Error in atexit._run_exitfuncs:
Traceback (most recent call last):
  File "/usr/lib/python2.7/atexit.py", line 24, in _run_exitfuncs
    func(*targs, **kargs)
  File "/usr/lib/python2.7/dist-packages/colorama/initialise.py", line 17, in reset_all
    AnsiToWin32(orig_stdout).reset_all()
TypeError: 'NoneType' object is not callable
Error in sys.exitfunc:
Traceback (most recent call last):
  File "/usr/lib/python2.7/atexit.py", line 24, in _run_exitfuncs
    func(*targs, **kargs)
  File "/usr/lib/python2.7/dist-packages/colorama/initialise.py", line 17, in reset_all
    AnsiToWin32(orig_stdout).reset_all()
TypeError: 'NoneType' object is not callable

Indicate size of the content channel prior to retrieving on network

In Belgrade atm, trying to run bellow commands for the latest Kolibri installer (build 24):

kolibri manage importchannel -- 7db80873586841e4a1c249b2bb8ba62d
kolibri manage retrievecontent -- network 7db80873586841e4a1c249b2bb8ba62d

The second command run for more than 45 minutes and then VM restarted, so I'm not sure if it finished correctly, or run of the space in the VM hd maybe...

Could we add a confirmation dialog for the user indicating the size? Something along these lines:

Size of this content channel is 1.5Gb, are you sure you want to install it now? Y/n

@jamalex @aronasorman

Error reading /UserPath/kolibri/kolibri/core/kolibri_core_stats.json.

Branch: Master

Current behavior: when running kolibri manage run server and access the port :8000 will spawn an error Error reading /Users/user/kolibri/kolibri/core/kolibri_core_stats.json. Are you sure webpack has generated the file and the path is correct?

Steps to reproduce

  1. Follow the instructions to run kolibri at https://github.com/learningequality/kolibri#running-kolibri
  2. After running the command kolibri manage runserver and access the port :8000 will spawn the error.

Here's the sample screenshot

screen shot 2016-04-12 at 1 33 37 pm

Related content is not unidirectional, but rather bidirectional.

The issue is that we can't enforce the relationship to be symmetric in Django - so we are probably better off allowing these to be set, and proxying the 'related' property to be a unique combination of the related, and reverse_related properties for that object.

Current behaviour: We disallow these symmetric relationships.

Desired behaviour: Allow such symmetric relationships, and collapse the 'related' lookups and 'reverse_related' in a computed property that gives a unique queryset of all related content - regardless of whether it is in related or reverse_related.

ImportError: No module named 'kolibri.tasks'

Summary

The kolibri.tasks module was not found during creating the sdist source distribution.

System information

  • Version: master

Traceback or relevant snippet from server.log

(kolibritest) echo-air:dist arceduardvincent$ kolibri start
Traceback (most recent call last):
  File "/Users/arceduardvincent/.virtualenvs/kolibritest/bin/kolibri", line 11, in <module>
    sys.exit(main())
  File "/Users/arceduardvincent/.virtualenvs/kolibritest/lib/python3.5/site-packages/kolibri/utils/cli.py", line 232, in main
    django.setup()
  File "/Users/arceduardvincent/.virtualenvs/kolibritest/lib/python3.5/site-packages/kolibri/dist/django/__init__.py", line 18, in setup
    apps.populate(settings.INSTALLED_APPS)
  File "/Users/arceduardvincent/.virtualenvs/kolibritest/lib/python3.5/site-packages/kolibri/dist/django/apps/registry.py", line 85, in populate
    app_config = AppConfig.create(entry)
  File "/Users/arceduardvincent/.virtualenvs/kolibritest/lib/python3.5/site-packages/kolibri/dist/django/apps/config.py", line 116, in create
    mod = import_module(mod_path)
  File "/Users/arceduardvincent/.virtualenvs/kolibritest/lib/python3.5/importlib/__init__.py", line 126, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 986, in _gcd_import
  File "<frozen importlib._bootstrap>", line 969, in _find_and_load
  File "<frozen importlib._bootstrap>", line 944, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 222, in _call_with_frames_removed
  File "<frozen importlib._bootstrap>", line 986, in _gcd_import
  File "<frozen importlib._bootstrap>", line 969, in _find_and_load
  File "<frozen importlib._bootstrap>", line 956, in _find_and_load_unlocked
ImportError: No module named 'kolibri.tasks'
(kolibritest) echo-air:dist arceduardvincent$

How to reproduce

  1. Used virtualenv then navigate to ~/kolibri.
  2. Run python setup.py sdist --static --format=zip. When it is finished navigate to ~/kolibri/dist.
  3. Install the zip file via pip.
  4. Run kolibri start. Notice that the local server fails to start.

Kolibri Module routing & plugin conventions

Based on discussion we decided:

  • Django should inject both the portion of the url it captured for routing and the remaining portion which should be routed by the js app.
  • We will remove the urls module from plugins -- plugins should only define one url, and we can entirely construct it from the existing plugin attributes for urls.

plugins cannot be disabled when they don't exist

steps to reproduce:

  1. create a new plugin (e.g. hello)
  2. enable it: kolibri plugin kolibri.plugins.hello enable
  3. delete the plugin. Now running kolibri throws an error: ImportError: No module named hello
  4. try to disable the plugin: kolibri plugin kolibri.plugins.hello disable - thows an error: kolibri.utils.cli.PluginDoesNotExist: Plugin does not exist

At this point, ~/.kolibri/kolibri_settings.json must be manually edited to remove the offending plugin

I'm not sure what the correct behavior is, but we probably don't want people to need to edit the settings file directly. Also, we may be able to log warnings with helpful information rather than raising exceptions.

Support browser zooming up to 200%

One a11y check I tota11y forgot about until now is the zooming of the page in browser... ๐Ÿ˜ž
WCAG recs state that the success criterion is satisfied when user is able to zoom in up to 200% and still retain proper access to all the elements in the page. Here is what we stand if I test the Kolibri content zoomed to 200% on the most prevalent laptop monitor size today (1366x768px):

Device Admin cannot reach the user/log out menu item
kolibri - chromium_638

Add New Account modal
kolibri - mozilla firefox_636

Edit User Account modal
kolibri - mozilla firefox_637

User content (document) Learn page - title remains cut out (invisible)
kolibri - chromium_640

Maybe another reason to reconsider the placement of the H1? @indirectlylit @whitzhu @66eli77

Plugins dependencies and build configuration have to be present in the top level configuration files

At the moment, our plugins pollute the global configuration for their npm dependencies and specific webpack configuration needs.

This is unnecessary as each one is built separately, so they do not have to share anything but the base configuration.

Solution: Each plugin can (optionally) have its own package.json, and its own webpack config.

We can use https://www.npmjs.com/package/recursive-install to recursively install dependencies inside each plugin, and inject the individual webpack configurations into the overall configuration for that bundle at build time.

IOError on server start

Hi all, problem with build on OSX 10.11.3. Any help much appreciated.

Terminal output:

(kol)  ~/Code/kolibri$ kolibri manage runserver
Performing system checks...

System check identified some issues:

WARNINGS:
?: (urls.W001) Your URL pattern '^$' uses include with a regex ending with a '$'. Remove the dollar from the regex to avoid problems including URLs.
kolibriauth.DeviceOwner: (auth.W004) 'DeviceOwner.username' is named as the 'USERNAME_FIELD', but it is not unique.
    HINT: Ensure that your authentication backend(s) can handle non-unique usernames.

System check identified 2 issues (0 silenced).

You have unapplied migrations; your app may not work properly until they are applied.
Run 'python manage.py migrate' to apply them.

May 09, 2016 - 14:27:31
Django version 1.9.1, using settings 'kolibri.deployment.default.settings.base'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
[09/May/2016 14:31:50] "GET / HTTP/1.1" 500 150769
[09/May/2016 14:31:50] "GET /favicon.ico HTTP/1.1" 404 8184

Browser output:

IOError at /
Error reading /Users/kevinsmith/Code/kolibri/kolibri/core/build/KolibriCoreFrontEnd_stats.json. Are you sure webpack has generated the file and the path is correct?
Request Method: GET
Request URL:    http://127.0.0.1:8000/
Django Version: 1.9.1
Exception Type: IOError
Exception Value:    
Error reading /Users/kevinsmith/Code/kolibri/kolibri/core/build/KolibriCoreFrontEnd_stats.json. Are you sure webpack has generated the file and the path is correct?
Exception Location: kolibri/utils/webpack.py in initialize_plugin_cache, line 69
Python Executable:  /Users/kevinsmith/Code/kolibri/kol/bin/python
Python Version: 2.7.8
Python Path:    
['',
 '/Users/kevinsmith/Code/kolibri',
 '/Users/kevinsmith/Code/kolibri/kol/lib/python27.zip',
 '/Users/kevinsmith/Code/kolibri/kol/lib/python2.7',
 '/Users/kevinsmith/Code/kolibri/kol/lib/python2.7/plat-darwin',
 '/Users/kevinsmith/Code/kolibri/kol/lib/python2.7/plat-mac',
 '/Users/kevinsmith/Code/kolibri/kol/lib/python2.7/plat-mac/lib-scriptpackages',
 '/Users/kevinsmith/Code/kolibri/kol/lib/python2.7/lib-tk',
 '/Users/kevinsmith/Code/kolibri/kol/lib/python2.7/lib-old',
 '/Users/kevinsmith/Code/kolibri/kol/lib/python2.7/lib-dynload',
 '/usr/local/Cellar/python/2.7.8_2/Frameworks/Python.framework/Versions/2.7/lib/python2.7',
 '/usr/local/Cellar/python/2.7.8_2/Frameworks/Python.framework/Versions/2.7/lib/python2.7/plat-darwin',
 '/usr/local/Cellar/python/2.7.8_2/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-tk',
 '/usr/local/Cellar/python/2.7.8_2/Frameworks/Python.framework/Versions/2.7/lib/python2.7/plat-mac',
 '/usr/local/Cellar/python/2.7.8_2/Frameworks/Python.framework/Versions/2.7/lib/python2.7/plat-mac/lib-scriptpackages',
 '/Users/kevinsmith/Code/kolibri/kol/lib/python2.7/site-packages']
Server time:    Mon, 9 May 2016 14:31:49 +0000
Error during template rendering

In template /Users/kevinsmith/Code/kolibri/kolibri/core/templates/kolibri/index.html, error at line 0
Error reading /Users/kevinsmith/Code/kolibri/kolibri/core/build/KolibriCoreFrontEnd_stats.json. Are you sure webpack has generated the file and the path is correct?
1   {% extends "kolibri/todo.html" %}
2   
Traceback Switch to copy-and-paste view

/Users/kevinsmith/Code/kolibri/kol/lib/python2.7/site-packages/django/core/handlers/base.py in get_response
                    response = self.process_exception_by_middleware(e, request) ...
โ–ถ Local vars
/Users/kevinsmith/Code/kolibri/kol/lib/python2.7/site-packages/django/core/handlers/base.py in get_response
                    response = response.render() ...
โ–ถ Local vars
/Users/kevinsmith/Code/kolibri/kol/lib/python2.7/site-packages/django/template/response.py in render
            self.content = self.rendered_content ...
โ–ถ Local vars
/Users/kevinsmith/Code/kolibri/kol/lib/python2.7/site-packages/django/template/response.py in rendered_content
        content = template.render(context, self._request) ...
โ–ถ Local vars
/Users/kevinsmith/Code/kolibri/kol/lib/python2.7/site-packages/django/template/backends/django.py in render
            return self.template.render(context) ...
โ–ถ Local vars
/Users/kevinsmith/Code/kolibri/kol/lib/python2.7/site-packages/django/template/base.py in render
                    return self._render(context) ...
โ–ถ Local vars
/Users/kevinsmith/Code/kolibri/kol/lib/python2.7/site-packages/django/template/base.py in _render
        return self.nodelist.render(context) ...
โ–ถ Local vars
/Users/kevinsmith/Code/kolibri/kol/lib/python2.7/site-packages/django/template/base.py in render
                bit = node.render_annotated(context) ...
โ–ถ Local vars
/Users/kevinsmith/Code/kolibri/kol/lib/python2.7/site-packages/django/template/base.py in render_annotated
            return self.render(context) ...
โ–ถ Local vars
/Users/kevinsmith/Code/kolibri/kol/lib/python2.7/site-packages/django/template/loader_tags.py in render
        return compiled_parent._render(context) ...
โ–ถ Local vars
/Users/kevinsmith/Code/kolibri/kol/lib/python2.7/site-packages/django/template/base.py in _render
        return self.nodelist.render(context) ...
โ–ถ Local vars
/Users/kevinsmith/Code/kolibri/kol/lib/python2.7/site-packages/django/template/base.py in render
                bit = node.render_annotated(context) ...
โ–ถ Local vars
/Users/kevinsmith/Code/kolibri/kol/lib/python2.7/site-packages/django/template/base.py in render_annotated
            return self.render(context) ...
โ–ถ Local vars
/Users/kevinsmith/Code/kolibri/kol/lib/python2.7/site-packages/django/template/loader_tags.py in render
        return compiled_parent._render(context) ...
โ–ถ Local vars
/Users/kevinsmith/Code/kolibri/kol/lib/python2.7/site-packages/django/template/base.py in _render
        return self.nodelist.render(context) ...
โ–ถ Local vars
/Users/kevinsmith/Code/kolibri/kol/lib/python2.7/site-packages/django/template/base.py in render
                bit = node.render_annotated(context) ...
โ–ถ Local vars
/Users/kevinsmith/Code/kolibri/kol/lib/python2.7/site-packages/django/template/base.py in render_annotated
            return self.render(context) ...
โ–ถ Local vars
/Users/kevinsmith/Code/kolibri/kol/lib/python2.7/site-packages/django/template/library.py in render
        output = self.func(*resolved_args, **resolved_kwargs) ...
โ–ถ Local vars
kolibri/core/templatetags/kolibri_tags.py in frontend_assets
    return render_as_tags(get_webpack_bundle(bundle_path, extension)) ...
โ–ถ Local vars
kolibri/core/templatetags/kolibri_tags.py in render_as_tags
    for chunk in bundle: ...
โ–ถ Local vars
kolibri/utils/webpack.py in get_bundle
    check_plugin_cache() ...
โ–ถ Local vars
kolibri/utils/webpack.py in check_plugin_cache
        initialize_plugin_cache() ...
kolibri/utils/webpack.py in initialize_plugin_cache
                'and the path is correct?'.format(stats_file)) ...
โ–ถ Local vars
Request information

GET
No GET data
POST
No POST data
FILES
No FILES data
COOKIES
Variable    Value
csrftoken   
'7pQjPFgKpiwTFjROsTV4mf6jK8w82ijU'
META
Variable    Value
RUN_MAIN    
'true'
KOLIBRI_HOME    
'/Users/kevinsmith/.kolibri'
HTTP_ACCEPT_LANGUAGE    
'en-US,en;q=0.8'
SERVER_PROTOCOL 
'HTTP/1.1'
SERVER_SOFTWARE 
'WSGIServer/0.1 Python/2.7.8'
TERM_PROGRAM_VERSION    
'361.1'
REQUEST_METHOD  
'GET'
LOGNAME 
'kevinsmith'
USER    
'kevinsmith'
HOME    
'/Users/kevinsmith'
QUERY_STRING    
''
PATH    
'/Users/kevinsmith/Code/kolibri/kol/bin:/opt/local/bin:/opt/local/sbin:/opt/local/bin:/opt/local/sbin:/usr/local/bin:/opt/local/bin:/opt/local/sbin:/opt/local/bin:/opt/local/sbin:/opt/local/bin:/opt/local/sbin:/opt/local/bin:/opt/local/sbin:/usr/local/bin:/opt/local/bin:/opt/local/sbin:/sw/bin:/sw/sbin:/opt/local/bin:/opt/local/sbin:/opt/local/bin:/opt/local/sbin:/opt/local/bin:/opt/local/sbin:/opt/local/bin:/opt/local/sbin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/X11/bin:/usr/local/git/bin:/usr/local/MacGPG2/bin:/Users/kevinsmith/depot_tools:/Users/kevinsmith/depot_tools:/Users/kevinsmith/depot_tools:/Users/kevinsmith/depot_tools'
VIRTUALENVWRAPPER_SCRIPT    
'/usr/local/bin/virtualenvwrapper.sh'
DISPLAY 
'/private/tmp/com.apple.launchd.XXAJv1vzKO/org.macosforge.xquartz:0'
KOLIBRI_LISTEN_PORT 
'8008'
LANG    
'en_GB.UTF-8'
INFOPATH    
'/sw/share/info:/sw/info:/usr/share/info'
TERM    
'xterm-256color'
SHELL   
'/bin/bash'
KALITE_PYTHON   
'/Applications/KA-Lite/support/pyrun-2.7/bin/pyrun'
HTTP_COOKIE 
'csrftoken=7pQjPFgKpiwTFjROsTV4mf6jK8w82ijU'
SERVER_NAME 
'1.0.0.127.in-addr.arpa'
REMOTE_ADDR 
'127.0.0.1'
SHLVL   
'1'
XPC_FLAGS   
'0x0'
wsgi.url_scheme 
'http'
_   
'/Users/kevinsmith/Code/kolibri/kol/bin/kolibri'
MANPATH 
'/sw/share/man:/opt/local/man:/opt/local/man:/opt/local/man::/sw/lib/perl5/5.18.2/man'
CONTENT_LENGTH  
''
TERM_PROGRAM    
'Apple_Terminal'
KALITE_HOME 
'/Users/kevinsmith/.kalite'
WORKON_HOME 
'/Users/kevinsmith/.virtualenvs'
TERM_SESSION_ID 
'187E857F-38F9-4DC6-90A6-8B9E0064D4FF'
XPC_SERVICE_NAME    
'0'
VERSIONER_PERL_PREFER_32_BIT    
'yes'
SERVER_PORT 
'8000'
PERL5LIB    
'/sw/lib/perl5:/sw/lib/perl5/darwin'
SSH_AUTH_SOCK   
'/private/tmp/com.apple.launchd.bzavLSrx2g/Listeners'
VIRTUAL_ENV 
'/Users/kevinsmith/Code/kolibri/kol'
HTTP_CONNECTION 
'keep-alive'
wsgi.input  
<socket._fileobject object at 0x1109df350>
Apple_PubSub_Socket_Render  
'/private/tmp/com.apple.launchd.hJpSZojaHt/Render'
PS1 
'(kol) \\[\\033[1m\\033[32m\\] \\w\\[\\033[0m\\]\\$ '
SCRIPT_NAME 
u''
wsgi.multithread    
True
TZ  
u'UTC'
TMPDIR  
'/var/folders/8c/h2bdmcvx1k1gnghk1jnt3tv80000gn/T/'
HTTP_ACCEPT 
'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8'
VIRTUALENVWRAPPER_PROJECT_FILENAME  
'.project'
wsgi.file_wrapper   
''
wsgi.version    
(1, 0)
VIRTUALENVWRAPPER_HOOK_DIR  
'/Users/kevinsmith/.virtualenvs'
GATEWAY_INTERFACE   
'CGI/1.1'
wsgi.run_once   
False
CSRF_COOKIE 
u'7pQjPFgKpiwTFjROsTV4mf6jK8w82ijU'
OLDPWD  
'/usr/local/bin'
wsgi.multiprocess   
False
HTTP_USER_AGENT 
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.112 Safari/537.36'
wsgi.errors 
<open file '<stderr>', mode 'w' at 0x10f3ff1e0>
HTTP_ACCEPT_ENCODING    
'gzip, deflate, sdch'
__CF_USER_TEXT_ENCODING 
'0x1F5:0x0:0x0'
PWD 
'/Users/kevinsmith/Code/kolibri'
DJANGO_SETTINGS_MODULE  
'kolibri.deployment.default.settings.base'
CONTENT_TYPE    
'text/plain'
HTTP_HOST   
'127.0.0.1:8000'
HTTP_UPGRADE_INSECURE_REQUESTS  
'1'
REMOTE_HOST 
''
VIRTUALENVWRAPPER_WORKON_CD 
'1'
PATH_INFO   
u'/'
Settings
Using settings module kolibri.deployment.default.settings.base
Setting Value
CONTENT_COPY_DIR    
u'/Users/kevinsmith/Code/kolibri/kolibri/content/content_copy'
SECURE_BROWSER_XSS_FILTER   
False
USE_X_FORWARDED_PORT    
False
USE_THOUSAND_SEPARATOR  
False
CSRF_COOKIE_SECURE  
False
LANGUAGE_CODE   
u'en-us'
ROOT_URLCONF    
u'kolibri.deployment.default.urls'
MANAGERS    
[]
BASE_DIR    
'/Users/kevinsmith/Code/kolibri'
SILENCED_SYSTEM_CHECKS  
[]
DEFAULT_CHARSET 
'utf-8'
SESSION_SERIALIZER  
'django.contrib.sessions.serializers.JSONSerializer'
STATIC_ROOT 
None
ALLOWED_HOSTS   
[]
MESSAGE_STORAGE 
'django.contrib.messages.storage.fallback.FallbackStorage'
EMAIL_SUBJECT_PREFIX    
'[Django] '
SERVER_EMAIL    
'root@localhost'
SECURE_HSTS_SECONDS 
0
STATICFILES_FINDERS 
['django.contrib.staticfiles.finders.FileSystemFinder',
 'django.contrib.staticfiles.finders.AppDirectoriesFinder']
SESSION_CACHE_ALIAS 
'default'
SESSION_COOKIE_DOMAIN   
None
SESSION_COOKIE_NAME 
'sessionid'
TIME_INPUT_FORMATS  
['%H:%M:%S', '%H:%M:%S.%f', '%H:%M']
SECURE_REDIRECT_EXEMPT  
[]
DATABASES   
{u'default': {'ATOMIC_REQUESTS': False,
              'AUTOCOMMIT': True,
              'CONN_MAX_AGE': 0,
              u'ENGINE': u'django.db.backends.sqlite3',
              'HOST': '',
              u'NAME': u'/Users/kevinsmith/.kolibri/db.sqlite3',
              'OPTIONS': {},
              'PASSWORD': u'********************',
              'PORT': '',
              'TEST': {'CHARSET': None,
                       'COLLATION': None,
                       'MIRROR': None,
                       'NAME': None},
              'TIME_ZONE': None,
              'USER': ''}}
EMAIL_SSL_KEYFILE   
u'********************'
FILE_UPLOAD_DIRECTORY_PERMISSIONS   
None
FILE_UPLOAD_PERMISSIONS 
None
FILE_UPLOAD_HANDLERS    
['django.core.files.uploadhandler.MemoryFileUploadHandler',
 'django.core.files.uploadhandler.TemporaryFileUploadHandler']
DEFAULT_CONTENT_TYPE    
'text/html'
APPEND_SLASH    
True
LOCALE_PATHS    
[]
DATABASE_ROUTERS    
[]
DEFAULT_TABLESPACE  
''
YEAR_MONTH_FORMAT   
'F Y'
STATICFILES_STORAGE 
'django.contrib.staticfiles.storage.StaticFilesStorage'
CACHES  
{'default': {'BACKEND': 'django.core.cache.backends.locmem.LocMemCache'}}
KOLIBRI_HOME    
'/Users/kevinsmith/.kolibri'
SESSION_COOKIE_PATH 
'/'
EMAIL_HOST_PASSWORD 
u'********************'
SECURE_CONTENT_TYPE_NOSNIFF 
False
MIDDLEWARE_CLASSES  
(u'django.contrib.sessions.middleware.SessionMiddleware',
 u'django.middleware.common.CommonMiddleware',
 u'django.middleware.csrf.CsrfViewMiddleware',
 u'django.contrib.auth.middleware.AuthenticationMiddleware',
 u'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
 u'django.contrib.messages.middleware.MessageMiddleware',
 u'django.middleware.clickjacking.XFrameOptionsMiddleware',
 u'django.middleware.security.SecurityMiddleware')
USE_I18N    
True
THOUSAND_SEPARATOR  
','
SECRET_KEY  
u'********************'
LANGUAGE_COOKIE_NAME    
'django_language'
DEFAULT_INDEX_TABLESPACE    
''
LOGGING_CONFIG  
'logging.config.dictConfig'
CONTENT_DB_DIR  
u'/Users/kevinsmith/Code/kolibri/kolibri/content/content_db'
TEMPLATE_LOADERS    
['django.template.loaders.filesystem.Loader',
 'django.template.loaders.app_directories.Loader']
FIRST_DAY_OF_WEEK   
0
WSGI_APPLICATION    
u'kolibri.deployment.default.wsgi.application'
TEMPLATE_DEBUG  
False
X_FRAME_OPTIONS 
'SAMEORIGIN'
CSRF_COOKIE_NAME    
'csrftoken'
FORCE_SCRIPT_NAME   
None
USE_X_FORWARDED_HOST    
False
CSRF_HEADER_NAME    
'HTTP_X_CSRFTOKEN'
EMAIL_TIMEOUT   
None
SECURE_SSL_HOST 
None
SIGNING_BACKEND 
'django.core.signing.TimestampSigner'
SESSION_COOKIE_SECURE   
False
CSRF_COOKIE_DOMAIN  
None
FILE_CHARSET    
'utf-8'
DEBUG   
True
CSRF_TRUSTED_ORIGINS    
[]
LANGUAGE_COOKIE_DOMAIN  
None
DEFAULT_FILE_STORAGE    
'django.core.files.storage.FileSystemStorage'
INSTALLED_APPS  
[u'kolibri.core',
 u'django.contrib.admin',
 u'django.contrib.auth',
 u'django.contrib.contenttypes',
 u'django.contrib.sessions',
 u'django.contrib.messages',
 u'django.contrib.staticfiles',
 u'kolibri.auth.apps.KolibriAuthConfig',
 u'kolibri.content',
 u'rest_framework']
LANGUAGES   
[('af', 'Afrikaans'),
 ('ar', 'Arabic'),
 ('ast', 'Asturian'),
 ('az', 'Azerbaijani'),
 ('bg', 'Bulgarian'),
 ('be', 'Belarusian'),
 ('bn', 'Bengali'),
 ('br', 'Breton'),
 ('bs', 'Bosnian'),
 ('ca', 'Catalan'),
 ('cs', 'Czech'),
 ('cy', 'Welsh'),
 ('da', 'Danish'),
 ('de', 'German'),
 ('el', 'Greek'),
 ('en', 'English'),
 ('en-au', 'Australian English'),
 ('en-gb', 'British English'),
 ('eo', 'Esperanto'),
 ('es', 'Spanish'),
 ('es-ar', 'Argentinian Spanish'),
 ('es-co', 'Colombian Spanish'),
 ('es-mx', 'Mexican Spanish'),
 ('es-ni', 'Nicaraguan Spanish'),
 ('es-ve', 'Venezuelan Spanish'),
 ('et', 'Estonian'),
 ('eu', 'Basque'),
 ('fa', 'Persian'),
 ('fi', 'Finnish'),
 ('fr', 'French'),
 ('fy', 'Frisian'),
 ('ga', 'Irish'),
 ('gd', 'Scottish Gaelic'),
 ('gl', 'Galician'),
 ('he', 'Hebrew'),
 ('hi', 'Hindi'),
 ('hr', 'Croatian'),
 ('hu', 'Hungarian'),
 ('ia', 'Interlingua'),
 ('id', 'Indonesian'),
 ('io', 'Ido'),
 ('is', 'Icelandic'),
 ('it', 'Italian'),
 ('ja', 'Japanese'),
 ('ka', 'Georgian'),
 ('kk', 'Kazakh'),
 ('km', 'Khmer'),
 ('kn', 'Kannada'),
 ('ko', 'Korean'),
 ('lb', 'Luxembourgish'),
 ('lt', 'Lithuanian'),
 ('lv', 'Latvian'),
 ('mk', 'Macedonian'),
 ('ml', 'Malayalam'),
 ('mn', 'Mongolian'),
 ('mr', 'Marathi'),
 ('my', 'Burmese'),
 ('nb', 'Norwegian Bokmal'),
 ('ne', 'Nepali'),
 ('nl', 'Dutch'),
 ('nn', 'Norwegian Nynorsk'),
 ('os', 'Ossetic'),
 ('pa', 'Punjabi'),
 ('pl', 'Polish'),
 ('pt', 'Portuguese'),
 ('pt-br', 'Brazilian Portuguese'),
 ('ro', 'Romanian'),
 ('ru', 'Russian'),
 ('sk', 'Slovak'),
 ('sl', 'Slovenian'),
 ('sq', 'Albanian'),
 ('sr', 'Serbian'),
 ('sr-latn', 'Serbian Latin'),
 ('sv', 'Swedish'),
 ('sw', 'Swahili'),
 ('ta', 'Tamil'),
 ('te', 'Telugu'),
 ('th', 'Thai'),
 ('tr', 'Turkish'),
 ('tt', 'Tatar'),
 ('udm', 'Udmurt'),
 ('uk', 'Ukrainian'),
 ('ur', 'Urdu'),
 ('vi', 'Vietnamese'),
 ('zh-hans', 'Simplified Chinese'),
 ('zh-hant', 'Traditional Chinese')]
USE_L10N    
True
SECURE_HSTS_INCLUDE_SUBDOMAINS  
False
STATICFILES_DIRS    
[]
PREPEND_WWW 
False
SECURE_PROXY_SSL_HEADER 
None
LANGUAGE_COOKIE_AGE 
None
SESSION_COOKIE_HTTPONLY 
True
DEBUG_PROPAGATE_EXCEPTIONS  
False
CSRF_COOKIE_AGE 
31449600
MONTH_DAY_FORMAT    
'F j'
LOGIN_URL   
'/accounts/login/'
SESSION_EXPIRE_AT_BROWSER_CLOSE 
False
TIME_FORMAT 
'P'
AUTH_USER_MODEL 
u'kolibriauth.DeviceOwner'
DATE_INPUT_FORMATS  
['%Y-%m-%d',
 '%m/%d/%Y',
 '%m/%d/%y',
 '%b %d %Y',
 '%b %d, %Y',
 '%d %b %Y',
 '%d %b, %Y',
 '%B %d %Y',
 '%B %d, %Y',
 '%d %B %Y',
 '%d %B, %Y']
AUTHENTICATION_BACKENDS 
[u'kolibri.auth.backends.DeviceOwnerBackend',
 u'kolibri.auth.backends.FacilityUserBackend']
AUTH_PASSWORD_VALIDATORS    
u'********************'
PASSWORD_RESET_TIMEOUT_DAYS 
u'********************'
SESSION_FILE_PATH   
None
CACHE_MIDDLEWARE_ALIAS  
'default'
SESSION_SAVE_EVERY_REQUEST  
False
NUMBER_GROUPING 
0
SESSION_ENGINE  
'django.contrib.sessions.backends.db'
CSRF_FAILURE_VIEW   
'django.views.csrf.csrf_failure'
CSRF_COOKIE_PATH    
'/'
LOGIN_REDIRECT_URL  
'/accounts/profile/'
DECIMAL_SEPARATOR   
'.'
IGNORABLE_404_URLS  
[]
MIGRATION_MODULES   
{}
TEMPLATE_STRING_IF_INVALID  
''
LOGOUT_URL  
'/accounts/logout/'
EMAIL_USE_TLS   
False
FIXTURE_DIRS    
[]
EMAIL_HOST  
'localhost'
DATE_FORMAT 
'N j, Y'
MEDIA_ROOT  
''
DEFAULT_EXCEPTION_REPORTER_FILTER   
'django.views.debug.SafeExceptionReporterFilter'
ADMINS  
[]
FORMAT_MODULE_PATH  
None
DEFAULT_FROM_EMAIL  
'webmaster@localhost'
MEDIA_URL   
''
DATETIME_FORMAT 
'N j, Y, P'
TEMPLATE_DIRS   
[]
DISALLOWED_USER_AGENTS  
[]
ALLOWED_INCLUDE_ROOTS   
[]
LOGGING 
{u'disable_existing_loggers': False,
 u'filters': {u'require_debug_false': {u'()': u'django.utils.log.RequireDebugFalse'},
              u'require_debug_true': {u'()': u'django.utils.log.RequireDebugTrue'}},
 u'formatters': {u'color': {u'()': u'colorlog.ColoredFormatter',
                            u'format': u'%(log_color)s%(levelname)-8s %(message)s',
                            u'log_colors': {u'CRITICAL': u'bold_red',
                                            u'DEBUG': u'bold_black',
                                            u'ERROR': u'red',
                                            u'INFO': u'white',
                                            u'WARNING': u'yellow'}},
                 u'simple': {u'format': u'%(levelname)s %(message)s'},
                 u'simple_date': {u'format': u'%(levelname)s %(asctime)s %(module)s %(message)s'},
                 u'verbose': {u'format': u'%(levelname)s %(asctime)s %(module)s %(process)d %(thread)d %(message)s'}},
 u'handlers': {u'console': {u'class': u'logging.StreamHandler',
                            u'filters': [u'require_debug_true'],
                            u'formatter': u'color',
                            u'level': u'INFO'},
               u'file': {u'class': u'logging.FileHandler',
                         u'filename': u'/Users/kevinsmith/.kolibri/kolibri.log',
                         u'filters': [],
                         u'formatter': u'simple_date',
                         u'level': u'INFO'},
               u'file_debug': {u'class': u'logging.FileHandler',
                               u'filename': u'/Users/kevinsmith/.kolibri/debug.log',
                               u'filters': [u'require_debug_true'],
                               u'formatter': u'simple_date',
                               u'level': u'DEBUG'},
               u'mail_admins': {u'class': u'django.utils.log.AdminEmailHandler',
                                u'filters': [u'require_debug_false'],
                                u'level': u'ERROR'}},
 u'loggers': {u'django': {u'handlers': [u'console', u'file'],
                          u'propagate': True},
              u'django.request': {u'handlers': [u'mail_admins', u'file'],
                                  u'level': u'ERROR',
                                  u'propagate': False},
              u'kolibri': {u'handlers': [u'console',
                                         u'mail_admins',
                                         u'file',
                                         u'file_debug'],
                           u'level': u'INFO'}},
 u'version': 1}
SHORT_DATE_FORMAT   
'm/d/Y'
TEMPLATES   
[{u'APP_DIRS': True,
  u'BACKEND': u'django.template.backends.django.DjangoTemplates',
  u'DIRS': [],
  u'OPTIONS': {u'context_processors': [u'django.template.context_processors.debug',
                                       u'django.template.context_processors.request',
                                       u'django.contrib.auth.context_processors.auth',
                                       u'django.contrib.messages.context_processors.messages']}}]
TEST_RUNNER 
'django.test.runner.DiscoverRunner'
CACHE_MIDDLEWARE_KEY_PREFIX 
u'********************'
SECURE_SSL_REDIRECT 
False
TIME_ZONE   
u'UTC'
FILE_UPLOAD_MAX_MEMORY_SIZE 
2621440
EMAIL_BACKEND   
'django.core.mail.backends.smtp.EmailBackend'
EMAIL_USE_SSL   
False
TEMPLATE_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']
SESSION_COOKIE_AGE  
1209600
SETTINGS_MODULE 
'kolibri.deployment.default.settings.base'
USE_ETAGS   
False
LANGUAGES_BIDI  
['he', 'ar', 'fa', 'ur']
FILE_UPLOAD_TEMP_DIR    
None
INTERNAL_IPS    
[]
STATIC_URL  
u'/static/'
EMAIL_PORT  
25
USE_TZ  
True
SHORT_DATETIME_FORMAT   
'm/d/Y P'
TEST_NON_SERIALIZED_APPS    
[]
PASSWORD_HASHERS    
u'********************'
ABSOLUTE_URL_OVERRIDES  
{}
LANGUAGE_COOKIE_PATH    
'/'
CACHE_MIDDLEWARE_SECONDS    
600
EMAIL_SSL_CERTFILE  
None
CSRF_COOKIE_HTTPONLY    
False
DATETIME_INPUT_FORMATS  
['%Y-%m-%d %H:%M:%S',
 '%Y-%m-%d %H:%M:%S.%f',
 '%Y-%m-%d %H:%M',
 '%Y-%m-%d',
 '%m/%d/%Y %H:%M:%S',
 '%m/%d/%Y %H:%M:%S.%f',
 '%m/%d/%Y %H:%M',
 '%m/%d/%Y',
 '%m/%d/%y %H:%M:%S',
 '%m/%d/%y %H:%M:%S.%f',
 '%m/%d/%y %H:%M',
 '%m/%d/%y']
EMAIL_HOST_USER 
''
You're seeing this error because you have DEBUG = True in your Django settings file. Change that to False, and Django will display a standard page generated by the handler for this status code.

12-factor app review

Suggestion that we give our project a 12 factor review:

  • I. Codebase
  • II. Dependencies
  • III. Config
  • IV. Backing Services
  • V. Build, release, run
  • VI. Processes
  • VII. Port binding
  • VIII. Concurrency
  • IX. Disposability
  • X. Dev/prod parity
  • XI. Logs
  • XII. Admin processes

Reference: http://12factor.net/

Process: For each of the 12 factors, we get some inspiration and possibly open up a single PR to resolve it. The PR is linked here. If the task requires more work, open an issue and refer it to the task list above. Once processed, mark the task as completed.

I feel like taking the lead on this, and I won't make it a long a messy process once started. But if any one wants to join in, that'd be great :)

Move installed plugins to options.ini and deprecate kolibri_settings.json

Currently, we use JSON, which isn't human friendly. This was under the assumption that ConfigParser (Python 2) and configparser (Python 3) would be terrible to try and unify. However, it turns out there's a backport of Python 3's configparser for Python 2:

https://pypi.python.org/pypi/configparser

@rtibbles you asked about .ini files, thanks for reminding me about this :)

  • New ini-based configuration - introduced in #3607
  • Option for well-known + auto-enabled plugins
  • Do not store values directly for appending to INSTALLED_APPS, instead rename configuration option to PLUGINS and use module names. This avoids problems with application configs and can minimize the work done when checking if a plugin exists #1902

Simply frontend_assets syntax

Current syntax looks like this:

  {% frontend_assets 'kolibri_core' plugin='kolibri.core' %}

It would be nice if we made it match python import syntax, so it looks like this:

  {% frontend_assets 'kolibri.core.KolibriCoreFrontend' %}

That should make the name attribute for KolibriFrontendPluginBase unnecessary.

AttributeError: `Notetype` object has no attribute `MethodFilter`

Summary

I generated a kolibri-staticvia python setup.py bdist_wheel --static then install it on my Windows 7 VM using pip then run kolibre manage runserver
I got an error see the screenshots below.

Branch or installer

  • Version: master

Screenshots

screen shot 2016-07-09 at 2 34 43 am

How to reproduce

  1. cd ~/kolibri in your working machine
  2. run command python setup.py bdist_wheel --static
  3. install the kolibri-static in your Windows 7 virtualbox

Consolidate documentation regarding asset hooks

After some final amendments on #66, we went for a model where asset definitions and building takes place in one WebpackBundleHook and the inclusion itself is done through means of hooks for each location where hooks are loaded or with a template tag taking the asset's slug as a parameter.

Kolibri not installed on every device

Branch: develop
OS: all OSes

Hi,

I just noticed that Kolibri isn't installed on my laptop as of this writing. I checked other PCs and it's not there as well. How can I get to learning if it's not installed on every PC or device I use?

Please fix.

Conditional testing

Sphinx link checking fails because of network timeouts (no docs changes and the whole test may still break). I think we know the story of BDD / Saucelabs random failures. I'm vouching we should consider conditional testing based on git commit changesets. I've mentioned it before.

This can speed up testing.

Of course we should still do full testing once in a while.

Something based on this command:

git show -s --no-notes --oneline 41dcb5e1720929f015b1e04c59fa30f78661daa4

Enhance the webpack builder to look at INSTALLED_APPS for buildable assets

Use case:

An external contributor does a pip install kolibri and then creates their own plugin with frontend JS.

After doing a kolibri plugin enable and npm run build, webpack should then inspect the list of INSTALLED_APPS (where the new plugin is presumably added), and then build assets, and inform Django that the new assets are available for serving.

cannot enable `learn` plugin

Steps to repo:

  • rename your kolibri settings file
    • (e.g. from ~/.kolibri/kolibri_settings.json to ~/.kolibri/kolibri_settings.json.backup)
  • run kolibri plugin kolibri.plugins.learn enable

I get

Traceback (most recent call last):
  File "/Users/d/PythonEnvs/kolibri/bin/kolibri", line 9, in <module>
    load_entry_point('kolibri', 'console_scripts', 'kolibri')()
  File "/Users/d/Projects/learning_equality/repos/kolibri/kolibri/utils/cli.py", line 268, in main
    plugin(plugin_name, **arguments)
  File "/Users/d/Projects/learning_equality/repos/kolibri/kolibri/utils/cli.py", line 204, in plugin
    plugin_module = importlib.import_module(plugin_name + ".kolibri_plugin")
  File "/usr/local/Cellar/python/2.7.11/Frameworks/Python.framework/Versions/2.7/lib/python2.7/importlib/__init__.py", line 37, in import_module
    __import__(name)
  File "/Users/d/Projects/learning_equality/repos/kolibri/kolibri/plugins/learn/kolibri_plugin.py", line 8, in <module>
    from . import hooks, urls
  File "/Users/d/Projects/learning_equality/repos/kolibri/kolibri/plugins/learn/urls.py", line 3, in <module>
    from . import views
  File "/Users/d/Projects/learning_equality/repos/kolibri/kolibri/plugins/learn/views.py", line 4, in <module>
    from kolibri.content.api import get_top_level_topics
  File "/Users/d/Projects/learning_equality/repos/kolibri/kolibri/content/api.py", line 6, in <module>
    from kolibri.content import models as KolibriContent
  File "/Users/d/Projects/learning_equality/repos/kolibri/kolibri/content/models.py", line 13, in <module>
    from mptt.models import MPTTModel, TreeForeignKey
  File "/Users/d/PythonEnvs/kolibri/lib/python2.7/site-packages/mptt/models.py", line 379, in <module>
    class MPTTModel(six.with_metaclass(MPTTModelBase, models.Model)):
  File "/Users/d/PythonEnvs/kolibri/lib/python2.7/site-packages/django/utils/six.py", line 808, in __new__
    return meta(name, bases, d)
  File "/Users/d/PythonEnvs/kolibri/lib/python2.7/site-packages/mptt/models.py", line 262, in __new__
    cls = super_new(meta, class_name, bases, class_dict)
  File "/Users/d/PythonEnvs/kolibri/lib/python2.7/site-packages/django/db/models/base.py", line 94, in __new__
    app_config = apps.get_containing_app_config(module)
  File "/Users/d/PythonEnvs/kolibri/lib/python2.7/site-packages/django/apps/registry.py", line 239, in get_containing_app_config
    self.check_apps_ready()
  File "/Users/d/PythonEnvs/kolibri/lib/python2.7/site-packages/django/apps/registry.py", line 124, in check_apps_ready
    raise AppRegistryNotReady("Apps aren't loaded yet.")
django.core.exceptions.AppRegistryNotReady: Apps aren't loaded yet.

Workaround for new Kolibri check-outs:

manually set your settings file to:

{"FIRST_RUN": false, "AUTO_SEARCH_PLUGINS": ["some.plugin.module.path"], "INSTALLED_APPS": ["kolibri.plugins.management", "kolibri.plugins.learn", "kolibri.plugins.document_pdf_render", "kolibri.plugins.video_mp4_render", "kolibri.plugins.audio_mp3_render"]}

No module named 'kolibri.utils'

Branch:master

Current behaviour: Build and install the Kolibri sdist will spawn these error.

Processing ./dist/kolibri-0.0.1.dev20160706202123.tar.gz
    Complete output from command python setup.py egg_info:
    Traceback (most recent call last):
      File "<string>", line 1, in <module>
      File "/var/folders/pf/jwg228js7cg687y7hkgym1040000gn/T/pip-fy99cddn-build/setup.py", line 16, in <module>
        import kolibri
      File "/private/var/folders/pf/jwg228js7cg687y7hkgym1040000gn/T/pip-fy99cddn-build/kolibri/__init__.py", line 5, in <module>
        from .utils.version import get_version
    ImportError: No module named 'kolibri.utils'

Command "python setup.py egg_info" failed with error code 1 in /var/folders/pf/jwg228js7cg687y7hkgym1040000gn/T/pip-fy99cddn-build/

"Cannot redefine property: e" error when running from production-built code

I'm experimenting with adding a cherrypy-based production-mode server, and came across an issue with code built using the production webpack configuration.

Observed

image

Steps to reproduce

  1. Run npm run build
  2. Load site in browser (without rebuilding with --watch)

Observations

This is "fixed" by commenting out the UglifyJsPlugin from:
https://github.com/learningequality/kolibri/blob/master/frontend_build/src/webpack.config.prod.js#L20

Additonal note

Commenting out just the warning suppression from the uglification, we get the following list of warnings. It seems like the uglification is being applied across a lot of source files that are not ours, which may not be desirable (and could be a source of problems, perhaps?).

    WARNING in default_frontend-c202a7d97c46c1416720.js from UglifyJs
    Condition always true [./kolibri/core/assets/src/core_app_instance.js:10,24]
    Side effects in initialization of unused variable isInteger [./~/babel-polyfill/~/core-js/modules/_typed-array.js:14,0]
    Side effects in initialization of unused variable isIterable [./~/babel-polyfill/~/core-js/modules/_typed-array.js:28,0]
    Condition always true [./~/loglevel/lib/loglevel.js:11,5]
    Dropping unreachable code [./~/loglevel/lib/loglevel.js:14,0]
    Side effects in initialization of unused variable parseInt [./~/babel-polyfill/~/core-js/modules/_typed-buffer.js:24,0]
    Side effects in initialization of unused variable min [./~/babel-polyfill/~/core-js/modules/_typed-buffer.js:30,0]
    Dropping unused variable vertxRequire [./~/rest/~/when/lib/env.js:31,0]
    Condition always false [./~/style-loader/addStyles.js:24,0]
    Dropping unreachable code [./~/style-loader/addStyles.js:25,0]
    Condition always false [./~/vue-style-loader/addStyles.js:24,0]
    Dropping unreachable code [./~/vue-style-loader/addStyles.js:25,0]
    Side effects in initialization of unused variable hide [./~/babel-polyfill/~/core-js/modules/_collection-strong.js:4,0]
    Side effects in initialization of unused variable has [./~/babel-polyfill/~/core-js/modules/es6.weak-map.js:8,0]
    Condition always true [./~/vue-intl/dist/vue-intl.js:42,0]
    Condition always true [./~/vue-intl/dist/vue-intl.js:2743,0]
    Condition always true [./~/vue-intl/dist/vue-intl.js:2762,0]
    Condition always true [./~/vue-intl/dist/vue-intl.js:2793,0]
    Condition always true [./~/vue-intl/dist/vue-intl.js:2823,0]
    Condition always true [./~/vue-intl/dist/vue-intl.js:2846,0]
    Condition always true [./~/vue-intl/dist/vue-intl.js:2864,0]
    Boolean && always false [./~/vue-intl/dist/vue-intl.js:2894,0]
    Condition always false [./~/vue-intl/dist/vue-intl.js:2894,0]
    Dropping unreachable code [./~/vue-intl/dist/vue-intl.js:2895,0]
    Condition always true [./~/vue-intl/dist/vue-intl.js:2906,0]
    Condition always true [./~/vue-intl/dist/vue-intl.js:2911,0]
    Condition always true [./~/vue-intl/dist/vue-intl.js:2928,0]
    Condition always true [./~/vue-intl/dist/vue-intl.js:2935,0]
    Side effects in initialization of unused variable hasValues [./~/vue-intl/dist/vue-intl.js:2890,0]
    Dropping side-effect-free statement [./~/vue-intl/dist/vue-intl.js:60,0]
    Dropping unused function text [./~/vue-intl/dist/vue-intl.js:525,0]
    Dropping unused function offset [./~/vue-intl/dist/vue-intl.js:529,0]
    Dropping unused function line [./~/vue-intl/dist/vue-intl.js:533,0]
    Dropping unused function column [./~/vue-intl/dist/vue-intl.js:537,0]
    Dropping unused function expected [./~/vue-intl/dist/vue-intl.js:541,0]
    Dropping unused function error [./~/vue-intl/dist/vue-intl.js:545,0]
    Dropping unused variable peg$c0 [./~/vue-intl/dist/vue-intl.js:354,0]
    Side effects in initialization of unused variable resolvedLocale [./~/vue-intl/dist/vue-intl.js:2194,0]
    Side effects in initialization of unused variable es3 [./~/vue-intl/dist/vue-intl.js:106,0]
    Side effects in initialization of unused variable es3$1 [./~/vue-intl/dist/vue-intl.js:2061,0]
    Side effects in initialization of unused variable es3$2 [./~/vue-intl/dist/vue-intl.js:2482,0]
    Condition left of && always false [./~/vue/dist/vue.common.js:1120,0]
    Dropping side-effect-free statement [./~/vue/dist/vue.common.js:1120,0]
    Dropping side-effect-free statement [./~/vue/dist/vue.common.js:1119,0]
    Dropping unused variable selector [./~/vue/dist/vue.common.js:1117,0]
    Condition always false [./~/vue/dist/vue.common.js:1579,7]
    Dropping unreachable code [./~/vue/dist/vue.common.js:1579,7]
    Declarations in unreachable code! [./~/vue/dist/vue.common.js:1580,0]
    Dropping unused variable expectedTag [./~/vue/dist/vue.common.js:1580,0]
    Condition always false [./~/vue/dist/vue.common.js:1783,0]
    Dropping unreachable code [./~/vue/dist/vue.common.js:1784,0]
    Declarations in unreachable code! [./~/vue/dist/vue.common.js:1784,0]
    Condition left of && always false [./~/vue/dist/vue.common.js:1789,0]
    Dropping side-effect-free statement [./~/vue/dist/vue.common.js:1789,0]
    Condition always false [./~/vue/dist/vue.common.js:1794,0]
    Dropping unreachable code [./~/vue/dist/vue.common.js:1795,0]
    Dropping unused variable map [./~/vue/dist/vue.common.js:1784,0]
    Condition left of && always false [./~/vue/dist/vue.common.js:1855,0]
    Dropping side-effect-free statement [./~/vue/dist/vue.common.js:1855,0]
    Condition always false [./~/vue/dist/vue.common.js:1878,0]
    Dropping unreachable code [./~/vue/dist/vue.common.js:1879,0]
    Condition always false [./~/vue/dist/vue.common.js:1932,0]
    Dropping unreachable code [./~/vue/dist/vue.common.js:1933,0]
    Condition always false [./~/vue/dist/vue.common.js:2767,0]
    Dropping unreachable code [./~/vue/dist/vue.common.js:2768,0]
    Condition always false [./~/vue/dist/vue.common.js:2778,0]
    Dropping unreachable code [./~/vue/dist/vue.common.js:2779,0]
    Condition left of && always false [./~/vue/dist/vue.common.js:2884,0]
    Dropping side-effect-free statement [./~/vue/dist/vue.common.js:2884,0]
    Condition left of && always false [./~/vue/dist/vue.common.js:2912,0]
    Dropping side-effect-free statement [./~/vue/dist/vue.common.js:2912,0]
    Condition left of && always false [./~/vue/dist/vue.common.js:2930,0]
    Dropping side-effect-free statement [./~/vue/dist/vue.common.js:2930,0]
    Condition always false [./~/vue/dist/vue.common.js:3052,0]
    Dropping unreachable code [./~/vue/dist/vue.common.js:3054,0]
    Condition always false [./~/vue/dist/vue.common.js:5982,0]
    Dropping unreachable code [./~/vue/dist/vue.common.js:5982,0]
    Condition left of && always false [./~/vue/dist/vue.common.js:5992,0]
    Dropping side-effect-free statement [./~/vue/dist/vue.common.js:5992,0]
    Condition always false [./~/vue/dist/vue.common.js:6028,0]
    Dropping unreachable code [./~/vue/dist/vue.common.js:6029,0]
    Condition always false [./~/vue/dist/vue.common.js:6036,0]
    Dropping unreachable code [./~/vue/dist/vue.common.js:6037,0]
    Condition always false [./~/vue/dist/vue.common.js:6042,5]
    Dropping unreachable code [./~/vue/dist/vue.common.js:6042,5]
    Declarations in unreachable code! [./~/vue/dist/vue.common.js:6044,0]
    Dropping unused variable lowerCaseName [./~/vue/dist/vue.common.js:6044,0]
    Condition left of && always false [./~/vue/dist/vue.common.js:6197,0]
    Dropping side-effect-free statement [./~/vue/dist/vue.common.js:6197,0]
    Condition always false [./~/vue/dist/vue.common.js:6233,0]
    Dropping unreachable code [./~/vue/dist/vue.common.js:6234,0]
    Condition left of && always false [./~/vue/dist/vue.common.js:6241,0]
    Dropping side-effect-free statement [./~/vue/dist/vue.common.js:6241,0]
    Condition always false [./~/vue/dist/vue.common.js:6467,0]
    Dropping unreachable code [./~/vue/dist/vue.common.js:6468,0]
    Condition always true [./~/vue/dist/vue.common.js:6879,0]
    Condition always false [./~/vue/dist/vue.common.js:6949,0]
    Dropping unreachable code [./~/vue/dist/vue.common.js:6950,0]
    Condition always false [./~/vue/dist/vue.common.js:7011,3]
    Dropping unreachable code [./~/vue/dist/vue.common.js:7011,3]
    Declarations in unreachable code! [./~/vue/dist/vue.common.js:7013,0]
    Declarations in unreachable code! [./~/vue/dist/vue.common.js:7024,0]
    Dropping unused variable names [./~/vue/dist/vue.common.js:7013,0]
    Dropping unused variable plural [./~/vue/dist/vue.common.js:7024,0]
    Condition always false [./~/vue/dist/vue.common.js:7453,0]
    Dropping unreachable code [./~/vue/dist/vue.common.js:7454,0]
    Condition left of && always false [./~/vue/dist/vue.common.js:7654,0]
    Dropping side-effect-free statement [./~/vue/dist/vue.common.js:7654,0]
    Condition left of && always false [./~/vue/dist/vue.common.js:7683,0]
    Dropping side-effect-free statement [./~/vue/dist/vue.common.js:7683,0]
    Condition always false [./~/vue/dist/vue.common.js:7750,0]
    Dropping unreachable code [./~/vue/dist/vue.common.js:7751,0]
    Condition left of && always false [./~/vue/dist/vue.common.js:7840,0]
    Dropping side-effect-free statement [./~/vue/dist/vue.common.js:7840,0]
    Dropping side-effect-free statement [./~/vue/dist/vue.common.js:7839,0]
    Condition left of && always false [./~/vue/dist/vue.common.js:7858,0]
    Dropping side-effect-free statement [./~/vue/dist/vue.common.js:7858,0]
    Condition always false [./~/vue/dist/vue.common.js:7873,7]
    Dropping unreachable code [./~/vue/dist/vue.common.js:7874,0]
    Condition left of && always false [./~/vue/dist/vue.common.js:8126,0]
    Dropping side-effect-free statement [./~/vue/dist/vue.common.js:8126,0]
    Condition always false [./~/vue/dist/vue.common.js:8254,0]
    Dropping unreachable code [./~/vue/dist/vue.common.js:8255,0]
    Condition left of && always false [./~/vue/dist/vue.common.js:8828,0]
    Dropping side-effect-free statement [./~/vue/dist/vue.common.js:8828,0]
    Condition left of && always false [./~/vue/dist/vue.common.js:9403,0]
    Dropping side-effect-free statement [./~/vue/dist/vue.common.js:9403,0]
    Condition always false [./~/vue/dist/vue.common.js:9904,0]
    Dropping unreachable code [./~/vue/dist/vue.common.js:9905,0]
    Condition always false [./~/vue/dist/vue.common.js:9995,0]
    Dropping unreachable code [./~/vue/dist/vue.common.js:9996,0]
    Condition always false [./~/vue/dist/vue.common.js:1008,0]
    Dropping unreachable code [./~/vue/dist/vue.common.js:1009,0]
    Condition always false [./~/vue/dist/vue.common.js:1545,0]
    Dropping unreachable code [./~/vue/dist/vue.common.js:1546,0]
    Condition left of && always false [./~/vue/dist/vue.common.js:1660,0]
    Dropping side-effect-free statement [./~/vue/dist/vue.common.js:1660,0]
    Condition left of && always false [./~/vue/dist/vue.common.js:1694,0]
    Dropping side-effect-free statement [./~/vue/dist/vue.common.js:1694,0]
    Condition always false [./~/vue/dist/vue.common.js:2734,0]
    Dropping unreachable code [./~/vue/dist/vue.common.js:2735,0]
    Condition always false [./~/vue/dist/vue.common.js:3154,0]
    Dropping unreachable code [./~/vue/dist/vue.common.js:3155,0]
    Condition always false [./~/vue/dist/vue.common.js:3190,0]
    Dropping unreachable code [./~/vue/dist/vue.common.js:3191,0]
    Condition left of && always false [./~/vue/dist/vue.common.js:3198,0]
    Dropping side-effect-free statement [./~/vue/dist/vue.common.js:3198,0]
    Condition always false [./~/vue/dist/vue.common.js:3279,0]
    Dropping unreachable code [./~/vue/dist/vue.common.js:3280,0]
    Condition always false [./~/vue/dist/vue.common.js:3308,0]
    Dropping unreachable code [./~/vue/dist/vue.common.js:3308,0]
    Side effects in initialization of unused variable prevError [./~/vue/dist/vue.common.js:3306,0]
    Condition left of && always false [./~/vue/dist/vue.common.js:3989,0]
    Dropping side-effect-free statement [./~/vue/dist/vue.common.js:3989,0]
    Condition left of && always false [./~/vue/dist/vue.common.js:4343,0]
    Dropping side-effect-free statement [./~/vue/dist/vue.common.js:4343,0]
    Dropping side-effect-free statement [./~/vue/dist/vue.common.js:4342,7]
    Condition left of && always false [./~/vue/dist/vue.common.js:4351,0]
    Dropping side-effect-free statement [./~/vue/dist/vue.common.js:4351,0]
    Condition always false [./~/vue/dist/vue.common.js:4355,7]
    Dropping unreachable code [./~/vue/dist/vue.common.js:4356,0]
    Condition left of && always false [./~/vue/dist/vue.common.js:4382,0]
    Dropping side-effect-free statement [./~/vue/dist/vue.common.js:4382,0]
    Condition always false [./~/vue/dist/vue.common.js:4566,0]
    Dropping unreachable code [./~/vue/dist/vue.common.js:4567,0]
    Condition left of && always false [./~/vue/dist/vue.common.js:4590,0]
    Dropping side-effect-free statement [./~/vue/dist/vue.common.js:4590,0]
    Condition left of && always false [./~/vue/dist/vue.common.js:5023,0]
    Dropping side-effect-free statement [./~/vue/dist/vue.common.js:5023,0]
    Condition left of && always false [./~/vue/dist/vue.common.js:5035,0]
    Dropping side-effect-free statement [./~/vue/dist/vue.common.js:5035,0]
    Condition left of && always false [./~/vue/dist/vue.common.js:5151,0]
    Dropping side-effect-free statement [./~/vue/dist/vue.common.js:5151,0]
    Condition always false [./~/vue/dist/vue.common.js:5245,0]
    Dropping unreachable code [./~/vue/dist/vue.common.js:5246,0]
    Condition left of && always false [./~/vue/dist/vue.common.js:5356,0]
    Dropping side-effect-free statement [./~/vue/dist/vue.common.js:5356,0]
    Condition always false [./~/vue/dist/vue.common.js:5362,0]
    Dropping unreachable code [./~/vue/dist/vue.common.js:5362,0]
    Declarations in unreachable code! [./~/vue/dist/vue.common.js:5363,0]
    Dropping unused variable raw [./~/vue/dist/vue.common.js:5363,0]
    Condition left of && always false [./~/vue/dist/vue.common.js:5471,0]
    Dropping side-effect-free statement [./~/vue/dist/vue.common.js:5471,0]
    Condition left of && always false [./~/vue/dist/vue.common.js:5645,0]
    Dropping side-effect-free statement [./~/vue/dist/vue.common.js:5645,0]
    Condition always false [./~/vue/dist/vue.common.js:5809,0]
    Dropping unreachable code [./~/vue/dist/vue.common.js:5810,0]
    Condition always false [./~/vue/dist/vue.common.js:8432,3]
    Dropping unreachable code [./~/vue/dist/vue.common.js:8433,0]
    Condition always false [./~/vue/dist/vue.common.js:8495,0]
    Dropping unreachable code [./~/vue/dist/vue.common.js:8496,0]
    Condition always false [./~/vue/dist/vue.common.js:10024,5]
    Dropping unreachable code [./~/vue/dist/vue.common.js:10025,0]
    Dropping unused function formatType [./~/vue/dist/vue.common.js:6310,0]
    Dropping unused function formatValue [./~/vue/dist/vue.common.js:6321,0]
    Dropping unused variable formatComponentName [./~/vue/dist/vue.common.js:1006,0]
    Dropping unused variable isUnknownElement [./~/vue/dist/vue.common.js:1544,0]
    Dropping unused variable warnNonExistent [./~/vue/dist/vue.common.js:2733,0]
    Dropping unused variable settablePathRE [./~/vue/dist/vue.common.js:5961,0]
    Side effects in initialization of unused variable anInstance [./~/babel-polyfill/~/core-js/modules/es6.number.to-fixed.js:3,0]
    Side effects in initialization of unused variable anObject [./~/babel-polyfill/~/core-js/modules/es6.promise.js:8,0]
    Side effects in initialization of unused variable setProto [./~/babel-polyfill/~/core-js/modules/es6.promise.js:12,0]
    Side effects in initialization of unused variable TYPED_ARRAY [./~/babel-polyfill/~/core-js/modules/es6.typed.array-buffer.js:9,0]
    Dropping unused variable D [./~/babel-polyfill/~/core-js/modules/es7.object.get-own-property-descriptors.js:15,0]
    Side effects in initialization of unused variable anObject [./~/babel-runtime/~/core-js/library/modules/es6.promise.js:8,0]
    Side effects in initialization of unused variable setProto [./~/babel-runtime/~/core-js/library/modules/es6.promise.js:12,0]
    Condition always true [./~/fg-loadcss/src/loadCSS.js:73,0]
    Dropping unreachable code [./~/fg-loadcss/src/loadCSS.js:77,0]
    Condition always true [./~/scriptjs/dist/script.js:9,0]
    Dropping unreachable code [./~/scriptjs/dist/script.js:10,0]
    Dropping unused variable s [./~/scriptjs/dist/script.js:14,0]
    Condition always false [./~/style-loader!./~/css-loader!./kolibri/core/assets/src/font-NotoSans.css:10,0]
    Dropping unreachable code [./~/style-loader!./~/css-loader!./kolibri/core/assets/src/font-NotoSans.css:12,0]
    Side effects in initialization of unused variable update [./~/style-loader!./~/css-loader!./kolibri/core/assets/src/font-NotoSans.css:7,0]
    Condition always false [./~/style-loader!./~/css-loader!./~/normalize.css/normalize.css:10,0]
    Dropping unreachable code [./~/style-loader!./~/css-loader!./~/normalize.css/normalize.css:12,0]
    Side effects in initialization of unused variable update [./~/style-loader!./~/css-loader!./~/normalize.css/normalize.css:7,0]
    Condition always false [./~/style-loader!./~/css-loader?sourceMap!./~/stylus-loader!./~/stylint-loader!./kolibri/core/assets/src/core-global.styl:10,0]
    Dropping unreachable code [./~/style-loader!./~/css-loader?sourceMap!./~/stylus-loader!./~/stylint-loader!./kolibri/core/assets/src/core-global.styl:12,0]
    Side effects in initialization of unused variable update [./~/style-loader!./~/css-loader?sourceMap!./~/stylus-loader!./~/stylint-loader!./kolibri/core/assets/src/core-global.styl:7,0]
    Condition always false [./~/vue-style-loader!./~/css-loader?sourceMap!./~/vue-loader/lib/style-rewriter.js?id=_v-14214bc0&scoped=true!./~/stylus-loader!./~/stylint-loader!./~/vue-loader/lib/selector.js?type=style&index=0!./kolibri/core/assets/src/core-base.vue:10,0]
    Dropping unreachable code [./~/vue-style-loader!./~/css-loader?sourceMap!./~/vue-loader/lib/style-rewriter.js?id=_v-14214bc0&scoped=true!./~/stylus-loader!./~/stylint-loader!./~/vue-loader/lib/selector.js?type=style&index=0!./kolibri/core/assets/src/core-base.vue:12,0]
    Side effects in initialization of unused variable update [./~/vue-style-loader!./~/css-loader?sourceMap!./~/vue-loader/lib/style-rewriter.js?id=_v-14214bc0&scoped=true!./~/stylus-loader!./~/stylint-loader!./~/vue-loader/lib/selector.js?type=style&index=0!./kolibri/core/assets/src/core-base.vue:7,0]
    Condition always false [./~/vue-style-loader!./~/css-loader?sourceMap!./~/vue-loader/lib/style-rewriter.js?id=_v-5e2b17c6&scoped=true!./~/stylus-loader!./~/stylint-loader!./~/vue-loader/lib/selector.js?type=style&index=0!./kolibri/core/assets/src/content-renderer.vue:10,0]
    Dropping unreachable code [./~/vue-style-loader!./~/css-loader?sourceMap!./~/vue-loader/lib/style-rewriter.js?id=_v-5e2b17c6&scoped=true!./~/stylus-loader!./~/stylint-loader!./~/vue-loader/lib/selector.js?type=style&index=0!./kolibri/core/assets/src/content-renderer.vue:12,0]
    Side effects in initialization of unused variable update [./~/vue-style-loader!./~/css-loader?sourceMap!./~/vue-loader/lib/style-rewriter.js?id=_v-5e2b17c6&scoped=true!./~/stylus-loader!./~/stylint-loader!./~/vue-loader/lib/selector.js?type=style&index=0!./kolibri/core/assets/src/content-renderer.vue:7,0]
    Condition always false [./~/vue-style-loader!./~/css-loader?sourceMap!./~/vue-loader/lib/style-rewriter.js?id=_v-613f7103&scoped=true!./~/stylus-loader!./~/stylint-loader!./~/vue-loader/lib/selector.js?type=style&index=0!./kolibri/core/assets/src/navigation.vue:10,0]
    Dropping unreachable code [./~/vue-style-loader!./~/css-loader?sourceMap!./~/vue-loader/lib/style-rewriter.js?id=_v-613f7103&scoped=true!./~/stylus-loader!./~/stylint-loader!./~/vue-loader/lib/selector.js?type=style&index=0!./kolibri/core/assets/src/navigation.vue:12,0]
    Side effects in initialization of unused variable update [./~/vue-style-loader!./~/css-loader?sourceMap!./~/vue-loader/lib/style-rewriter.js?id=_v-613f7103&scoped=true!./~/stylus-loader!./~/stylint-loader!./~/vue-loader/lib/selector.js?type=style&index=0!./kolibri/core/assets/src/navigation.vue:7,0]
    Condition always true [./~/vuex/dist/vuex.js:7,0]
    Dropping side-effect-free statement [./~/vuex/dist/vuex.js:53,0]

    WARNING in 1.1-c202a7d97c46c1416720.js from UglifyJs
    Dropping side-effect-free statement [./~/intl/lib/core.js:9,0]

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.