internlm/SWE-Fixer-Train-110K huggingface dataset:
Repository: learningequality/kolibri

Issue:
license description has confusing wording

### Observed behavior

reported by @carinediaz that this string has confusing wording and will be difficult for translators: https://crowdin.com/translate/kolibri/3306/en-ptbr#234420

> This is the license used by Wikipedia, and is recommended for materials that would benefit from incorporating resource from Wikipedia and similarly licensed projects.

Specifically, the phrase "would benefit from" is confusing, and 'resource' should be 'resources'

### Expected behavior

alternate phrasing: 

> This is the license used by Wikipedia. It recommended for materials that use resources from Wikipedia or similarly licensed projects.


### User-facing consequences

Unclear wording. 

However, this string is not actually used yet so implications are minimal for the time being



### Context

0.13.0 alpha 0


Discussion:

Resolving patch:
diff --git a/build_tools/i18n/crowdin.py b/build_tools/i18n/crowdin.py
--- a/build_tools/i18n/crowdin.py
+++ b/build_tools/i18n/crowdin.py
@@ -56,6 +56,14 @@ def checkApiKey():
 """
 
 
+PERSEUS_CSV_NOT_AVAILABLE = """
+You must manually generate Perseus CSV files in order to upload them.
+Change to the installed Perseus directory and run:
+
+    yarn run makemessages
+"""
+
+
 def checkPerseus():
     if not (os.path.exists(utils.PERSEUS_LOCALE_PATH)):
         logging.error("Cannot find Perseus locale directory.")
@@ -66,6 +74,11 @@ def checkPerseus():
         logging.info(PERSEUS_NOT_INSTALLED_FOR_DEV)
         click.confirm("Continue anyway?", abort=True)
 
+    if not (os.path.exists(os.path.join(utils.PERSEUS_LOCALE_PATH, PERSEUS_CSV))):
+        logging.warning("Perseus strings are not available as CSVs")
+        logging.info(PERSEUS_CSV_NOT_AVAILABLE)
+        click.confirm("Continue anyway?", abort=True)
+
 
 """
 Shared constants and helpers


Test patch:
Repository: learningequality/kolibri

Issue:
recipients column in coach tools in not accurate

### Observed behavior

recipients column always indicates assignment to the entire class, even when that's not true:

![groups](https://user-images.githubusercontent.com/2367265/69926711-644bce80-146a-11ea-8f2b-82ec444fb367.gif)


### Expected behavior

recipients column should be accurate

### User-facing consequences

confusion

### Errors and logs

none observed

### Steps to reproduce

create a lesson and assign it to a group

### Context

0.13.0 beta 3



Discussion:

Resolving patch:
diff --git a/kolibri/core/lessons/viewsets.py b/kolibri/core/lessons/viewsets.py
--- a/kolibri/core/lessons/viewsets.py
+++ b/kolibri/core/lessons/viewsets.py
@@ -4,6 +4,7 @@
 
 from django.db import connection
 from django.db.models import CharField
+from django.db.models import F
 from django_filters.rest_framework import DjangoFilterBackend
 
 from .serializers import LessonSerializer
@@ -104,7 +105,11 @@ def _process_item(item):
         assignments = {
             a["id"]: _process_item(a)
             for a in assignments.values(
-                "id", "collection", "collection__kind", "learner_ids", "assigned_by"
+                "id",
+                "collection",
+                "learner_ids",
+                "assigned_by",
+                collection_kind=F("collection__kind"),
             )
         }
         for item in items:


Test patch:
Repository: learningequality/kolibri

Issue:
tasks got cleared without triggering a 'clear task' action
### Observed behavior

Observed that my list of tasks got cleared after initiating a new import

### Expected behavior

tasks should not be cleared until explicitly done by the user

### User-facing consequences

loss of data: historical context

### Errors and logs

none

### Steps to reproduce

see notes below

### Context

0.13.0 beta 1


Discussion:
Seeing this on beta4 too, and cannot figure out when it happens exactly: just realized that navigating back to the task manager page all previous tasks (completed *and* cancelled) disappeared without me clearing them intentionally 😕 
@indirectlylit Are the tasks supposed to survive the device restart? 
I also realized that when I restart the VM all the past tasks disappear. 
> Are the tasks supposed to survive the device restart?

I don't believe so, no. That would probably be a new feature
Just making sure, not saying they should, thanks!
Correct - currently the task scheduler gets cleared at every restart.
opened a new issue for that here: https://github.com/learningequality/kolibri/issues/6255
There are three places I see in the code where `deleteFinishedTasks` is being inappropriately called:

```
kolibri/plugins/device/assets/src/modules/manageContent/actions/taskActions.js:
   16        () => {
   17          cancelWatch();
   18:         TaskResource.deleteFinishedTasks().then(resolve);
   19        }
   20      );

kolibri/plugins/device/assets/src/modules/wizard/utils.js:
   57        const { taskId, cancelled } = completedTask;
   58        if (taskId && !cancelled) {
   59:         return TaskResource.deleteFinishedTasks().then(() => {
   60            return getChannelWithContentSizes(transferredChannel.id);
   61          });

kolibri/plugins/facility/assets/src/modules/manageCSV/actions.js:
   67        if (task.status === TaskStatuses.COMPLETED) {
   68          store.commit(commitFinish, new Date());
   69:         TaskResource.deleteFinishedTasks();
   70        }
   71      }
```

Seems like these should be corrected to only ever delete the task in question.
agreed

Resolving patch:
diff --git a/kolibri/core/content/serializers.py b/kolibri/core/content/serializers.py
--- a/kolibri/core/content/serializers.py
+++ b/kolibri/core/content/serializers.py
@@ -67,6 +67,7 @@ class Meta:
             "version",
             "available",
             "num_coach_contents",
+            "public",
         )
 
 


Test patch:
Repository: learningequality/kolibri

Issue:
update Kolibri to handle new h5p content kind
### Observed behavior

In order to decouple H5P from the HTML5 content kind and allow us to properly filter supported types, we're migrating H5P to be it's own type.

This will also require changes in other repos such as studio and kolibri utils.

### Expected behavior

```
            Kind        Preset      Extension
---------------------------------------------
Current     html5       H5P_ZIP     .h5p
New         h5p         H5P_ZIP     .h5p
```

### User-facing consequences

must show content when it can be rendered, and not show it when it cannot


### Steps to reproduce

experiment with importing html5 and h5p content in both recently and non-recently published channels

### Context

0.13.0 beta 3


Discussion:
`le-utils` PR for introducing new `h5p` content kind is here: https://github.com/learningequality/le-utils/pull/71

Studio changes needed to change h5p export to be of content kind `h5p` so that they can be ignored by 0.12.s Kolibris.

Note Kolibri "can I render H5P" logic changed in  https://github.com/learningequality/kolibri/pull/6268
0.13 now uses format preset check: https://github.com/learningequality/kolibri/pull/6268/files#diff-ef2895192188b3837bcd15d73cafddf2R19




Resolving patch:
diff --git a/kolibri/core/content/migrations/0025_add_h5p_kind.py b/kolibri/core/content/migrations/0025_add_h5p_kind.py
new file mode 100644
--- /dev/null
+++ b/kolibri/core/content/migrations/0025_add_h5p_kind.py
@@ -0,0 +1,34 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11.23 on 2019-12-19 02:29
+from __future__ import unicode_literals
+
+from django.db import migrations
+from django.db import models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ("content", "0024_channelmetadata_public"),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name="contentnode",
+            name="kind",
+            field=models.CharField(
+                blank=True,
+                choices=[
+                    ("topic", "Topic"),
+                    ("video", "Video"),
+                    ("audio", "Audio"),
+                    ("exercise", "Exercise"),
+                    ("document", "Document"),
+                    ("html5", "HTML5 App"),
+                    ("slideshow", "Slideshow"),
+                    ("h5p", "H5P"),
+                ],
+                max_length=200,
+            ),
+        ),
+    ]


Test patch:
Repository: learningequality/kolibri

Issue:
multiple instances of Kolibri can access the same DB at the same time
### Observed behavior

I am able to run both a pex and an app on MacOS simultaneously

### Expected behavior

The second Kolibri instance should fail to start with an error that another instance appears to already be running.

One way to achieve this would be for Kolibri to periodically write timestamps to a file like `$KOLIBRI_HOME/heartbeat.txt`. Whenever a new instance of Kolibri starts, it would read this file and error out if the most recent timestamp is within some threshold of the current time (e.g. 30 seconds).

### User-facing consequences

more likely to get situations like https://github.com/learningequality/kolibri/issues/6334



### Context

0.13.0



Discussion:
Our current sanity check only checks same port, it would be relatively straightforward to extend this to check for Kolibri running on any port (without having to add anything new). 

Resolving patch:
diff --git a/kolibri/utils/cli.py b/kolibri/utils/cli.py
--- a/kolibri/utils/cli.py
+++ b/kolibri/utils/cli.py
@@ -432,6 +432,12 @@ def start(port, background):
     Start the server on given port.
     """
 
+    serve_http = OPTIONS["Server"]["CHERRYPY_START"]
+
+    if serve_http:
+        # Check if the port is occupied
+        check_other_kolibri_running(port)
+
     create_startup_lock(port)
 
     # Check if the content directory exists when Kolibri runs after the first time.
@@ -445,8 +451,6 @@ def start(port, background):
     if sys.platform == "darwin":
         background = False
 
-    serve_http = OPTIONS["Server"]["CHERRYPY_START"]
-
     if not background:
         logger.info("Running Kolibri")
 
@@ -454,8 +458,6 @@ def start(port, background):
         logger.info("Running Kolibri as background process")
 
     if serve_http:
-        # Check if the port is occupied
-        check_other_kolibri_running(port)
 
         __, urls = server.get_urls(listen_port=port)
         if not urls:


Test patch:
Repository: learningequality/kolibri

Issue:
Display the Python version where Kolibri server is running
### Observed behavior
During the testing it's good to know on what Python version i'm running on the Kolibri server, This also helpful when it comes on reporting and debugging an issue.

Some operating Systems had a multiple pre installed Python version, and it's difficult to pinpoint on what version that Kolibri use to run.

### Expected behavior
I expect to display the Python version at the Device info page or at the kolibri benchmark command output.

### User-facing consequences
<!--
Implications and real-world consequences for learners, coaches, admins, and other users of the application
-->

…

### Errors and logs
<!--
Relevant logs from:
 * the command line
 * ~/.kolibri/logs/kolibri.txt
 * the browser console

Please wrap errors in triple backticks for clean formatting like this:
```
01:10 info: something happened
01:12 error: something bad happened
```
-->

…

### Steps to reproduce
<!--
Precise steps that someone else can follow in order to see this behavior
-->

…

### Context
<!--
Tell us about your environment, including:
 * Kolibri version
 * Operating system
 * Browser
-->

…



Discussion:
cc @jredrejo as the `benchmark` command is his baby :wink: 
Thanks, I will take care of adding it

Resolving patch:
diff --git a/kolibri/core/device/api.py b/kolibri/core/device/api.py
--- a/kolibri/core/device/api.py
+++ b/kolibri/core/device/api.py
@@ -1,3 +1,5 @@
+from sys import version_info
+
 from django.conf import settings
 from django.http.response import HttpResponseBadRequest
 from morango.models import InstanceIDModel
@@ -103,7 +105,9 @@ def get(self, request, format=None):
         # Returns the named timezone for the server (the time above only includes the offset)
         info["server_timezone"] = settings.TIME_ZONE
         info["installer"] = installation_type()
-
+        info["python_version"] = "{major}.{minor}.{micro}".format(
+            major=version_info.major, minor=version_info.minor, micro=version_info.micro
+        )
         return Response(info)
 
 


Test patch:
Repository: learningequality/kolibri

Issue:
Importing more content (or deleting resources) to a channel undoes its original position in channel list
<!--
Instructions:
 * Fill out the sections below, replace …'s with information about your issue
 * Use the 'preview' function above this text box to verify formatting before submitting
-->

### Observed behavior

~Similar to #5292, if you import more content to a channel, it will always be moved to the bottom of the Device > Channel page even if you had given it a different order (or didn't reorder it but just imported it in the past at some point). Because a lot of places in the app use the same order, we also see #5292~

Edit: This has been resolved for Kolibri when using Sqlite, but when using Postgresl, what seems to happen is that the newly modified channel goes to the _top_ of the list. It's because the channel in this case falls into this branch:

https://github.com/learningequality/kolibri/blob/0ee38838e5fc74d1f85b15c867f53ec4c261448c/kolibri/core/content/utils/annotation.py#L479-L482

~A somewhat mitigating factor is that newly updated channels will temporarily be moved to the top of the channel and have a green "New" label attached to it, so it will be easy to find immediately after the import.~

### Expected behavior

Updating a channel doesn't move it to the ~"bottom"~ top of the channel list.

### User-facing consequences

1. Users will need to move the channel again
1. Users might not immediately realize the channel moved 

### Errors and logs
<!--
Relevant logs from:
 * the command line
 * ~/.kolibri/logs/kolibri.txt
 * the browser console

Please wrap errors in triple backticks for clean formatting like this:
```
01:10 info: something happened
01:12 error: something bad happened
```
-->

…

### Steps to reproduce
1. Run Kolibri using Postgresql as DB
1. Run a similar scenario as described above

### Context
Kolibri 0.13


Discussion:

Resolving patch:
diff --git a/kolibri/core/content/utils/annotation.py b/kolibri/core/content/utils/annotation.py
--- a/kolibri/core/content/utils/annotation.py
+++ b/kolibri/core/content/utils/annotation.py
@@ -478,6 +478,8 @@ def calculate_next_order(channel, model=ChannelMetadata):
     latest_order = model.objects.latest("order").order
     if latest_order is None:
         channel.order = 1
-    else:
+
+    if channel.order is None or channel.order == 0:
         channel.order = latest_order + 1
+
     channel.save()


Test patch:
Repository: learningequality/kolibri

Issue:
Database is open while the server is idle
### Observed behavior
After kolibri starts, the db is kept open, with the journal file created, even if the server is idle, not receiving any query. This has produced corruptions in the db in the past.

### Expected behavior
Once the server starts, the db should be closed and not journal should appear while there are not requests  nor jobs happening.

### User-facing consequences

Possible corruption of the main db


### Steps to reproduce

1. Start Kolibri
2. don't do any request 
3. check the files db.sqlite3-wal and db.sqlite3-shm exist in the kolibri folder.

### Context

Tell us about your environment, including:
 * Kolibri version 0.13.0 
 * Linux





Discussion:

Resolving patch:
diff --git a/kolibri/utils/sanity_checks.py b/kolibri/utils/sanity_checks.py
--- a/kolibri/utils/sanity_checks.py
+++ b/kolibri/utils/sanity_checks.py
@@ -128,10 +128,12 @@ def check_database_is_migrated():
     is in a proper state to be used. This must only be run after django initialization.
     """
     apps.check_apps_ready()
+    from django.db import connection
     from morango.models import InstanceIDModel
 
     try:
         InstanceIDModel.get_or_create_current_instance()[0]
+        connection.close()
         return
     except OperationalError:
         try:


Test patch:
Repository: learningequality/kolibri

Issue:
cannot change device language to 'browser default'

### Observed behavior

Trying to set the default device language as 'Browser default' does not work:

![image](https://user-images.githubusercontent.com/2367265/74486514-f1030780-4e71-11ea-8538-d71dd1d2e20c.png)


### Expected behavior

Setting should work or be removed

### User-facing consequences

broken behavior in device settings

### Errors and logs

* Request URL: `http://localhost:8000/api/device/devicesettings/`
* Request Method: `PATCH`
* Status Code: `400 Bad Request`
* Response: `language_id`

### Steps to reproduce

Try to set language to browser default

### Context

0.13.1 beta 2
mac
devserver



Discussion:
My guess would be that we need to mark this field as nullable on the serializer. 
It's actually failing at the validation from language_id validation here https://github.com/learningequality/kolibri/blob/73ae3e3066128bda2297ea00cf5be32bb4af7928/kolibri/core/device/serializers.py#L36-L44

When language_id is null, it's not passing the `check_for_language`, but I don't see that custom validation error in the logs or response.

If I add a branch to pass through `language_id = None`, it seems to work. The `DeviceSettingModel` already allows blank and null language_id
> If I add a branch to pass through `language_id = None`, it seems to work. The `DeviceSettingModel` already allows blank and null language_id

Yeah, this is how the old DeviceLanguageSettingViewset worked (pass through None values). https://github.com/learningequality/kolibri/commit/c256321225d7231fcbeaad13b3f66063055873ac#diff-5c2a74fbedf7ad859adad5b2f40bf5a2L133

Resolving patch:
diff --git a/kolibri/core/device/serializers.py b/kolibri/core/device/serializers.py
--- a/kolibri/core/device/serializers.py
+++ b/kolibri/core/device/serializers.py
@@ -38,7 +38,7 @@ def validate_language_id(self, language_id):
         """
         Check that the language_id is supported by Kolibri
         """
-        if not check_for_language(language_id):
+        if language_id is not None and not check_for_language(language_id):
             raise serializers.ValidationError(_("Language is not supported by Kolibri"))
         return language_id
 


Test patch:
Repository: learningequality/kolibri

Issue:
"Channel name unavailable" after bulk import
### Observed behavior

This appears to be a regression of https://github.com/learningequality/kolibri/issues/6175

Noticed that when an import actually completes, the channel shows up.

![2020-03-02 14 00 08](https://user-images.githubusercontent.com/2367265/75722351-e5e01200-5c8e-11ea-8487-e9839c721b74.gif)


### Expected behavior

All channel names should show after initiating a bulk import. 

Additionally, if the task manager is opened by another user in another browser or device, they should also see the names of any waiting or in-progress bulk imports.

### User-facing consequences

Confusing behavior in task manager

### Errors and logs

None

### Steps to reproduce

Using the bulk import function, queue up a few channels and let er rip.

### Context

* 0.13.1
* Windows 10



Discussion:
I don't think this is a regression unless the channel name _never_ appears (even after the import starts) which is what was fixed originally.

When the Tasks are queued, we don't have the name available instantly, but rather have to wait until we have completed downloading the channel metadata DB from the remote source. Until that point all we have is the Channel ID.

Resolving patch:
diff --git a/kolibri/core/tasks/api.py b/kolibri/core/tasks/api.py
--- a/kolibri/core/tasks/api.py
+++ b/kolibri/core/tasks/api.py
@@ -68,7 +68,9 @@ def validate_content_task(request, task_description, require_channel=False):
     except KeyError:
         raise serializers.ValidationError("The channel_ids field is required.")
 
-    channel_name = get_channel_name(channel_id, require_channel)
+    channel_name = task_description.get(
+        "channel_name", get_channel_name(channel_id, require_channel)
+    )
 
     node_ids = task_description.get("node_ids", None)
     exclude_node_ids = task_description.get("exclude_node_ids", None)


Test patch:
Repository: learningequality/kolibri

Issue:
birth year is a required field

### Observed behavior

When importing users without a birth year specified, I see

```
1	BIRTH_YEAR		Not a valid 'BIRTH_YEAR'
2	BIRTH_YEAR		Not a valid 'BIRTH_YEAR'
```


### Expected behavior

`BIRTH_YEAR` should be optional

### User-facing consequences

Some users will not be imported



### Steps to reproduce

* Export users without birth year
* import them

### Context

profuturo branch


Discussion:

Resolving patch:
diff --git a/kolibri/core/auth/management/commands/bulkimportusers.py b/kolibri/core/auth/management/commands/bulkimportusers.py
--- a/kolibri/core/auth/management/commands/bulkimportusers.py
+++ b/kolibri/core/auth/management/commands/bulkimportusers.py
@@ -82,13 +82,15 @@
 # Validators ###
 
 
-def number_range(min, max):
+def number_range(min, max, allow_null=False):
     """
     Return a value check function which raises a ValueError if the supplied
     value is less than `min` or greater than `max`.
     """
 
     def checker(v):
+        if allow_null and not v:
+            return checker
         if int(v) < min or int(v) > max:
             raise ValueError(v)
 
@@ -299,7 +301,7 @@ def csv_values_validation(self, reader, header_translation):
         )
         validator.add_check(
             "BIRTH_YEAR",
-            number_range(1900, 99999),
+            number_range(1900, 99999, allow_null=True),
             MESSAGES[INVALID].format("BIRTH_YEAR"),
         )
         validator.add_check(


Test patch: