internlm/SWE-Fixer-Train-110K huggingface dataset:
Repository: openfun/richie

Issue:
Improve Organization list look
## Feature Request

Currently this page is just a raw list inside default "fullwidth" template.

**Describe the solution you'd like**
It should have a better look using possibly "card" list, maybe something like the course glimpses but as horizontal flux since organization logo would not fit well in a vertical flux like course glimpses.

**Describe alternatives you've considered**
A simple list with some work on padding and font size but it would not be as pretty as cards.



Discussion:

Resolving patch:
diff --git a/sandbox/settings.py b/sandbox/settings.py
--- a/sandbox/settings.py
+++ b/sandbox/settings.py
@@ -280,6 +280,7 @@ class Base(DRFMixin, ElasticSearchMixin, Configuration):
     CMS_TEMPLATES = (
         ("courses/cms/course_detail.html", _("Course page")),
         ("courses/cms/course_run_detail.html", _("Course run page")),
+        ("courses/cms/organization_list.html", _("Organization list")),
         ("courses/cms/organization_detail.html", _("Organization page")),
         ("courses/cms/category_detail.html", _("Category page")),
         ("persons/cms/person_detail.html", _("Person page")),
diff --git a/src/richie/apps/core/management/commands/create_demo_site.py b/src/richie/apps/core/management/commands/create_demo_site.py
--- a/src/richie/apps/core/management/commands/create_demo_site.py
+++ b/src/richie/apps/core/management/commands/create_demo_site.py
@@ -72,7 +72,7 @@
         "in_navigation": True,
         "kwargs": {
             "reverse_id": Organization.ROOT_REVERSE_ID,
-            "template": "richie/child_pages_list.html",
+            "template": "courses/cms/organization_list.html",
         },
     },
     "persons": {


Test patch:
Repository: openfun/richie

Issue:
Simple text input doesn't allow links to set target
## Feature Request

**Is your feature request related to a problem or unsupported use case? Please describe.**
When adding a simple text widget a course page, the only options available to create a link are the ones described in the image:
![Screenshot from 2022-08-17 10-42-30](https://user-images.githubusercontent.com/34194007/186388553-381dccec-2c78-48c6-b333-8c7671666583.png)

Richie doesn't allow us to define a link target inside a simple text widget.

**Describe the solution you'd like**
Links should allow us to set a target, like other link widgets available on Richie. Links with `target="_blank"` should be set in context. The default would continue to open the link on the same window.

**Do you want to work on it through a Pull Request?**
Yes



Discussion:
@sandroscosta so this could be a question of configuration of CKEditor?
I haven't invested enough time looking into a possible solution, but would say this is related with CKEditor. If it is something we can just "switch on", it might be an easy fix.
It is related with the CKEditor, the  `RICHIE_SIMPLETEXT_CONFIGURATION` uses the `CKEDITOR_LIMITED_CONFIGURATION` or `CKEDITOR_BASIC_CONFIGURATION` for the course fields. Only the `maincontent` uses the default `CKEDITOR_SETTINGS`.
So, if we try to edit the main content on, for example, the homepage it's possible to edit the link and change the target.
![image](https://user-images.githubusercontent.com/67018/187550877-ceecd49c-6a98-4224-9095-58b4c7d942b1.png)
![image](https://user-images.githubusercontent.com/67018/187550903-78d38755-cf51-464f-be52-fb00177626d8.png)


Resolving patch:
diff --git a/src/richie/apps/courses/settings/__init__.py b/src/richie/apps/courses/settings/__init__.py
--- a/src/richie/apps/courses/settings/__init__.py
+++ b/src/richie/apps/courses/settings/__init__.py
@@ -434,7 +434,7 @@ def richie_placeholder_conf(name):
     "toolbarCanCollapse": False,
     "contentsCss": "/static/css/ckeditor.css",
     # Only enable following tag definitions
-    "allowedContent": ["p", "b", "i", "a[href]"],
+    "allowedContent": ["p", "b", "i", "a[href,target]"],
     # Enabled showblocks as default behavior
     "startupOutlineBlocks": True,
     # Default toolbar configurations for djangocms_text_ckeditor


Test patch:
Repository: openfun/richie

Issue:
Frontend feature flags
## Feature Request

**Is your feature request related to a problem or unsupported use case? Please describe.**
We use feature flags configurable through environment variable to show/hide next features. Currently, those flags are only accessible by the backend. Those feature flags should be accessible by the frontend.

**Describe the solution you'd like**
We should bind FEATURES settings into the Richie frontend context through the web_processors.

**Do you want to work on it through a Pull Request?**
Yup



Discussion:

Resolving patch:
diff --git a/src/richie/apps/core/context_processors.py b/src/richie/apps/core/context_processors.py
--- a/src/richie/apps/core/context_processors.py
+++ b/src/richie/apps/core/context_processors.py
@@ -120,6 +120,10 @@ def site_metas(request: HttpRequest):
             for lms in getattr(settings, "RICHIE_LMS_BACKENDS", [])
         ]
 
+    context["FRONTEND_CONTEXT"]["context"]["features"] = getattr(
+        settings, "FEATURES", {}
+    )
+
     context["FRONTEND_CONTEXT"] = json.dumps(context["FRONTEND_CONTEXT"])
 
     if getattr(settings, "RICHIE_MINIMUM_COURSE_RUNS_ENROLLMENT_COUNT", None):


Test patch:
diff --git a/src/frontend/js/utils/test/factories/richie.ts b/src/frontend/js/utils/test/factories/richie.ts
--- a/src/frontend/js/utils/test/factories/richie.ts
+++ b/src/frontend/js/utils/test/factories/richie.ts
@@ -75,12 +75,13 @@ export const FonzieUserFactory = factory<User>(() => ({
 }));
 
 export const RichieContextFactory = factory<CommonDataProps['context']>(() => ({
-  csrftoken: faker.string.alphanumeric(64),
-  environment: 'test',
   authentication: {
     backend: APIBackend.OPENEDX_HAWTHORN,
     endpoint: 'https://endpoint.test',
   },
+  csrftoken: faker.string.alphanumeric(64),
+  environment: 'test',
+  features: {},
   lms_backends: [
     {
       backend: APIBackend.DUMMY,
diff --git a/tests/apps/core/test_pages.py b/tests/apps/core/test_pages.py
--- a/tests/apps/core/test_pages.py
+++ b/tests/apps/core/test_pages.py
@@ -85,7 +85,8 @@ def test_pages_i18n_hreflang(self):
         ]
     )
     @override_settings(
-        WEB_ANALYTICS={"google_universal_analytics": {"tracking_id": "TRACKING_ID"}}
+        FEATURES={"FEATURE_FLAG": True},
+        WEB_ANALYTICS={"google_universal_analytics": {"tracking_id": "TRACKING_ID"}},
     )
     def test_page_includes_frontend_context(self):
         """
@@ -123,3 +124,8 @@ def test_page_includes_frontend_context(self):
             response,
             r"\u0022web_analytics_providers\u0022: \u0022[\u005C\u0022google_universal_analytics\u005C\u0022]\u0022,",  # noqa pylint: disable=line-too-long
         )
+
+        self.assertContains(
+            response,
+            r"\u0022features\u0022: {\u0022FEATURE_FLAG\u0022: true}",  # noqa pylint: disable=line-too-long
+        )
Repository: openfun/richie

Issue:
Cookiecutter bootstrap failure
## Bug Report

**Problematic Behavior**
The `nightly round` job warns us that there is a problem with cookiecutter template.

**Additional context/Screenshots**
[Add any other context about the problem here. If applicable, add screenshots to help explain.](https://app.circleci.com/pipelines/github/openfun/richie/6840/workflows/7b6bd5f9-e2d4-4ef1-8e54-4562a521d50d/jobs/183180)



Discussion:

Resolving patch:
diff --git a/cookiecutter/{{cookiecutter.organization}}-richie-site-factory/template/{{cookiecutter.site}}/src/backend/{{cookiecutter.site}}/urls.py b/cookiecutter/{{cookiecutter.organization}}-richie-site-factory/template/{{cookiecutter.site}}/src/backend/{{cookiecutter.site}}/urls.py
--- a/cookiecutter/{{cookiecutter.organization}}-richie-site-factory/template/{{cookiecutter.site}}/src/backend/{{cookiecutter.site}}/urls.py
+++ b/cookiecutter/{{cookiecutter.organization}}-richie-site-factory/template/{{cookiecutter.site}}/src/backend/{{cookiecutter.site}}/urls.py
@@ -11,10 +11,7 @@
 from django.views.static import serve
 
 from cms.sitemaps import CMSSitemap
-from richie.apps.courses.urls import (
-    redirects_urlpatterns as courses_redirects_urlpatterns,
-    urlpatterns as courses_urlpatterns,
-)
+from richie.apps.courses.urls import urlpatterns as courses_urlpatterns
 from richie.apps.search.urls import urlpatterns as search_urlpatterns
 from richie.plugins.urls import urlpatterns as plugins_urlpatterns
 


Test patch:
Repository: openfun/richie

Issue:
Frontend - Rename teacher dashboard menu entry
## Feature Request

**Is your feature request related to a problem or unsupported use case? Please describe.**
Currently, we name the dashboard dedicated to manage trainings "teacher dashboard". After a demonstration, it appears this term is weird as other user than teacher have to use this dashboard (university members, course leaders...). 
 
**Describe the solution you'd like**
We should rename this entry by something like "Administration dashboard" or "Training dashboard" ?

Furthermore, we could display this entry apart from other to explicitly show this is an extra entry not available to all users.


Discussion:
We could isolate this menu item at the beginning  of the list like
![main_menyu](https://github.com/openfun/richie/assets/139848/ede04758-89be-4491-8e8e-cfd65d72a367)

I'll just put it below instead of above entries
I wanted to keep logout as the last entry, that's why i proposed it on top.
Ok right !

Resolving patch:
diff --git a/sandbox/settings.py b/sandbox/settings.py
--- a/sandbox/settings.py
+++ b/sandbox/settings.py
@@ -284,7 +284,7 @@ class Base(StyleguideMixin, DRFMixin, RichieCoursesConfigurationMixin, Configura
                 "href": _("/dashboard/"),
             },
             "dashboard_teacher": {
-                "label": _("Teacher dashboard"),
+                "label": _("Course administration"),
                 "href": _("/dashboard/teacher"),
             },
         }


Test patch:
Repository: stb-tester/stb-tester

Issue:
Pipeline flush causes intermittent long teardown with live source
fadfe6e added a flush during pipeline teardown, to avoid what we call "long teardown" with _non-live_ sources like filesrc -- the pipeline doesn't actually get the EOS within 10 seconds so stbt times out and exits forcefully.

Unfortunately this caused a live v4l source (real video-capture hardware) to always suffer from long teardown.

e051ba8 changed the order of sending eos vs. flush_stop, for an unrelated reason (to fix an intermittent long teardown found with a non-live source in our self-tests). This commit also improved the long teardown with our live source, from 100% of test runs to ~2% of test runs. I did a manual bisection (this table goes from oldest commit at the top to newest commit at the bottom):

| Commit | Long teardowns / total test runs |
| --- | --- |
| 0.19.1-62-g31eddf9 | 0/1953 |
| 0.19.1-63-gfadfe6e: Fix ungraceful teardowns (with delays) with non-live sources | 25/25 |
| ... | ... |
| 0.19.1-79-g12b7928 | 10/10 |
| 0.19-1-80-ge051ba8: Display teardown: Fix race condition in flushing logic | 33/1678 |

**TODO:**
- [x] Decide whether we want to keep the improved behaviour for non-live sources, or revert both fadfe6e and e051ba8.
- [ ] Revert fadfe6e and e051ba8.



Discussion:

Resolving patch:
diff --git a/stbt.py b/stbt.py
--- a/stbt.py
+++ b/stbt.py
@@ -1664,9 +1664,7 @@ def teardown(self):
         self.source_pipeline, source = None, self.source_pipeline
         if source:
             for elem in gst_iterate(source.iterate_sources()):
-                elem.send_event(Gst.Event.new_flush_start())
                 elem.send_event(Gst.Event.new_eos())
-                elem.send_event(Gst.Event.new_flush_stop(False))
             if not self.appsink_await_eos(
                     source.get_by_name('appsink'), timeout=10):
                 debug("teardown: Source pipeline did not teardown gracefully")


Test patch:
diff --git a/tests/test-stbt-run.sh b/tests/test-stbt-run.sh
--- a/tests/test-stbt-run.sh
+++ b/tests/test-stbt-run.sh
@@ -97,14 +97,3 @@ test_that_stbt_run_exits_on_ctrl_c() {
     ! grep -q "No beer left" beer.txt || fail "Test script should not have completed"
     [ "$exit_status" != "0" ] || fail "Unexpected return code $exit_status"
 }
-
-# A regression test
-test_that_stbt_run_exits_gracefully_with_non_live_sources() {
-    cat > test.py <<-EOF
-	wait_for_match("$testdir/videotestsrc-gamut.png", timeout_secs=1)
-	EOF
-    stbt run -v --source-pipeline="videotestsrc" test.py >log.log 2>&1
-
-    ! grep -q "Source pipeline did not teardown gracefully" log.log ||
-        fail "Source pipeline did not teardown gracefully"
-}
Repository: stb-tester/stb-tester

Issue:
Bad error message when matching non-BGR images
``` python
def _match(image, template, match_parameters, template_name):
    if any(image.shape[x] < template.shape[x] for x in (0, 1)):
        raise ValueError("Source image must be larger than template image")
    if any(template.shape[x] < 1 for x in (0, 1)):
        raise ValueError("Template image must contain some data")
    if template.shape[2] != 3:
        raise ValueError("Template image must be 3 channel BGR")
```

The final `if` causes an `IndexError` with single-channel images because the image `shape` is `(y, x)` not the assumed `(y, x, c)`. The result is that the purposefully placed error message about the required image types does not get raised.



Discussion:
I guess that should read `if len(template.shape) != 3 or template.shape[2] != 3:`.  Do you have a test case?  How did you come across this issue?

> Do you have a test case? How did you come across this issue?

I don't have a test case - I just was trying to get a fiddly bit of transparent navigation to work (which involved pre-processing frame and template) which resulted in passing in a greyscale (single channel) template into `stbt.match`. I think you could synthesise it with something like this:

``` python
im = numpy.zeros(shape=(10, 10), dtype=numpy.uint8)
try:
    stbt.match(im)
except ValueError as e:
    assert "Template image must be 3 channel BGR" in str(e)
```


Resolving patch:
diff --git a/_stbt/core.py b/_stbt/core.py
--- a/_stbt/core.py
+++ b/_stbt/core.py
@@ -1674,7 +1674,7 @@ def _match(image, template, match_parameters, template_name):
         raise ValueError("Source image must be larger than template image")
     if any(template.shape[x] < 1 for x in (0, 1)):
         raise ValueError("Template image must contain some data")
-    if template.shape[2] != 3:
+    if len(template.shape) != 3 or template.shape[2] != 3:
         raise ValueError("Template image must be 3 channel BGR")
     if template.dtype != numpy.uint8:
         raise ValueError("Template image must be 8-bits per channel")


Test patch:
diff --git a/tests/test_match.py b/tests/test_match.py
--- a/tests/test_match.py
+++ b/tests/test_match.py
@@ -1,6 +1,9 @@
+import cv2
 import numpy
+from nose.tools import raises
 
 import stbt
+from _stbt.core import _load_template
 
 
 def black(width=1280, height=720):
@@ -18,3 +21,9 @@ def test_that_matchresult_str_image_matches_template_passed_to_match():
 def test_that_matchresult_str_image_matches_template_passed_to_match_custom():
     assert "image=<Custom Image>" in str(
         stbt.match(black(30, 30), frame=black()))
+
+
+@raises(ValueError)
+def test_that_match_rejects_greyscale_template():
+    grey = cv2.cvtColor(_load_template("black.png").image, cv2.cv.CV_BGR2GRAY)
+    stbt.match(grey, frame=black())
Repository: stb-tester/stb-tester

Issue:
match_text doesn't produce debug output
SUMMARY
There is no debug output from match_text, even in verbose mode. This is inconsistent with other stbt functions like match.

STEPS TO REPRODUCE
  assert stbt.match_text(“Some Text”)

EXPECTED RESULTS
  stbt-run: No match found: 'Some Text'
  stbt-run: No match found: 'Some Text'
or
  stbt-run: Match found: 'Some Text' Region(x=532, y=446, width=127, height=31)

ACTUAL RESULTS
  Nothing, other than the assert if it fails.



Discussion:
slight amendment to the steps to reproduce above..

STEPS TO REPRODUCE
  stbt run --verbose assert stbt.match_text(“Some Text”)


Resolving patch:
diff --git a/_stbt/core.py b/_stbt/core.py
--- a/_stbt/core.py
+++ b/_stbt/core.py
@@ -875,22 +875,30 @@ def match_text(self, text, frame=None, region=Region.ALL,
         xml, region = _tesseract(frame, region, mode, lang, _config,
                                  user_words=text.split())
         if xml == '':
-            return TextMatchResult(ts, False, None, frame, text)
-        hocr = lxml.etree.fromstring(xml)
-        p = _hocr_find_phrase(hocr, text.split())
-        if p:
-            # Find bounding box
-            box = None
-            for _, elem in p:
-                box = _bounding_box(box, _hocr_elem_region(elem))
-            # _tesseract crops to region and scales up by a factor of 3 so we
-            # must undo this transformation here.
-            box = Region.from_extents(
-                region.x + box.x // 3, region.y + box.y // 3,
-                region.x + box.right // 3, region.y + box.bottom // 3)
-            return TextMatchResult(ts, True, box, frame, text)
+            result = TextMatchResult(ts, False, None, frame, text)
         else:
-            return TextMatchResult(ts, False, None, frame, text)
+            hocr = lxml.etree.fromstring(xml)
+            p = _hocr_find_phrase(hocr, text.split())
+            if p:
+                # Find bounding box
+                box = None
+                for _, elem in p:
+                    box = _bounding_box(box, _hocr_elem_region(elem))
+                # _tesseract crops to region and scales up by a factor of 3 so
+                # we must undo this transformation here.
+                box = Region.from_extents(
+                    region.x + box.x // 3, region.y + box.y // 3,
+                    region.x + box.right // 3, region.y + box.bottom // 3)
+                result = TextMatchResult(ts, True, box, frame, text)
+            else:
+                result = TextMatchResult(ts, False, None, frame, text)
+
+        if result.match:
+            debug("match_text: Match found: %s" % str(result))
+        else:
+            debug("match_text: No match found: %s" % str(result))
+
+        return result
 
     def frames(self, timeout_secs=None):
         return self._display.frames(timeout_secs)


Test patch:
Repository: stb-tester/stb-tester

Issue:
irnetbox.py does not support "double signals" config files
Files generated by RedRat irnetbox signal utility cannot be correctly parsed if they are of the "double signals" variety.
Update irnetbox.py for double signals configs (issue #413)
Add the ability to parse RedRat irnetbox config files with "double signals".


Discussion:

Resolving patch:
diff --git a/_stbt/irnetbox.py b/_stbt/irnetbox.py
--- a/_stbt/irnetbox.py
+++ b/_stbt/irnetbox.py
@@ -280,19 +280,23 @@ def _parse_config(config_file):
     """Read irNetBox configuration file.
 
     Which is produced by RedRat's (Windows-only) "IR Signal Database Utility".
-
-    This doesn't support config files with "double signals" (where 2 different
-    signals were recorded from alternate presses of the same button on the
-    remote control unit).
     """
     d = {}
     for line in config_file:
-        fields = re.split("[\t ]+", line.rstrip(), maxsplit=3)
+        fields = re.split("[\t ]+", line.rstrip(), maxsplit=4)
         if len(fields) == 4:
             # (name, type, max_num_lengths, data)
             name, type_, _, data = fields
             if type_ == "MOD_SIG":
                 d[name] = binascii.unhexlify(data)
+        if len(fields) == 5:
+            # "Double signals" where pressing the button on the remote control
+            # alternates between signal1 & signal2. We'll always send signal1,
+            # but that shouldn't matter.
+            # (name, type, signal1 or signal2, max_num_lengths, data)
+            name, type_, signal, _, data = fields
+            if type_ == "DMOD_SIG" and signal == "signal1":
+                d[name] = binascii.unhexlify(data)
     return d
 
 
@@ -333,10 +337,14 @@ def test_that_parse_config_understands_redrat_format():
             DOWN	MOD_SIG	16 000174F5FF60000000060000004802450222F704540D12116A464F0000000000000000000000000000000000000000000102020202020202020202020202020202020202020202020202030202020202020202020202030202020202020203020202030203020202030203020302020203027F0004027F
 
             UP	MOD_SIG	16 000174FAFF60000000050000004803457422F7045A0D13116A00000000000000000000000000000000000000000000000102020202020202020202020202020202020202020202020202030202020202020203020202020202020202020203020202020203020302030203020302020203027F0004027F
+
+            RED	DMOD_SIG	signal1	16 0002BCAFFF5A0000000300000024010E3206E60DB1000000000000000000000000000000000000000000000000000000010101010200020002000200020101017F00010101010200020002000200020101017F
+            RED	DMOD_SIG	signal2	16 0002BCE3FF5A0000000300000020010E2C0DB006EC00000000000000000000000000000000000000000000000000000001000100010001000100010202027F0001000100010001000100010202027F
             """))
     config = _parse_config(f)
     assert config["DOWN"].startswith("\x00\x01\x74\xF5")
     assert config["UP"].startswith("\x00\x01\x74\xFA")
+    assert config["RED"].startswith("\x00\x02\xBC\xAF")
 
 
 class _FileToSocket(object):


Test patch:
Repository: stb-tester/stb-tester

Issue:
stbt.Image.__repr__ breaks after numpy operations like `max()`
`stbt.Image` is a sub-class of `numpy.ndarray`. It implements `__new__` and `__array_finalize__` in such a way that operations like slicing still return `stbt.Image` (instead of a plain `numpy.ndarray)`. The problem is that this even applies to operations like `max()`.

`max()` returns a `numpy.uint8` instead of a native Python int. When called on a `stbt.Image`, `max()` returns a `stbt.Image` with `shape=()`. This breaks `__repr__()`:

```
>>> img = stbt.load_image("...")
>>> print(img.max())
[...]
_stbt/imgutils.py in __repr__(self)
--> 121             dimensions = "%dx%d" % (self.shape[1], self.shape[0])
IndexError: tuple index out of range
```




Discussion:

Resolving patch:
diff --git a/_stbt/imgutils.py b/_stbt/imgutils.py
--- a/_stbt/imgutils.py
+++ b/_stbt/imgutils.py
@@ -53,8 +53,10 @@ def __repr__(self):
         if len(self.shape) == 3:
             dimensions = "%dx%dx%d" % (
                 self.shape[1], self.shape[0], self.shape[2])
-        else:
+        elif len(self.shape) == 2:
             dimensions = "%dx%d" % (self.shape[1], self.shape[0])
+        else:
+            return super(Frame, self).__repr__()
         return "<Frame(time=%s, dimensions=%s)>" % (
             "None" if self.time is None else "%.3f" % self.time,
             dimensions)
@@ -126,8 +128,10 @@ def __repr__(self):
         if len(self.shape) == 3:
             dimensions = "%dx%dx%d" % (
                 self.shape[1], self.shape[0], self.shape[2])
-        else:
+        elif len(self.shape) == 2:
             dimensions = "%dx%d" % (self.shape[1], self.shape[0])
+        else:
+            return super(Image, self).__repr__()
         if (self.relative_filename is None or
                 self.relative_filename.startswith('../')):
             filename = self.absolute_filename


Test patch:
diff --git a/tests/test_core.py b/tests/test_core.py
--- a/tests/test_core.py
+++ b/tests/test_core.py
@@ -140,6 +140,16 @@ def test_that_load_image_with_nonexistent_image_raises_ioerror():
         stbt.load_image("idontexist.png")
 
 
+def test_that_image_and_frame_repr_can_print_numpy_scalar():
+    # Operations like `numpy.max` propagate the type of the input, so its
+    # output is still a `stbt.Image`.
+    f = stbt.Frame(numpy.zeros((720, 1280, 3), dtype=numpy.uint8))
+    assert repr(numpy.max(f)) == "Frame(0, dtype=uint8)"
+
+    img = stbt.load_image("action-panel.png")
+    assert repr(numpy.max(img)) == "Image(255, dtype=uint8)"
+
+
 def test_crop():
     img = stbt.load_image("action-panel.png")
     cropped = stbt.crop(img, stbt.Region(x=1045, y=672, right=1081, bottom=691))