coveralls: ## Pull Request Test Coverage Report for [Build 184](https://coveralls.io/builds/26893534)

* **15** of **16**   **(93.75%)**  changed or added relevant lines in **2** files are covered.
* No unchanged relevant lines lost coverage.
* Overall coverage decreased (**-0.09%**) to **97.976%**

---

|  Changes Missing Coverage | Covered Lines | Changed/Added Lines | % |
| :-----|--------------|--------|---: |
| [omegaconf/omegaconf.py](https://coveralls.io/builds/26893534/source?filename=omegaconf%2Fomegaconf.py#L198) | 7 | 8 | 87.5%
<!-- | **Total:** | **15** | **16** | **93.75%** | -->


|  Totals | [![Coverage Status](https://coveralls.io/builds/26893534/badge)](https://coveralls.io/builds/26893534) |
| :-- | --: |
| Change from base [Build 177](https://coveralls.io/builds/26882001): |  -0.09% |
| Covered Lines: | 823 |
| Relevant Lines: | 840 |

---
##### 💛  - [Coveralls](https://coveralls.io)

diff --git a/docs/source/usage.rst b/docs/source/usage.rst
index 6a52702..e1872d1 100644
--- a/docs/source/usage.rst
+++ b/docs/source/usage.rst
@@ -393,4 +393,24 @@ You can temporarily remove the struct flag from a config object:
     >>> with omegaconf.open_dict(conf):
     ...   conf.a.cc = 30
     >>> conf.a.cc
-    30
\ No newline at end of file
+    30
+
+Utility functions
+-----------------
+
+OmegaConf.masked_copy
+^^^^^^^^^^^^^^^^^^^^^
+Creates a copy of a DictConfig that contains only specific keys.
+.. doctest:: loaded
+
+    >>> conf = OmegaConf.create(dict(a=dict(b=10), c=20))
+    >>> print(conf.pretty())
+    a:
+      b: 10
+    c: 20
+    <BLANKLINE>
+    >>> c = OmegaConf.masked_copy(conf, ["a"])
+    >>> print(c.pretty())
+    a:
+      b: 10
+    <BLANKLINE>
diff --git a/news/42.feature b/news/42.feature
new file mode 100644
index 0000000..b2283bc
--- /dev/null
+++ b/news/42.feature
@@ -0,0 +1,1 @@
+Add OmegaConf.masked_copy(keys) function that returns a copy of a config with a subset of the keys
diff --git a/omegaconf/dictconfig.py b/omegaconf/dictconfig.py
index 9f81527..7c180f8 100644
--- a/omegaconf/dictconfig.py
+++ b/omegaconf/dictconfig.py
@@ -139,7 +139,7 @@ class DictConfig(Config):
     def __iter__(self):
         return iter(self.keys())
 
-    def items(self, resolve=True):
+    def items(self, resolve=True, keys=None):
         class MyItems(object):
             def __init__(self, m):
                 self.map = m
@@ -148,11 +148,20 @@ class DictConfig(Config):
             def __iter__(self):
                 return self
 
-            # Python 3 compatibility
             def __next__(self):
-                return self.next()
+                k, v = self._next_pair()
+                if keys is not None:
+                    while True:
+                        if k not in keys:
+                            k, v = self._next_pair()
+                        else:
+                            break
+                return k, v
 
             def next(self):
+                return self.__next__()
+
+            def _next_pair(self):
                 k = next(self.iterator)
                 if resolve:
                     v = self.map.get(k)
diff --git a/omegaconf/listconfig.py b/omegaconf/listconfig.py
index d2696b5..993ba31 100644
--- a/omegaconf/listconfig.py
+++ b/omegaconf/listconfig.py
@@ -60,9 +60,6 @@ class ListConfig(Config):
 
         value = self._prepare_value_to_add(index, value)
 
-        if self._get_flag("readonly"):
-            raise ReadonlyConfigError(self.get_full_key(index))
-
         if not isinstance(value, BaseNode):
             self.__dict__["content"][index].set_value(value)
         else:
@@ -149,7 +146,7 @@ class ListConfig(Config):
 
     def pop(self, index=-1):
         if self._get_flag("readonly"):
-            raise ReadonlyConfigError(self.get_full_key(index))
+            raise ReadonlyConfigError(self.get_full_key(index if index != -1 else ""))
         return self._resolve_with_default(
             key=index, value=self.content.pop(index), default_value=None
         )
diff --git a/omegaconf/omegaconf.py b/omegaconf/omegaconf.py
index 3699447..df50a2e 100644
--- a/omegaconf/omegaconf.py
+++ b/omegaconf/omegaconf.py
@@ -184,6 +184,24 @@ class OmegaConf:
         # noinspection PyProtectedMember
         return conf._get_flag("struct")
 
+    @staticmethod
+    def masked_copy(conf, keys):
+        """
+        Create a masked copy of of this config that contains a subset of the keys
+        :param conf: DictConfig object
+        :param keys: keys to preserve in the copy
+        :return:
+        """
+        from .dictconfig import DictConfig
+
+        if not isinstance(conf, DictConfig):
+            raise ValueError("masked_copy is only supported for DictConfig")
+
+        if isinstance(keys, str):
+            keys = [keys]
+        content = {key: value for key, value in conf.items(resolve=False, keys=keys)}
+        return DictConfig(content=content)
+
 
 # register all default resolvers
 register_default_resolvers()

[Feature Request] Add ability to get parts (sub-trees) of the config
Currently in OmegaConf, for the following config:
```
server:
  host: localhost
  port: 80

client:
  url: http://${server.host}:${server.port}/
  server_port: ${server.port}
```

We can get `conf["server"]` and `conf["client"]`, but then we lose the parent component name (e.g., "server" or "client").


This feature is to be able to get complete subtrees, rooted at the specified head.

Example config:
```
server:
  host: localhost
  port: 80

client:
  url: http://${server.host}:${server.port}/
  server_port: ${server.port}
```

Usage:
```
print(conf.root_from("server"))
```

Outputs
```
server:
  host: localhost
  port: 80
```
diff --git a/tests/test_basic_ops_dict.py b/tests/test_basic_ops_dict.py
index d968908..126175c 100644
--- a/tests/test_basic_ops_dict.py
+++ b/tests/test_basic_ops_dict.py
@@ -397,3 +397,28 @@ def test_members():
     # Make sure accessing __members__ does not return None or throw.
     c = OmegaConf.create({"foo": {}})
     assert c.__members__ == {}
+
+
+@pytest.mark.parametrize(
+    "cfg, mask_keys, expected",
+    [
+        ({}, [], {}),
+        ({"a": 1}, "a", {"a": 1}),
+        ({"a": 1}, ["b"], {}),
+        ({"a": 1, "b": 2}, "b", {"b": 2}),
+        ({"a": 1, "b": 2}, ["a", "b"], {"a": 1, "b": 2}),
+    ],
+)
+def test_masked_copy(cfg, mask_keys, expected):
+    cfg = OmegaConf.create(cfg)
+    masked = OmegaConf.masked_copy(cfg, keys=mask_keys)
+    assert masked == expected
+
+
+def test_masked_copy_is_deep():
+    cfg = OmegaConf.create({"a": {"b": 1, "c": 2}})
+    expected = {"a": {"b": 1, "c": 2}}
+    masked = OmegaConf.masked_copy(cfg, keys=["a"])
+    assert masked == expected
+    cfg.a.b = 2
+    assert cfg != expected
diff --git a/tests/test_readonly.py b/tests/test_readonly.py
index 2a138b9..fe0521e 100644
--- a/tests/test_readonly.py
+++ b/tests/test_readonly.py
@@ -1,43 +1,36 @@
 import re
 
 import pytest
-
+from pytest import raises
 from omegaconf import ReadonlyConfigError, OmegaConf
 
 
 @pytest.mark.parametrize(
     "src, func, expectation",
     [
-        (
-            {},
-            lambda c: c.__setitem__("a", 1),
-            pytest.raises(ReadonlyConfigError, match="a"),
-        ),
+        ({}, lambda c: c.__setitem__("a", 1), raises(ReadonlyConfigError, match="a"),),
         (
             dict(a=dict(b=dict(c=1))),
             lambda c: c.__getattr__("a").__getattr__("b").__setitem__("c", 1),
-            pytest.raises(ReadonlyConfigError, match="a.b.c"),
-        ),
-        (
-            {},
-            lambda c: c.update("a.b", 10),
-            pytest.raises(ReadonlyConfigError, match="a"),
+            raises(ReadonlyConfigError, match="a.b.c"),
         ),
+        ({}, lambda c: c.update("a.b", 10), raises(ReadonlyConfigError, match="a"),),
         (
             dict(a=10),
             lambda c: c.__setattr__("a", 1),
-            pytest.raises(ReadonlyConfigError, match="a"),
-        ),
-        (
-            dict(a=10),
-            lambda c: c.pop("a"),
-            pytest.raises(ReadonlyConfigError, match="a"),
+            raises(ReadonlyConfigError, match="a"),
         ),
+        (dict(a=10), lambda c: c.pop("a"), raises(ReadonlyConfigError, match="a"),),
         (
             dict(a=10),
             lambda c: c.__delitem__("a"),
-            pytest.raises(ReadonlyConfigError, match="a"),
+            raises(ReadonlyConfigError, match="a"),
         ),
+        # list
+        ([], lambda c: c.__setitem__(0, 1), raises(ReadonlyConfigError, match="0"),),
+        ([], lambda c: c.update("0.b", 10), raises(ReadonlyConfigError, match="[0]"),),
+        ([10], lambda c: c.pop(), raises(ReadonlyConfigError)),
+        ([0], lambda c: c.__delitem__(0), raises(ReadonlyConfigError, match="[0]"),),
     ],
 )
 def test_readonly(src, func, expectation):
@@ -81,7 +74,7 @@ def test_readonly_nested_list():
 def test_readonly_list_insert():
     c = OmegaConf.create([])
     OmegaConf.set_readonly(c, True)
-    with pytest.raises(ReadonlyConfigError, match="[0]"):
+    with raises(ReadonlyConfigError, match="[0]"):
         c.insert(0, 10)
     assert c == []
 
@@ -90,7 +83,7 @@ def test_readonly_list_insert_deep():
     src = [dict(a=[dict(b=[])])]
     c = OmegaConf.create(src)
     OmegaConf.set_readonly(c, True)
-    with pytest.raises(ReadonlyConfigError, match=re.escape("[0].a[0].b[0]")):
+    with raises(ReadonlyConfigError, match=re.escape("[0].a[0].b[0]")):
         c[0].a[0].b.insert(0, 10)
     assert c == src
 
@@ -98,7 +91,7 @@ def test_readonly_list_insert_deep():
 def test_readonly_list_append():
     c = OmegaConf.create([])
     OmegaConf.set_readonly(c, True)
-    with pytest.raises(ReadonlyConfigError, match="[0]"):
+    with raises(ReadonlyConfigError, match="[0]"):
         c.append(10)
     assert c == []
 
@@ -106,7 +99,7 @@ def test_readonly_list_append():
 def test_readonly_list_change_item():
     c = OmegaConf.create([1, 2, 3])
     OmegaConf.set_readonly(c, True)
-    with pytest.raises(ReadonlyConfigError, match="[1]"):
+    with raises(ReadonlyConfigError, match="[1]"):
         c[1] = 10
     assert c == [1, 2, 3]
 
@@ -114,7 +107,7 @@ def test_readonly_list_change_item():
 def test_readonly_list_pop():
     c = OmegaConf.create([1, 2, 3])
     OmegaConf.set_readonly(c, True)
-    with pytest.raises(ReadonlyConfigError, match="[1]"):
+    with raises(ReadonlyConfigError, match="[1]"):
         c.pop(1)
     assert c == [1, 2, 3]
 
@@ -122,7 +115,7 @@ def test_readonly_list_pop():
 def test_readonly_list_del():
     c = OmegaConf.create([1, 2, 3])
     OmegaConf.set_readonly(c, True)
-    with pytest.raises(ReadonlyConfigError, match="[1]"):
+    with raises(ReadonlyConfigError, match="[1]"):
         del c[1]
     assert c == [1, 2, 3]
 
@@ -130,7 +123,7 @@ def test_readonly_list_del():
 def test_readonly_list_sort():
     c = OmegaConf.create([3, 1, 2])
     OmegaConf.set_readonly(c, True)
-    with pytest.raises(ReadonlyConfigError):
+    with raises(ReadonlyConfigError):
         c.sort()
     assert c == [3, 1, 2]
 
@@ -139,5 +132,5 @@ def test_readonly_from_cli():
     c = OmegaConf.create({"foo": {"bar": [1]}})
     OmegaConf.set_readonly(c, True)
     cli = OmegaConf.from_dotlist(["foo.bar=[2]"])
-    with pytest.raises(ReadonlyConfigError, match="foo.bar"):
+    with raises(ReadonlyConfigError, match="foo.bar"):
         OmegaConf.merge(c, cli)

pip install -e .[dev]
parse_log_pytest
requirements.txt
pytest flake8 black
apt-get update apt-get install -y gcc
3.7
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
argcomplete==3.1.2
black==23.3.0
bleach==6.0.0
certifi @ file:///croot/certifi_1671487769961/work/certifi
cffi==1.15.1
cfgv==3.3.1
charset-normalizer==3.4.1
click==8.1.8
click-default-group==1.2.4
colorlog==6.9.0
coverage==6.5.0
coveralls==3.3.1
cryptography==44.0.2
distlib==0.3.9
docopt==0.6.2
docutils==0.20.1
exceptiongroup==1.2.2
filelock==3.12.2
flake8==5.0.4
identify==2.5.24
idna==3.10
importlib-metadata==4.2.0
importlib-resources==5.12.0
incremental==22.10.0
iniconfig==2.0.0
jaraco.classes==3.2.3
jeepney==0.9.0
Jinja2==3.1.6
keyring==23.9.3
markdown-it-py==2.2.0
MarkupSafe==2.1.5
mccabe==0.7.0
mdurl==0.1.2
more-itertools==9.1.0
mypy-extensions==1.0.0
nodeenv==1.9.1
nox==2024.4.15
-e git+https://github.com/omry/omegaconf.git@dfa36718cd1ce8563eb19e238358d87e511a8cd0#egg=omegaconf
packaging==24.0
pathspec==0.11.2
pkginfo==1.10.0
platformdirs==2.6.2
pluggy==1.2.0
pre-commit==2.21.0
pycodestyle==2.9.1
pycparser==2.21
pyflakes==2.5.0
Pygments==2.17.2
pytest==7.4.4
PyYAML==6.0.1
readme-renderer==37.3
requests==2.31.0
requests-toolbelt==1.0.0
rfc3986==2.0.0
rich==13.8.1
SecretStorage==3.3.3
six==1.17.0
tomli==2.0.1
towncrier==23.6.0
twine==4.0.2
typed-ast==1.5.5
typing_extensions==4.7.1
urllib3==2.0.7
virtualenv==20.16.2
webencodings==0.5.1
zipp==3.15.0

name: omegaconf
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - ca-certificates=2025.2.25=h06a4308_0
  - certifi=2022.12.7=py37h06a4308_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.4.4=h6a678d5_1
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - ncurses=6.4=h6a678d5_0
  - openssl=1.1.1w=h7f8727e_0
  - pip=22.3.1=py37h06a4308_0
  - python=3.7.16=h7a1cb2a_0
  - readline=8.2=h5eee18b_0
  - setuptools=65.6.3=py37h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - wheel=0.38.4=py37h06a4308_0
  - xz=5.6.4=h5eee18b_1
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - argcomplete==3.1.2
      - black==23.3.0
      - bleach==6.0.0
      - cffi==1.15.1
      - cfgv==3.3.1
      - charset-normalizer==3.4.1
      - click==8.1.8
      - click-default-group==1.2.4
      - colorlog==6.9.0
      - coverage==6.5.0
      - coveralls==3.3.1
      - cryptography==44.0.2
      - distlib==0.3.9
      - docopt==0.6.2
      - docutils==0.20.1
      - exceptiongroup==1.2.2
      - filelock==3.12.2
      - flake8==5.0.4
      - identify==2.5.24
      - idna==3.10
      - importlib-metadata==4.2.0
      - importlib-resources==5.12.0
      - incremental==22.10.0
      - iniconfig==2.0.0
      - jaraco-classes==3.2.3
      - jeepney==0.9.0
      - jinja2==3.1.6
      - keyring==23.9.3
      - markdown-it-py==2.2.0
      - markupsafe==2.1.5
      - mccabe==0.7.0
      - mdurl==0.1.2
      - more-itertools==9.1.0
      - mypy-extensions==1.0.0
      - nodeenv==1.9.1
      - nox==2024.4.15
      - omegaconf==1.4.0rc2
      - packaging==24.0
      - pathspec==0.11.2
      - pkginfo==1.10.0
      - platformdirs==2.6.2
      - pluggy==1.2.0
      - pre-commit==2.21.0
      - pycodestyle==2.9.1
      - pycparser==2.21
      - pyflakes==2.5.0
      - pygments==2.17.2
      - pytest==7.4.4
      - pyyaml==6.0.1
      - readme-renderer==37.3
      - requests==2.31.0
      - requests-toolbelt==1.0.0
      - rfc3986==2.0.0
      - rich==13.8.1
      - secretstorage==3.3.3
      - six==1.17.0
      - tomli==2.0.1
      - towncrier==23.6.0
      - twine==4.0.2
      - typed-ast==1.5.5
      - typing-extensions==4.7.1
      - urllib3==2.0.7
      - virtualenv==20.16.2
      - webencodings==0.5.1
      - zipp==3.15.0
prefix: /opt/conda/envs/omegaconf

tests/test_basic_ops_dict.py::test_masked_copy[cfg0-mask_keys0-expected0] tests/test_basic_ops_dict.py::test_masked_copy[cfg1-a-expected1] tests/test_basic_ops_dict.py::test_masked_copy[cfg2-mask_keys2-expected2] tests/test_basic_ops_dict.py::test_masked_copy[cfg3-b-expected3] tests/test_basic_ops_dict.py::test_masked_copy[cfg4-mask_keys4-expected4] tests/test_basic_ops_dict.py::test_masked_copy_is_deep
tests/test_basic_ops_dict.py::test_setattr_deep_value tests/test_basic_ops_dict.py::test_setattr_deep_from_empty tests/test_basic_ops_dict.py::test_setattr_deep_map tests/test_basic_ops_dict.py::test_getattr tests/test_basic_ops_dict.py::test_getattr_dict tests/test_basic_ops_dict.py::test_mandatory_value tests/test_basic_ops_dict.py::test_nested_dict_mandatory_value tests/test_basic_ops_dict.py::test_mandatory_with_default tests/test_basic_ops_dict.py::test_subscript_get tests/test_basic_ops_dict.py::test_subscript_set tests/test_basic_ops_dict.py::test_pretty_dict tests/test_basic_ops_dict.py::test_default_value tests/test_basic_ops_dict.py::test_get_default_value tests/test_basic_ops_dict.py::test_scientific_notation_float tests/test_basic_ops_dict.py::test_dict_get_with_default tests/test_basic_ops_dict.py::test_map_expansion tests/test_basic_ops_dict.py::test_items tests/test_basic_ops_dict.py::test_items2 tests/test_basic_ops_dict.py::test_items_with_interpolation tests/test_basic_ops_dict.py::test_dict_keys tests/test_basic_ops_dict.py::test_pickle_get_root tests/test_basic_ops_dict.py::test_iterate_dictionary tests/test_basic_ops_dict.py::test_dict_pop tests/test_basic_ops_dict.py::test_in_dict[conf0-a-True] tests/test_basic_ops_dict.py::test_in_dict[conf1-b-True] tests/test_basic_ops_dict.py::test_in_dict[conf2-c-False] tests/test_basic_ops_dict.py::test_in_dict[conf3-b-True] tests/test_basic_ops_dict.py::test_in_dict[conf4-b-False] tests/test_basic_ops_dict.py::test_in_dict[conf5-c-False] tests/test_basic_ops_dict.py::test_in_dict[conf6-b-False] tests/test_basic_ops_dict.py::test_in_dict[conf7-a-True] tests/test_basic_ops_dict.py::test_get_root tests/test_basic_ops_dict.py::test_get_root_of_merged tests/test_basic_ops_dict.py::test_dict_config tests/test_basic_ops_dict.py::test_dict_delitem tests/test_basic_ops_dict.py::test_dict_len tests/test_basic_ops_dict.py::test_dict_assign_illegal_value tests/test_basic_ops_dict.py::test_dict_assign_illegal_value_nested tests/test_basic_ops_dict.py::test_assign_dict_in_dict tests/test_basic_ops_dict.py::test_to_container tests/test_basic_ops_dict.py::test_pretty_without_resolve tests/test_basic_ops_dict.py::test_pretty_with_resolve tests/test_basic_ops_dict.py::test_instantiate_config_fails tests/test_basic_ops_dict.py::test_dir tests/test_basic_ops_dict.py::test_dict_eq[input10-input20] tests/test_basic_ops_dict.py::test_dict_eq[input11-input21] tests/test_basic_ops_dict.py::test_dict_eq[input12-input22] tests/test_basic_ops_dict.py::test_dict_eq[input13-input23] tests/test_basic_ops_dict.py::test_dict_eq[input14-input24] tests/test_basic_ops_dict.py::test_dict_eq[input15-input25] tests/test_basic_ops_dict.py::test_dict_eq[input16-input26] tests/test_basic_ops_dict.py::test_dict_eq[input17-input27] tests/test_basic_ops_dict.py::test_dict_eq_with_interpolation[input10-input20] tests/test_basic_ops_dict.py::test_dict_not_eq[input10-input20] tests/test_basic_ops_dict.py::test_dict_not_eq[input11-input21] tests/test_basic_ops_dict.py::test_dict_not_eq[input12-input22] tests/test_basic_ops_dict.py::test_dict_not_eq[input13-input23] tests/test_basic_ops_dict.py::test_dict_not_eq[input14-input24] tests/test_basic_ops_dict.py::test_dict_not_eq[input15-input25] tests/test_basic_ops_dict.py::test_dict_not_eq[input16-input26] tests/test_basic_ops_dict.py::test_dict_not_eq[input17-input27] tests/test_basic_ops_dict.py::test_dict_not_eq[input18-input28] tests/test_basic_ops_dict.py::test_config_eq_mismatch_types tests/test_basic_ops_dict.py::test_dict_not_eq_with_another_class tests/test_basic_ops_dict.py::test_hash tests/test_basic_ops_dict.py::test_get_with_default_from_struct_not_throwing tests/test_basic_ops_dict.py::test_members tests/test_readonly.py::test_readonly[src0-<lambda>-expectation0] tests/test_readonly.py::test_readonly[src1-<lambda>-expectation1] tests/test_readonly.py::test_readonly[src2-<lambda>-expectation2] tests/test_readonly.py::test_readonly[src3-<lambda>-expectation3] tests/test_readonly.py::test_readonly[src4-<lambda>-expectation4] tests/test_readonly.py::test_readonly[src5-<lambda>-expectation5] tests/test_readonly.py::test_readonly[src6-<lambda>-expectation6] tests/test_readonly.py::test_readonly[src7-<lambda>-expectation7] tests/test_readonly.py::test_readonly[src8-<lambda>-expectation8] tests/test_readonly.py::test_readonly[src9-<lambda>-expectation9] tests/test_readonly.py::test_readonly_flag[src0] tests/test_readonly.py::test_readonly_flag[src1] tests/test_readonly.py::test_readonly_nested_list tests/test_readonly.py::test_readonly_list_insert tests/test_readonly.py::test_readonly_list_insert_deep tests/test_readonly.py::test_readonly_list_append tests/test_readonly.py::test_readonly_list_change_item tests/test_readonly.py::test_readonly_list_pop tests/test_readonly.py::test_readonly_list_del tests/test_readonly.py::test_readonly_list_sort tests/test_readonly.py::test_readonly_from_cli
omegaconf/dictconfig.py omegaconf/listconfig.py omegaconf/omegaconf.py docs/source/usage.rst news/42.feature
omegaconf/dictconfig.py omegaconf/listconfig.py omegaconf/omegaconf.py docs/source/usage.rst news/42.feature