dyyyyyyyy/swe-rebench-filtered-1150 huggingface dataset:
task: metadata: install: pip install -e .
patch: diff --git a/ignite/metrics/loss.py b/ignite/metrics/loss.py
index 0e9bf9e0..a8ddac9f 100644
--- a/ignite/metrics/loss.py
+++ b/ignite/metrics/loss.py
@@ -8,9 +8,21 @@ class Loss(Metric):
     """
     Calculates the average loss according to the passed loss_fn.
 
-    - `loss_fn` must return the average loss over all observations in the batch.
-    - `update` must receive output of the form `(y_pred, y)`.
+    Args:
+        loss_fn (callable): a callable taking a prediction tensor, a target
+            tensor, optionally other arguments, and returns the average loss
+            over all observations in the batch.
+        output_transform (callable): a callable that is used to transform the
+            :class:`ignite.engine.Engine`'s `process_function`'s output into the
+            form expected by the metric.
+            This can be useful if, for example, you have a multi-output model and
+            you want to compute the metric with respect to one of the outputs.
+            The output is is expected to be a tuple (prediction, target) or
+            (prediction, target, kwargs) where kwargs is a dictionary of extra
+            keywords arguments.
+
     """
+
     def __init__(self, loss_fn, output_transform=lambda x: x):
         super(Loss, self).__init__(output_transform)
         self._loss_fn = loss_fn
@@ -20,8 +32,12 @@ class Loss(Metric):
         self._num_examples = 0
 
     def update(self, output):
-        y_pred, y = output
-        average_loss = self._loss_fn(y_pred, y)
+        if len(output) == 2:
+            y_pred, y = output
+            kwargs = {}
+        else:
+            y_pred, y, kwargs = output
+        average_loss = self._loss_fn(y_pred, y, **kwargs)
         assert len(average_loss.shape) == 0, '`loss_fn` did not return the average loss'
         self._sum += average_loss.item() * y.shape[0]
         self._num_examples += y.shape[0]

problem_statement: [Feature Request] More general metrics
I find the metrics to be a bit limited as one might want to pass additional options (even tensors) to the loss.
For instance in recurrent models with different sequence lengths, one would use a mask to avoid counting errors on padded time steps.
The mask is necessary in the loss to know which outputs to use in the final averaging/ loss.
repo: pytorch/ignite
test_cmd: pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
test_patch: diff --git a/tests/ignite/metrics/test_loss.py b/tests/ignite/metrics/test_loss.py
index cc494d75..b5e7c59b 100644
--- a/tests/ignite/metrics/test_loss.py
+++ b/tests/ignite/metrics/test_loss.py
@@ -50,6 +50,15 @@ def test_non_averaging_loss():
         loss.update((y_pred, y))
 
 
+def test_kwargs_loss():
+    loss = Loss(nll_loss)
+
+    y_pred = torch.Tensor([[0.1, 0.4, 0.5], [0.1, 0.7, 0.2]]).log()
+    y = torch.LongTensor([2, 2])
+    loss.update((y_pred, y, {"weight": torch.Tensor([0, 0, 0])}))
+    assert_almost_equal(loss.compute(), 0)
+
+
 def test_reset():
     loss = Loss(nll_loss)
task: metadata: install: pip install -e .[dev]
patch: diff --git a/temba_client/utils.py b/temba_client/utils.py
index 39a3a2a..2489884 100644
--- a/temba_client/utils.py
+++ b/temba_client/utils.py
@@ -33,8 +33,11 @@ def parse_iso8601(value):
 
 def format_iso8601(value):
     """
-    Formats a datetime as a UTC ISO8601 date
+    Formats a datetime as a UTC ISO8601 date or returns None if value is None
     """
+    if value is None:
+        return None
+
     _format = ISO8601_DATETIME_FORMAT + '.%f'
 
     return six.text_type(value.astimezone(pytz.UTC).strftime(_format))

problem_statement: Null DatetimeField raises an exception upon serialisation request
Objects with DatetimeField attributes cannot be properly serialised when any of their DatetimeField attributes is not set (i.e. set to null in the JSON response).  This makes the following scenario possible:

1. fetch data from the server (e.g. TembaClient(...).get_runs()) - the data is internally deserialised by rapidpro-python
2. fed the result of this deserialisation process back to rapidpro-python to have it (re)serialised
3. error (please see the example traceback below)

```
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/ego/.virtualenvs/rapidpro-python/local/lib/python2.7/site-packages/temba_client/serialization.py", line 63, in serialize
    field_value = field.serialize(attr_value)
  File "/home/ego/.virtualenvs/rapidpro-python/local/lib/python2.7/site-packages/temba_client/serialization.py", line 148, in serialize
    return [self.item_class.serialize(item) for item in value]
  File "/home/ego/.virtualenvs/rapidpro-python/local/lib/python2.7/site-packages/temba_client/serialization.py", line 63, in serialize
    field_value = field.serialize(attr_value)
  File "/home/ego/.virtualenvs/rapidpro-python/local/lib/python2.7/site-packages/temba_client/serialization.py", line 122, in serialize
    return format_iso8601(value)
  File "/home/ego/.virtualenvs/rapidpro-python/local/lib/python2.7/site-packages/temba_client/utils.py", line 40, in format_iso8601
    return six.text_type(value.astimezone(pytz.UTC).strftime(_format))
AttributeError: 'NoneType' object has no attribute 'astimezone'
```
repo: rapidpro/rapidpro-python
test_cmd: pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
test_patch: diff --git a/temba_client/tests.py b/temba_client/tests.py
index d8386f7..e24f86a 100644
--- a/temba_client/tests.py
+++ b/temba_client/tests.py
@@ -72,6 +72,9 @@ class UtilsTest(TembaTest):
         d = datetime.datetime(2014, 1, 2, 3, 4, 5, 6, UtilsTest.TestTZ())
         self.assertEqual(format_iso8601(d), '2014-01-02T08:04:05.000006')
 
+    def test_format_iso8601_should_return_none_when_no_datetime_given(self):
+        self.assertIs(format_iso8601(None), None)
+
     def test_parse_iso8601(self):
         dt = datetime.datetime(2014, 1, 2, 3, 4, 5, 0, pytz.UTC)
         self.assertEqual(parse_iso8601('2014-01-02T03:04:05.000000Z'), dt)
task: metadata: install: pip install -e .[dev]
patch: diff --git a/src/dishka/dependency_source/make_factory.py b/src/dishka/dependency_source/make_factory.py
index d5a97cc..deb7280 100644
--- a/src/dishka/dependency_source/make_factory.py
+++ b/src/dishka/dependency_source/make_factory.py
@@ -433,6 +433,11 @@ def make_factory(
         is_in_class: bool,
         override: bool,
 ) -> Factory:
+    if get_origin(source) is ProvideMultiple:
+        if provides is None:
+            provides = source
+        source = get_args(source)[0]
+
     if is_bare_generic(source):
         source = source[get_type_vars(source)]  # type: ignore[index]
 

problem_statement: Unable to use provide_all with WithParents
Attempting to use provide_all with WithParents results in a `TypeError: Cannot use <class 'dishka.entities.provides_marker.ProvideMultiple'> as a factory.`

Example code:

```python
from abc import abstractmethod
from typing import Protocol

from dishka import Provider, Scope, WithParents, provide_all


class MyProtocol(Protocol):
    @abstractmethod
    def __call__(self, data: bytes) -> bytes: ...


class MyImpl(MyProtocol):
    def __call__(self, data: bytes) -> bytes: ...


class MyProvider(Provider):
    scope = Scope.REQUEST

    interactors = provide_all(WithParents[MyImpl])
```
repo: reagento/dishka
test_cmd: pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
test_patch: diff --git a/tests/unit/container/test_alias.py b/tests/unit/container/test_alias.py
index 1c69f61..1fdb615 100644
--- a/tests/unit/container/test_alias.py
+++ b/tests/unit/container/test_alias.py
@@ -67,6 +67,24 @@ def test_implicit():
     mock.assert_called_once()
 
 
+
+def test_implicit_no_source():
+    provider = Provider(scope=Scope.APP)
+    provider.provide_all(AnyOf[float, str])
+    container = make_container(provider)
+    assert container.get(float) == 0.0
+    assert container.get(str) == 0.0
+
+
+
+def test_implicit_all():
+    provider = Provider(scope=Scope.APP)
+    provider.provide_all(AnyOf[float, str])
+    container = make_container(provider)
+    assert container.get(float) == 0.0
+    assert container.get(str) == 0.0
+
+
 def test_implicit_generator():
     class MyProvider(Provider):
         value = 0
task: metadata: install: pip install -e .[dev]
patch: diff --git a/src/dishka/registry.py b/src/dishka/registry.py
index 7f9ff0e..db801e7 100644
--- a/src/dishka/registry.py
+++ b/src/dishka/registry.py
@@ -19,10 +19,10 @@ class Registry:
     def add_factory(self, factory: Factory):
         if is_generic(factory.provides.type_hint):
             origin = get_origin(factory.provides.type_hint)
-            origin_key = DependencyKey(origin, factory.provides.component)
-            self._factories[origin_key] = factory
-        else:
-            self._factories[factory.provides] = factory
+            if origin:
+                origin_key = DependencyKey(origin, factory.provides.component)
+                self._factories[origin_key] = factory
+        self._factories[factory.provides] = factory
 
     def get_factory(self, dependency: DependencyKey) -> Factory | None:
         try:

problem_statement: SqlAlchemy sessionmaker resolve failed
```python
AsyncSessionMaker = async_sessionmaker

class DbProvider(Provider):
    def __init__(self, connection_string: str | AnyUrl, *args, **kwargs) -> None:
        super().__init__(*args, **kwargs)
        self.connection_string = str(connection_string)

    @provide(scope=Scope.APP)
    async def get_engine(self) -> AsyncEngine:
        dsn = self.connection_string.replace("postgresql", "postgresql+asyncpg")
        return create_async_engine(dsn)

    @provide(scope=Scope.APP)
    async def get_sessionmaker(self, engine: AsyncEngine) -> AsyncSessionMaker:
        return async_sessionmaker(engine, class_=AsyncSession, expire_on_commit=False)

    @provide(scope=Scope.REQUEST)
    async def get_db_session(self, sessionmaker: AsyncSessionMaker) -> AsyncSession:
        return await get_or_create_db_session(sessionmaker)
```

```shell
dishka.exceptions.NoFactoryError: Cannot find factory for 
DependencyKey(type_hint=<class 'sqlalchemy.ext.asyncio.session.async_sessionmaker'>, component='')
requested by DependencyKey(type_hint=<class 'sqlalchemy.ext.asyncio.session.AsyncSession'>, component=''). 
It is missing or has invalid scope.```
repo: reagento/dishka
test_cmd: pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
test_patch: diff --git a/tests/unit/container/test_generic.py b/tests/unit/container/test_generic.py
index 68da0bb..054c06c 100644
--- a/tests/unit/container/test_generic.py
+++ b/tests/unit/container/test_generic.py
@@ -83,6 +83,20 @@ def test_generic_class():
     assert a.x == 42
 
 
+def test_bare_generic_method():
+    class MyProvider(Provider):
+        scope = Scope.APP
+
+        @provide
+        def a(self) -> A:
+            return A(42)
+
+    container = make_container(MyProvider())
+    a = container.get(A)
+    assert isinstance(a, A)
+    assert a.x == 42
+
+
 def test_generic_func():
     class MyProvider(Provider):
         scope = Scope.APP
task: metadata: install: pip install -e .
patch: diff --git a/.travis.yml b/.travis.yml
index eb1e3f6..59abe34 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -4,6 +4,7 @@ python:
   - "3.5"
   - "3.6"
   - "3.7"
+  - "3.8"
 # command to install dependencies
 install:
   - pip install tox-travis codecov
diff --git a/sqllineage/core.py b/sqllineage/core.py
index 0d7c505..a46e388 100644
--- a/sqllineage/core.py
+++ b/sqllineage/core.py
@@ -23,7 +23,8 @@ class LineageParser(object):
         self._stmt = [s for s in sqlparse.parse(sql.strip(), self._encoding) if s.token_first(skip_cm=True)]
         for stmt in self._stmt:
             if stmt.get_type() == "DROP":
-                self._target_tables -= {t.get_real_name() for t in stmt.tokens if isinstance(t, Identifier)}
+                for tables in (self._source_tables, self._target_tables):
+                    tables -= {t.get_real_name() for t in stmt.tokens if isinstance(t, Identifier)}
             else:
                 self._extract_from_token(stmt)
         self._tmp_tables = self._source_tables.intersection(self._target_tables)
diff --git a/tox.ini b/tox.ini
index 0fa8e74..9546285 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,5 +1,5 @@
 [tox]
-envlist = py35,py36,py37
+envlist = py35,py36,py37,py38
 
 [testenv]
 deps =

problem_statement: temp table checking
```sql
create table tab_a as select * from tab_b;
insert overwrite table tab_c select * from tab_a;
drop table tab_a;
```

Here tab_a is clearly a temp table, and yet it's marked as source table.
Possibly related to #29 #23 
repo: reata/sqllineage
test_cmd: pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
test_patch: diff --git a/tests/test_others.py b/tests/test_others.py
index ddc0c30..eabb6d4 100644
--- a/tests/test_others.py
+++ b/tests/test_others.py
@@ -31,6 +31,13 @@ def test_drop_after_create():
     helper("CREATE TABLE IF NOT EXISTS tab1 (col1 STRING);DROP TABLE IF EXISTS tab1", None, None)
 
 
+def test_drop_tmp_tab_after_create():
+    sql = """create table tab_a as select * from tab_b;
+insert overwrite table tab_c select * from tab_a;
+drop table tab_a;"""
+    helper(sql, {"tab_b"}, {"tab_c"})
+
+
 def test_create_select():
     helper("CREATE TABLE tab1 SELECT * FROM tab2", {"tab2"}, {"tab1"})
task: metadata: install: pip install -e .
patch: diff --git a/sqllineage/core.py b/sqllineage/core.py
index a46e388..1d9a021 100644
--- a/sqllineage/core.py
+++ b/sqllineage/core.py
@@ -4,7 +4,7 @@ import sys
 from typing import List, Set
 
 import sqlparse
-from sqlparse.sql import Comment, Function, Identifier, Parenthesis, Statement, TokenList
+from sqlparse.sql import Comment, Comparison, Function, Identifier, Parenthesis, Statement, TokenList
 from sqlparse.tokens import Keyword, Token
 
 SOURCE_TABLE_TOKENS = (r'FROM',
@@ -95,11 +95,17 @@ Target Tables:
                     # referring https://github.com/andialbrecht/sqlparse/issues/483 for further information
                     assert isinstance(sub_token.token_first(skip_cm=True), Identifier)
                     self._target_tables.add(sub_token.token_first(skip_cm=True).get_real_name())
-                    target_table_token_flag = False
+                elif isinstance(sub_token, Comparison):
+                    # create table tab1 like tab2, tab1 like tab2 will be parsed as Comparison
+                    # referring https://github.com/andialbrecht/sqlparse/issues/543 for further information
+                    assert isinstance(sub_token.left, Identifier)
+                    assert isinstance(sub_token.right, Identifier)
+                    self._target_tables.add(sub_token.left.get_real_name())
+                    self._source_tables.add(sub_token.right.get_real_name())
                 else:
                     assert isinstance(sub_token, Identifier)
                     self._target_tables.add(sub_token.get_real_name())
-                    target_table_token_flag = False
+                target_table_token_flag = False
             elif temp_table_token_flag:
                 if self.__token_negligible_before_tablename(sub_token):
                     continue

problem_statement: Support Create Table Like Statement
```
drop table  if exists tab_a;
create table if not exists tab_a like tab_b;
```
drop before create, the result is tab_a exists after the above statements;


If we switch the order:
```
create table if not exists tab_a like tab_b;
drop table  if exists tab_a;
```
Although the above statements make no sense, still, we should output result as tab_a does not exist.

Under current circumstances, both cases will be that tab_a does not exists since tab_a is identified as temp table. This is related to #23 
repo: reata/sqllineage
test_cmd: pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
test_patch: diff --git a/tests/test_others.py b/tests/test_others.py
index eabb6d4..a9405c8 100644
--- a/tests/test_others.py
+++ b/tests/test_others.py
@@ -14,6 +14,14 @@ def test_create_if_not_exist():
     helper("CREATE TABLE IF NOT EXISTS tab1 (col1 STRING)", None, {"tab1"})
 
 
+def test_create_as():
+    helper("CREATE TABLE tab1 AS SELECT * FROM tab2", {"tab2"}, {"tab1"})
+
+
+def test_create_like():
+    helper("CREATE TABLE tab1 LIKE tab2", {"tab2"}, {"tab1"})
+
+
 def test_create_after_drop():
     helper("DROP TABLE IF EXISTS tab1; CREATE TABLE IF NOT EXISTS tab1 (col1 STRING)", None, {"tab1"})
task: metadata: install: pip install -e .[dev]
patch: diff --git a/reframe/core/containers.py b/reframe/core/containers.py
index d108746b..15be3766 100644
--- a/reframe/core/containers.py
+++ b/reframe/core/containers.py
@@ -255,7 +255,7 @@ class Singularity(ContainerPlatform):
             run_opts.append('--nv')
 
         if self.workdir:
-            run_opts.append(f'-W {self.workdir}')
+            run_opts.append(f'--pwd {self.workdir}')
 
         run_opts += self.options
         if self.command:

problem_statement: The Singularity container platform doesn't change automatically to the mounted stage directory
In the Singularity container platform the change to the mounted `stage` directory is done with https://github.com/reframe-hpc/reframe/blob/0d2c11214c914584c754afffac360bfd3c3383f8/reframe/core/containers.py#L257-L258
but `-W` doesn't change the directory like docker or sarus. From `singularity --help`:
```
  -W, --workdir string         working directory to be used for /tmp,
                               /var/tmp and $HOME (if -c/--contain was
                               also used)
```
As a result the test doesn't start in the stage directory. 
repo: reframe-hpc/reframe
test_cmd: pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
test_patch: diff --git a/unittests/test_containers.py b/unittests/test_containers.py
index 6518781c..ea713465 100644
--- a/unittests/test_containers.py
+++ b/unittests/test_containers.py
@@ -104,15 +104,15 @@ def expected_cmd_mount_points(container_variant):
     elif container_variant in {'Singularity', 'Singularity+nopull'}:
         return ('singularity exec -B"/path/one:/one" '
                 '-B"/path/two:/two" -B"/foo:/rfm_workdir" '
-                '-W /rfm_workdir image:tag cmd')
+                '--pwd /rfm_workdir image:tag cmd')
     elif container_variant == 'Singularity+cuda':
         return ('singularity exec -B"/path/one:/one" '
                 '-B"/path/two:/two" -B"/foo:/rfm_workdir" --nv '
-                '-W /rfm_workdir image:tag cmd')
+                '--pwd /rfm_workdir image:tag cmd')
     elif container_variant == 'Singularity+nocommand':
         return ('singularity run -B"/path/one:/one" '
                 '-B"/path/two:/two" -B"/foo:/rfm_workdir" '
-                '-W /rfm_workdir image:tag')
+                '--pwd /rfm_workdir image:tag')
 
 
 @pytest.fixture
@@ -265,7 +265,7 @@ def expected_run_with_workdir(container_variant_noopt):
             '--foo image:tag cmd1'
         )
     elif container_variant_noopt == 'Singularity':
-        return ('singularity exec -B\"/foo:/rfm_workdir\" -W foodir '
+        return ('singularity exec -B\"/foo:/rfm_workdir\" --pwd foodir '
                 '--foo image:tag cmd1')
task: metadata: install: pip install -e .
patch: diff --git a/reframe/utility/__init__.py b/reframe/utility/__init__.py
index 12edb01e..a381abea 100644
--- a/reframe/utility/__init__.py
+++ b/reframe/utility/__init__.py
@@ -1275,6 +1275,9 @@ class ScopedDict(UserDict):
     def __missing__(self, key):
         raise KeyError(str(key))
 
+    def __rfm_json_encode__(self):
+        return self.data
+
 
 @functools.total_ordering
 class OrderedSet(collections.abc.MutableSet):

problem_statement: `--describe` option shows `reference` as `null` even if it is defined
Example:

```python
@rfm.simple_test
class stream_test(rfm.RegressionTest):
    valid_systems = ['*']
    valid_prog_environs = ['+openmp']
    build_system = 'SingleSource'
    sourcepath = 'stream.c'
    reference = {
        'tresa': {
            'copy_bandwidth': (23000, -0.05, None, 'MB/s')
        }
    }

    ...
```

```bash
./bin/reframe -C tutorials/cscs-webinar-2022/config/mysettings.py -c tutorials/cscs-webinar-2022/tests/stream6.py --describe | jq .[].reference
```

```console
null
null
```
repo: reframe-hpc/reframe
test_cmd: pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
test_patch: diff --git a/unittests/test_utility.py b/unittests/test_utility.py
index b89236ce..224d4dc0 100644
--- a/unittests/test_utility.py
+++ b/unittests/test_utility.py
@@ -799,7 +799,6 @@ def test_scoped_dict_construction():
         'a': {'k1': 3, 'k2': 4},
         'b': {'k3': 5}
     }
-    namespace_dict = reframe.utility.ScopedDict()
     namespace_dict = reframe.utility.ScopedDict(d)
 
     # Change local dict and verify that the stored values are not affected
@@ -1088,6 +1087,17 @@ def test_scoped_dict_update():
     assert scoped_dict == scoped_dict_alt
 
 
+def test_scoped_dict_json_enc():
+    import json
+
+    d = {
+        'a': {'k1': 3, 'k2': 4},
+        'b': {'k3': 5}
+    }
+    ns_dict = reframe.utility.ScopedDict(d)
+    assert d == json.loads(jsonext.dumps(ns_dict))
+
+
 def test_sequence_view():
     l = util.SequenceView([1, 2, 2])
     assert 1 == l[0]
task: metadata: install: pip install -e .[dev]
patch: diff --git a/reframe/frontend/cli.py b/reframe/frontend/cli.py
index 8c59a680..2a257c11 100644
--- a/reframe/frontend/cli.py
+++ b/reframe/frontend/cli.py
@@ -791,7 +791,7 @@ def main():
         if options.mode:
             mode = site_config.get(f'modes/@{options.mode}')
             if mode is None:
-                printer.warning(f'invalid mode: {options.mode!r}; ignoring...')
+                raise errors.ReframeError(f'invalid mode: {options.mode!r}')
             else:
                 mode_args = site_config.get(f'modes/@{options.mode}/options')
 
@@ -811,6 +811,10 @@ def main():
         printer.error(f'failed to load configuration: {e}')
         printer.info(logfiles_message())
         sys.exit(1)
+    except errors.ReframeError as e:
+        printer.error(str(e))
+        printer.info(logfiles_message())
+        sys.exit(1)
 
     printer.colorize = site_config.get('general/0/colorize')
     if not restrict_logging():

problem_statement: Passing an invalid mode should issue an error not a warning
Currently, passing an inexistent mode with the `--mode` option, only a warning will be issued and the option will be ignored. This is error prone, as reframe continues execution as if the option wasn't passed.
repo: reframe-hpc/reframe
test_cmd: pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
test_patch: diff --git a/unittests/test_cli.py b/unittests/test_cli.py
index d5d8f148..b468658f 100644
--- a/unittests/test_cli.py
+++ b/unittests/test_cli.py
@@ -527,7 +527,7 @@ def test_execution_modes(run_reframe, run_action):
     assert 'Ran 1/1 test case' in stdout
 
 
-def test_invalid_mode_warning(run_reframe):
+def test_invalid_mode_error(run_reframe):
     mode = 'invalid'
     returncode, stdout, stderr = run_reframe(
         action='list',
@@ -538,7 +538,8 @@ def test_invalid_mode_warning(run_reframe):
     )
     assert 'Traceback' not in stdout
     assert 'Traceback' not in stderr
-    assert f'invalid mode: {mode!r}; ignoring' in stdout
+    assert returncode == 1
+    assert f'ERROR: invalid mode: {mode!r}' in stdout
 
 
 def test_timestamp_option(run_reframe):
task: metadata: install: pip install -e .
patch: diff --git a/reframe/frontend/cli.py b/reframe/frontend/cli.py
index f55bf989..2337546b 100644
--- a/reframe/frontend/cli.py
+++ b/reframe/frontend/cli.py
@@ -1638,9 +1638,12 @@ def main():
             if options.max_retries and runner.stats.failed(run=0):
                 printer.retry_report(report)
 
-            # Print a failure report if we had failures in the last run
+            # Print a failure report in case of failures.
+            # If `--duration` or `--reruns` is used then take into account
+            # all runs, else (i.e., `--max-retries`) only the last run.
             success = True
-            if runner.stats.failed():
+            runid = None if options.duration or options.reruns else -1
+            if runner.stats.failed(run=runid):
                 success = False
                 printer.failure_report(
                     report,
@@ -1734,6 +1737,12 @@ def main():
             sys.exit(1)
 
         sys.exit(0)
+    except errors.RunSessionTimeout as err:
+        printer.warning(f'run session stopped: {err}')
+        if not success:
+            sys.exit(1)
+        else:
+            sys.exit(0)
     except (Exception, KeyboardInterrupt, errors.ReframeFatalError):
         exc_info = sys.exc_info()
         tb = ''.join(traceback.format_exception(*exc_info))

problem_statement: When running with `--duration` do not exit with a non-zero exit code just because of the time out of the last run
Also, we should document what is the expected exit code in case of reruns, either through the `--duration` or the `--reruns` option. For example, for `--reruns` it seems that reframe exits with zero if the last rerun was successful, despite failures in previous reruns.
repo: reframe-hpc/reframe
test_cmd: pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
test_patch: diff --git a/unittests/test_cli.py b/unittests/test_cli.py
index 1e176359..799b45f9 100644
--- a/unittests/test_cli.py
+++ b/unittests/test_cli.py
@@ -1076,6 +1076,13 @@ def test_reruns_with_duration(run_reframe):
     assert returncode == 1
 
 
+def test_exitcode_timeout(run_reframe):
+    assert_no_crash(*run_reframe(
+        more_options=['--duration=5s', '-n^HelloTest'],
+        checkpath=['unittests/resources/checks/hellocheck.py']
+    ))
+
+
 @pytest.fixture(params=['name', 'rname', 'uid', 'ruid', 'random'])
 def exec_order(request):
     return request.param
task: metadata: install: pip install -e .
patch: diff --git a/rollbar/logger.py b/rollbar/logger.py
index f646151..4b47241 100644
--- a/rollbar/logger.py
+++ b/rollbar/logger.py
@@ -139,7 +139,7 @@ class RollbarHandler(logging.Handler):
                                                extra_data=extra_data,
                                                payload_data=payload_data)
             else:
-                uuid = rollbar.report_message(record.msg,
+                uuid = rollbar.report_message(record.getMessage(),
                                               level=level,
                                               request=request,
                                               extra_data=extra_data,

problem_statement: Meaningless message reported on HttpResponseBadRequest
`pyrollbar` reports ` %s: %s (/Library/Frameworks/Python.framework/Versions/*/lib/python*/site-packages/django/utils/log.py:log_response)` when the `HttpResponseBadRequest` is returned from the view in Django projects.
repo: rollbar/pyrollbar
test_cmd: pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
test_patch: diff --git a/rollbar/test/test_loghandler.py b/rollbar/test/test_loghandler.py
index b830713..5c3cf1c 100644
--- a/rollbar/test/test_loghandler.py
+++ b/rollbar/test/test_loghandler.py
@@ -42,13 +42,13 @@ class LogHandlerTest(BaseTest):
         return logger
 
     @mock.patch('rollbar.send_payload')
-    def test_message_stays_unformatted(self, send_payload):
+    def test_message_gets_formatted(self, send_payload):
         logger = self._create_logger()
         logger.warning("Hello %d %s", 1, 'world')
 
         payload = send_payload.call_args[0][0]
 
-        self.assertEqual(payload['data']['body']['message']['body'], "Hello %d %s")
+        self.assertEqual(payload['data']['body']['message']['body'], "Hello 1 world")
         self.assertEqual(payload['data']['body']['message']['args'], (1, 'world'))
         self.assertEqual(payload['data']['body']['message']['record']['name'], __name__)
task: metadata: install: pip install -e .
patch: diff --git a/src/rsatoolbox/rdm/calc.py b/src/rsatoolbox/rdm/calc.py
index 03f8a992..0e31329f 100644
--- a/src/rsatoolbox/rdm/calc.py
+++ b/src/rsatoolbox/rdm/calc.py
@@ -164,6 +164,7 @@ def calc_rdm_movie(
 
         rdm = concat(rdms)
         rdm.rdm_descriptors[time_descriptor] = time
+    rdm.dissimilarity_measure = method
     return rdm
 
 

problem_statement: calc_rdm_movie's returned RDMs doesn't have its .dissimilarity_measure set
**Describe the bug**
`calc_rdm_movie` accepts a `method` parameter, which it uses for all the matrices in the `RDMs` object it returns, guaranteeing that they all use the same method. As such, it could (should) set the returned `RDMs.dissimilarity_measure` to be the `method`.

**To Reproduce**
(`data` as in the [Temporal RSA demo](https://rsatoolbox.readthedocs.io/en/stable/demo_temporal.html))
```python
rdms_data = calc_rdm_movie(data, method="correlation", descriptor="conditions")
print(rdms_data.dissimilarity_measure)  # None
```

**Expected behavior**
Prints `"correlation"`.

**Versions**
- the version of *rsatoolbox* you used
    - 0.1.3
- the version of python you used
    - 3.11.5

repo: rsagroup/rsatoolbox
test_cmd: pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
test_patch: diff --git a/tests/test_calc_rdm.py b/tests/test_calc_rdm.py
index 0d890c46..48d1569b 100755
--- a/tests/test_calc_rdm.py
+++ b/tests/test_calc_rdm.py
@@ -428,6 +428,7 @@ class TestCalcRDMMovie(unittest.TestCase):
         assert len([r for r in rdm]) == 15
         assert rdm.rdm_descriptors['time'][0] == 0.0
         assert len(rdm.rdm_descriptors['time']) == 15
+        assert rdm.dissimilarity_measure == "mahalanobis"
 
     def test_calc_rdm_movie_euclidean(self):
         rdm = rsr.calc_rdm_movie(
@@ -439,6 +440,7 @@ class TestCalcRDMMovie(unittest.TestCase):
         assert rdm.n_cond == 6
         assert len([r for r in rdm]) == 15
         assert rdm.rdm_descriptors['time'][0] == 0.0
+        assert rdm.dissimilarity_measure == "euclidean"
 
     def test_calc_rdm_movie_correlation(self):
         rdm = rsr.calc_rdm_movie(
@@ -450,6 +452,7 @@ class TestCalcRDMMovie(unittest.TestCase):
         assert rdm.n_cond == 6
         assert len([r for r in rdm]) == 15
         assert rdm.rdm_descriptors['time'][0] == 0.0
+        assert rdm.dissimilarity_measure == "correlation"
 
     def test_calc_rdm_movie_crossnobis(self):
         rdm = rsr.calc_rdm_movie(
@@ -462,6 +465,7 @@ class TestCalcRDMMovie(unittest.TestCase):
         assert rdm.n_cond == 6
         assert len([r for r in rdm]) == 15
         assert rdm.rdm_descriptors['time'][0] == 0.0
+        assert rdm.dissimilarity_measure == "crossnobis"
 
     def test_calc_rdm_movie_crossnobis_no_descriptors(self):
         rdm = rsr.calc_rdm_movie(
task: metadata: install: pip install -e .[dev]
patch: diff --git a/ursine/uri.py b/ursine/uri.py
index e7feacc..57be602 100644
--- a/ursine/uri.py
+++ b/ursine/uri.py
@@ -200,6 +200,16 @@ class URI:
         else:
             return uri
 
+    def short_uri(self):
+        if self.user and self.password:
+            user = f'{self.user}:{self.password}@'
+        elif self.user:
+            user = f'{self.user}@'
+        else:
+            user = ''
+
+        return f'{self.scheme}:{user}{self.host}:{self.port}'
+
     def __repr__(self):
         return f'{self.__class__.__name__}({self})'
 

problem_statement: Missing `short_uri`
aiosip needs this method to generate URI addresses.
repo: sangoma/ursine
test_cmd: pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
test_patch: diff --git a/tests/test_uri.py b/tests/test_uri.py
index d74630d..36a8806 100644
--- a/tests/test_uri.py
+++ b/tests/test_uri.py
@@ -29,6 +29,19 @@ def test_to_str(uri, expect):
     assert str(URI(uri)) == expect
 
 
+@pytest.mark.parametrize('uri,expect', [
+    ('sip:localhost', 'sip:localhost:5060'),
+    ('sips:localhost', 'sips:localhost:5061'),
+    ('<sip:localhost>', 'sip:localhost:5060'),
+    (
+        'John Doe <sip:localhost:5080?x=y&a=b>',
+        'sip:localhost:5080',
+    )
+])
+def test_to_short_uri(uri, expect):
+    assert URI(uri).short_uri() == expect
+
+
 @pytest.mark.parametrize('uri,expect', [
     ('sip:localhost', 'URI(sip:localhost:5060;transport=udp)'),
     ('sips:localhost', 'URI(sips:localhost:5061;transport=tcp)'),
task: metadata: install: pip install -e .
patch: diff --git a/src/scippnexus/nxdata.py b/src/scippnexus/nxdata.py
index cc8fbc3..3aac994 100644
--- a/src/scippnexus/nxdata.py
+++ b/src/scippnexus/nxdata.py
@@ -486,7 +486,7 @@ class NXlog(NXdata):
             attrs=attrs,
             children=children,
             fallback_dims=('time',),
-            fallback_signal_name='value',
+            fallback_signal_name='value' if 'value' in children else 'time',
         )
 
     def read_children(self, sel: ScippIndex) -> sc.DataGroup:

problem_statement: Support NXlog without value dataset
This appears to be a valid case, used for top-dead-center chopper timestamps. Currently there is a warning triggered. Probably all there is to do is avoid the warning in this case, by using the `time` dataset as the `signal`?

Should this return the `time` as a `DataArray`, or simply as a `Variable` (as it is now)?
repo: scipp/scippnexus
test_cmd: pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
test_patch: diff --git a/tests/nxlog_test.py b/tests/nxlog_test.py
index 44b9e2d..0cbf5e4 100644
--- a/tests/nxlog_test.py
+++ b/tests/nxlog_test.py
@@ -52,16 +52,14 @@ def test_nxobject_log(h5root):
     assert sc.identical(log[...], da)
 
 
-@pytest.mark.filterwarnings("ignore:Failed to load /entry/log:UserWarning")
-def test_nxlog_with_missing_value_triggers_fallback(nxroot):
+def test_nxlog_with_missing_value_uses_time_as_value(nxroot):
     time = sc.epoch(unit='ns') + sc.array(
         dims=['time'], unit='s', values=[4.4, 5.5, 6.6]
     ).to(unit='ns', dtype='int64')
     log = nxroot['entry'].create_class('log', NXlog)
     log['time'] = time - sc.epoch(unit='ns')
     loaded = log[()]
-    # Fallback to DataGroup, but we still have partial info from NXlog: dim is time
-    assert_identical(loaded, sc.DataGroup(time=time))
+    assert_identical(loaded, sc.DataArray(data=time))
 
 
 def test_nxlog_length_1(h5root):
task: metadata: install: pip install -e .[dev]
patch: diff --git a/src/scout_apm/core/config.py b/src/scout_apm/core/config.py
index 200968d..5d77b7b 100644
--- a/src/scout_apm/core/config.py
+++ b/src/scout_apm/core/config.py
@@ -233,6 +233,7 @@ class ScoutConfigDefaults(object):
             "name": "",
             "revision_sha": self._git_revision_sha(),
             "scm_subdirectory": "",
+            "uri_reporting": "filtered_params",
         }
 
     def _git_revision_sha(self):
diff --git a/src/scout_apm/core/web_requests.py b/src/scout_apm/core/web_requests.py
index 4e2b89e..52ff42d 100644
--- a/src/scout_apm/core/web_requests.py
+++ b/src/scout_apm/core/web_requests.py
@@ -1,5 +1,6 @@
 # coding=utf-8
 from scout_apm.compat import urlencode
+from scout_apm.core.context import AgentContext
 
 # Originally derived from:
 # 1. Rails:
@@ -35,6 +36,8 @@ FILTER_PARAMETERS = frozenset(
 
 
 def create_filtered_path(path, query_params):
+    if AgentContext.instance.config.value("uri_reporting") == "path":
+        return path
     filtered_params = sorted(
         (
             (k, "[FILTERED]" if k.lower() in FILTER_PARAMETERS else v)

problem_statement: Config to capture query string, not just path
When a request comes in, we capture `request.path`, which doesn't appear to capture any query string.

We should match the Ruby agent:
* Default to capturing the entire path and query string
* Config to not capture query string https://docs.scoutapm.com/#uri_reporting
repo: scoutapp/scout_apm_python
test_cmd: pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
test_patch: diff --git a/tests/unit/core/test_web_requests.py b/tests/unit/core/test_web_requests.py
index af36d4e..ffe9f0c 100644
--- a/tests/unit/core/test_web_requests.py
+++ b/tests/unit/core/test_web_requests.py
@@ -3,9 +3,17 @@ from __future__ import absolute_import, division, print_function, unicode_litera
 
 import pytest
 
+from scout_apm.core.context import AgentContext
 from scout_apm.core.web_requests import create_filtered_path
 
 
+@pytest.fixture(autouse=True)
+def force_context():
+    # Since this function accesses the context, it needs to always be built
+    # TODO: remove when moving to a sensible singleton pattern
+    AgentContext.build()
+
+
 @pytest.mark.parametrize(
     "path, params, expected",
     [
@@ -25,3 +33,14 @@ from scout_apm.core.web_requests import create_filtered_path
 )
 def test_create_filtered_path(path, params, expected):
     assert create_filtered_path(path, params) == expected
+
+
+@pytest.mark.parametrize("path, params", [("/", []), ("/", [("foo", "ignored")])])
+def test_create_filtered_path_path(path, params):
+    # If config filtered_params is set to "path", expect we always get the path
+    # back
+    AgentContext.instance.config.set(uri_reporting="path")
+    try:
+        assert create_filtered_path(path, params) == path
+    finally:
+        AgentContext.instance.config.reset_all()
task: metadata: install: pip install -e .[dev]
patch: diff --git a/CHANGELOG.md b/CHANGELOG.md
index c277c34..5ea5780 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,6 +8,8 @@
   ([PR #283](https://github.com/scoutapp/scout_apm_python/pull/283)).
 - Improve warning message for deprecated `log_level` configuration option
   ([PR #288](https://github.com/scoutapp/scout_apm_python/pull/288)).
+- Track errors on Pyramid
+  ([PR #298](https://github.com/scoutapp/scout_apm_python/pull/298)).
 
 ## [2.6.0] 2019-10-22
 
diff --git a/src/scout_apm/pyramid.py b/src/scout_apm/pyramid.py
index 73ade4e..b4d7f97 100644
--- a/src/scout_apm/pyramid.py
+++ b/src/scout_apm/pyramid.py
@@ -77,17 +77,18 @@ def instruments(handler, registry):
                     track_amazon_request_queue_time(amazon_queue_time, tracked_request)
 
             try:
-                response = handler(request)
+                try:
+                    response = handler(request)
+                finally:
+                    # Routing further down the call chain. So time it starting
+                    # above, but only name it if it gets a name
+                    if request.matched_route is not None:
+                        tracked_request.mark_real_request()
+                        span.operation = "Controller/" + request.matched_route.name
             except Exception:
                 tracked_request.tag("error", "true")
                 raise
 
-            # This happens further down the call chain. So time it starting
-            # above, but only name it if it gets to here.
-            if request.matched_route is not None:
-                tracked_request.mark_real_request()
-                span.operation = "Controller/" + request.matched_route.name
-
         finally:
             tracked_request.stop_span()
 

problem_statement: Report error requests on Pyramid
Currently if an error occurs in a Pyramid request, we don't report it. Error cases can be just as useful to see so we should try and do this. It looks like it's possible by rearranging the existing code.
repo: scoutapp/scout_apm_python
test_cmd: pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
test_patch: diff --git a/tests/integration/test_pyramid.py b/tests/integration/test_pyramid.py
index fb4df40..2606691 100644
--- a/tests/integration/test_pyramid.py
+++ b/tests/integration/test_pyramid.py
@@ -217,7 +217,13 @@ def test_server_error(tracked_requests):
     with app_with_scout() as app, pytest.raises(ValueError):
         TestApp(app).get("/crash/", expect_errors=True)
 
-    assert tracked_requests == []
+    assert len(tracked_requests) == 1
+    tracked_request = tracked_requests[0]
+    assert tracked_request.tags["path"] == "/crash/"
+    assert tracked_request.tags["error"] == "true"
+    assert len(tracked_request.complete_spans) == 1
+    span = tracked_request.complete_spans[0]
+    assert span.operation == "Controller/crash"
 
 
 def test_no_monitor(tracked_requests):
task: metadata: install: pip install -e .[dev]
patch: diff --git a/scrapy/utils/reqser.py b/scrapy/utils/reqser.py
index 7e1e99e48..2fceb0d94 100644
--- a/scrapy/utils/reqser.py
+++ b/scrapy/utils/reqser.py
@@ -5,6 +5,7 @@ import six
 
 from scrapy.http import Request
 from scrapy.utils.python import to_unicode, to_native_str
+from scrapy.utils.misc import load_object
 
 
 def request_to_dict(request, spider=None):
@@ -32,6 +33,8 @@ def request_to_dict(request, spider=None):
         'priority': request.priority,
         'dont_filter': request.dont_filter,
     }
+    if type(request) is not Request:
+        d['_class'] = request.__module__ + '.' + request.__class__.__name__
     return d
 
 
@@ -47,7 +50,8 @@ def request_from_dict(d, spider=None):
     eb = d['errback']
     if eb and spider:
         eb = _get_method(spider, eb)
-    return Request(
+    request_cls = load_object(d['_class']) if '_class' in d else Request
+    return request_cls(
         url=to_native_str(d['url']),
         callback=cb,
         errback=eb,

problem_statement: Disk queues don't preserve Request class
When a Request subclass (e.g. FormRequest) is sent to a disk queue a bare Request is what you get back. 

This is inconvenient for scrapy-splash: Splash requests all have Splash URL as request.url, but for logging it is nice to display the requested URL, not only Splash URL. In scrapy-splash this is implemented by changing `__repr__` in a Request subclass, but it works only when request is kept in memory.

repo: scrapy/scrapy
test_cmd: pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
test_patch: diff --git a/tests/test_utils_reqser.py b/tests/test_utils_reqser.py
index a62f13e21..5b889ab5d 100644
--- a/tests/test_utils_reqser.py
+++ b/tests/test_utils_reqser.py
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 import unittest
 
-from scrapy.http import Request
+from scrapy.http import Request, FormRequest
 from scrapy.spiders import Spider
 from scrapy.utils.reqser import request_to_dict, request_from_dict
 
@@ -42,6 +42,7 @@ class RequestSerializationTest(unittest.TestCase):
         self._assert_same_request(request, request2)
 
     def _assert_same_request(self, r1, r2):
+        self.assertEqual(r1.__class__, r2.__class__)
         self.assertEqual(r1.url, r2.url)
         self.assertEqual(r1.callback, r2.callback)
         self.assertEqual(r1.errback, r2.errback)
@@ -54,6 +55,12 @@ class RequestSerializationTest(unittest.TestCase):
         self.assertEqual(r1.priority, r2.priority)
         self.assertEqual(r1.dont_filter, r2.dont_filter)
 
+    def test_request_class(self):
+        r = FormRequest("http://www.example.com")
+        self._assert_serializes_ok(r, spider=self.spider)
+        r = CustomRequest("http://www.example.com")
+        self._assert_serializes_ok(r, spider=self.spider)
+
     def test_callback_serialization(self):
         r = Request("http://www.example.com", callback=self.spider.parse_item,
                     errback=self.spider.handle_error)
@@ -77,3 +84,7 @@ class TestSpider(Spider):
 
     def handle_error(self, failure):
         pass
+
+
+class CustomRequest(Request):
+    pass
task: metadata: install: pip install -e .[dev]
patch: diff --git a/scrapy/mail.py b/scrapy/mail.py
index c11f3898d..237327451 100644
--- a/scrapy/mail.py
+++ b/scrapy/mail.py
@@ -96,10 +96,9 @@ class MailSender:
             rcpts.extend(cc)
             msg["Cc"] = COMMASPACE.join(cc)
 
-        if charset:
-            msg.set_charset(charset)
-
         if attachs:
+            if charset:
+                msg.set_charset(charset)
             msg.attach(MIMEText(body, "plain", charset or "us-ascii"))
             for attach_name, mimetype, f in attachs:
                 part = MIMEBase(*mimetype.split("/"))
@@ -110,7 +109,7 @@ class MailSender:
                 )
                 msg.attach(part)
         else:
-            msg.set_payload(body)
+            msg.set_payload(body, charset)
 
         if _callback:
             _callback(to=to, subject=subject, body=body, cc=cc, attach=attachs, msg=msg)

problem_statement: Wrong charset handling in MailSender
Looks like passing `charset='utf-8'` makes a plain text message with `Content-Transfer-Encoding: base64` which then can't be read.

At https://github.com/scrapy/scrapy/blob/5a75b14a5fbbbd37c14aa7317761655ac7706b70/scrapy/mail.py#L81 `set_charset` is called but as the payload is not set yet, the underlying class just sets the headers. When later `set_payload` is called, it doesn't do any encoding, but the `Content-Transfer-Encoding` is already set. Looks like the fix should be passing the encoding to `set_payload` too, like was proposed in #3722 (and `set_charset` may be safe to be removed, not sure about this). Note that we have tests but they don't catch this.

Note also, that all of this seems to be compat code according to the Python docs.
repo: scrapy/scrapy
test_cmd: pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
test_patch: diff --git a/tests/test_mail.py b/tests/test_mail.py
index 504c78486..2535e58db 100644
--- a/tests/test_mail.py
+++ b/tests/test_mail.py
@@ -111,7 +111,7 @@ class MailSenderTest(unittest.TestCase):
 
         msg = self.catched_msg["msg"]
         self.assertEqual(msg["subject"], subject)
-        self.assertEqual(msg.get_payload(), body)
+        self.assertEqual(msg.get_payload(decode=True).decode("utf-8"), body)
         self.assertEqual(msg.get_charset(), Charset("utf-8"))
         self.assertEqual(msg.get("Content-Type"), 'text/plain; charset="utf-8"')
task: metadata: install: pip install -e .
patch: diff --git a/w3lib/html.py b/w3lib/html.py
index a31d42b..0cff2ff 100644
--- a/w3lib/html.py
+++ b/w3lib/html.py
@@ -91,7 +91,7 @@ def replace_entities(
                     return bytes((number,)).decode("cp1252")
                 else:
                     return chr(number)
-            except ValueError:
+            except (ValueError, OverflowError):
                 pass
 
         return "" if remove_illegal and groups.get("semicolon") else m.group(0)

problem_statement: Function `convert_entity` does not catch `OverflowError` 
Error:
```
OverflowError
Python int too large to convert to C int
```

`w3lib` version -> `2.0.1`
`Python` version -> `3.8.13`

<img width="1131" alt="Screenshot 2022-10-31 at 10 02 22" src="https://user-images.githubusercontent.com/107861298/198971171-1af35f01-42d2-413a-8c47-9d2c3dc6ece1.png">

repo: scrapy/w3lib
test_cmd: pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
test_patch: diff --git a/tests/test_html.py b/tests/test_html.py
index 1e637b0..1cabf6d 100644
--- a/tests/test_html.py
+++ b/tests/test_html.py
@@ -65,6 +65,10 @@ class RemoveEntitiesTest(unittest.TestCase):
         self.assertEqual(replace_entities("x&#x2264;y"), "x\u2264y")
         self.assertEqual(replace_entities("x&#157;y"), "xy")
         self.assertEqual(replace_entities("x&#157;y", remove_illegal=False), "x&#157;y")
+        self.assertEqual(replace_entities("&#82179209091;"), "")
+        self.assertEqual(
+            replace_entities("&#82179209091;", remove_illegal=False), "&#82179209091;"
+        )
 
     def test_browser_hack(self):
         # check browser hack for numeric character references in the 80-9F range