Skip to content
This repository was archived by the owner on Apr 26, 2024. It is now read-only.

Commit 68dcd2c

Browse files
authored
Re-type config paths in ConfigErrors to be StrSequences (#15615)
Part of #14809. Signed-off-by: Sean Quah <[email protected]>
1 parent e15aa00 commit 68dcd2c

File tree

8 files changed

+31
-26
lines changed

8 files changed

+31
-26
lines changed

changelog.d/15615.misc

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Re-type config paths in `ConfigError`s to be `StrSequence`s instead of `Iterable[str]`s.

synapse/config/_base.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
import pkg_resources
4545
import yaml
4646

47+
from synapse.types import StrSequence
4748
from synapse.util.templates import _create_mxc_to_http_filter, _format_ts_filter
4849

4950
logger = logging.getLogger(__name__)
@@ -58,7 +59,7 @@ class ConfigError(Exception):
5859
the problem lies.
5960
"""
6061

61-
def __init__(self, msg: str, path: Optional[Iterable[str]] = None):
62+
def __init__(self, msg: str, path: Optional[StrSequence] = None):
6263
self.msg = msg
6364
self.path = path
6465

synapse/config/_base.pyi

+2-1
Original file line numberDiff line numberDiff line change
@@ -61,9 +61,10 @@ from synapse.config import ( # noqa: F401
6161
voip,
6262
workers,
6363
)
64+
from synapse.types import StrSequence
6465

6566
class ConfigError(Exception):
66-
def __init__(self, msg: str, path: Optional[Iterable[str]] = None):
67+
def __init__(self, msg: str, path: Optional[StrSequence] = None):
6768
self.msg = msg
6869
self.path = path
6970

synapse/config/_util.py

+4-4
Original file line numberDiff line numberDiff line change
@@ -11,17 +11,17 @@
1111
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
14-
from typing import Any, Dict, Iterable, Type, TypeVar
14+
from typing import Any, Dict, Type, TypeVar
1515

1616
import jsonschema
1717
from pydantic import BaseModel, ValidationError, parse_obj_as
1818

1919
from synapse.config._base import ConfigError
20-
from synapse.types import JsonDict
20+
from synapse.types import JsonDict, StrSequence
2121

2222

2323
def validate_config(
24-
json_schema: JsonDict, config: Any, config_path: Iterable[str]
24+
json_schema: JsonDict, config: Any, config_path: StrSequence
2525
) -> None:
2626
"""Validates a config setting against a JsonSchema definition
2727
@@ -45,7 +45,7 @@ def validate_config(
4545

4646

4747
def json_error_to_config_error(
48-
e: jsonschema.ValidationError, config_path: Iterable[str]
48+
e: jsonschema.ValidationError, config_path: StrSequence
4949
) -> ConfigError:
5050
"""Converts a json validation error to a user-readable ConfigError
5151

synapse/config/oembed.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
import attr
2020
import pkg_resources
2121

22-
from synapse.types import JsonDict
22+
from synapse.types import JsonDict, StrSequence
2323

2424
from ._base import Config, ConfigError
2525
from ._util import validate_config
@@ -80,7 +80,7 @@ def _parse_and_validate_providers(
8080
)
8181

8282
def _parse_and_validate_provider(
83-
self, providers: List[JsonDict], config_path: Iterable[str]
83+
self, providers: List[JsonDict], config_path: StrSequence
8484
) -> Iterable[OEmbedEndpointConfig]:
8585
# Ensure it is the proper form.
8686
validate_config(
@@ -112,7 +112,7 @@ def _parse_and_validate_provider(
112112
api_endpoint, patterns, endpoint.get("formats")
113113
)
114114

115-
def _glob_to_pattern(self, glob: str, config_path: Iterable[str]) -> Pattern:
115+
def _glob_to_pattern(self, glob: str, config_path: StrSequence) -> Pattern:
116116
"""
117117
Convert the glob into a sane regular expression to match against. The
118118
rules followed will be slightly different for the domain portion vs.

synapse/config/server.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
from twisted.conch.ssh.keys import Key
2828

2929
from synapse.api.room_versions import KNOWN_ROOM_VERSIONS
30-
from synapse.types import JsonDict
30+
from synapse.types import JsonDict, StrSequence
3131
from synapse.util.module_loader import load_module
3232
from synapse.util.stringutils import parse_and_validate_server_name
3333

@@ -73,7 +73,7 @@ def _6to4(network: IPNetwork) -> IPNetwork:
7373
def generate_ip_set(
7474
ip_addresses: Optional[Iterable[str]],
7575
extra_addresses: Optional[Iterable[str]] = None,
76-
config_path: Optional[Iterable[str]] = None,
76+
config_path: Optional[StrSequence] = None,
7777
) -> IPSet:
7878
"""
7979
Generate an IPSet from a list of IP addresses or CIDRs.

synapse/types/__init__.py

+8
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,15 @@
8484

8585
# Collection[str] that does not include str itself; str being a Sequence[str]
8686
# is very misleading and results in bugs.
87+
#
88+
# StrCollection is an unordered collection of strings. If ordering is important,
89+
# StrSequence can be used instead.
8790
StrCollection = Union[Tuple[str, ...], List[str], AbstractSet[str]]
91+
# Sequence[str] that does not include str itself; str being a Sequence[str]
92+
# is very misleading and results in bugs.
93+
#
94+
# Unlike StrCollection, StrSequence is an ordered collection of strings.
95+
StrSequence = Union[Tuple[str, ...], List[str]]
8896

8997

9098
# Note that this seems to require inheriting *directly* from Interface in order

synapse/util/module_loader.py

+9-15
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,17 @@
1414

1515
import importlib
1616
import importlib.util
17-
import itertools
1817
from types import ModuleType
19-
from typing import Any, Iterable, Tuple, Type
18+
from typing import Any, Tuple, Type
2019

2120
import jsonschema
2221

2322
from synapse.config._base import ConfigError
2423
from synapse.config._util import json_error_to_config_error
24+
from synapse.types import StrSequence
2525

2626

27-
def load_module(provider: dict, config_path: Iterable[str]) -> Tuple[Type, Any]:
27+
def load_module(provider: dict, config_path: StrSequence) -> Tuple[Type, Any]:
2828
"""Loads a synapse module with its config
2929
3030
Args:
@@ -39,9 +39,7 @@ def load_module(provider: dict, config_path: Iterable[str]) -> Tuple[Type, Any]:
3939

4040
modulename = provider.get("module")
4141
if not isinstance(modulename, str):
42-
raise ConfigError(
43-
"expected a string", path=itertools.chain(config_path, ("module",))
44-
)
42+
raise ConfigError("expected a string", path=tuple(config_path) + ("module",))
4543

4644
# We need to import the module, and then pick the class out of
4745
# that, so we split based on the last dot.
@@ -55,19 +53,17 @@ def load_module(provider: dict, config_path: Iterable[str]) -> Tuple[Type, Any]:
5553
try:
5654
provider_config = provider_class.parse_config(module_config)
5755
except jsonschema.ValidationError as e:
58-
raise json_error_to_config_error(
59-
e, itertools.chain(config_path, ("config",))
60-
)
56+
raise json_error_to_config_error(e, tuple(config_path) + ("config",))
6157
except ConfigError as e:
6258
raise _wrap_config_error(
6359
"Failed to parse config for module %r" % (modulename,),
64-
prefix=itertools.chain(config_path, ("config",)),
60+
prefix=tuple(config_path) + ("config",),
6561
e=e,
6662
)
6763
except Exception as e:
6864
raise ConfigError(
6965
"Failed to parse config for module %r" % (modulename,),
70-
path=itertools.chain(config_path, ("config",)),
66+
path=tuple(config_path) + ("config",),
7167
) from e
7268
else:
7369
provider_config = module_config
@@ -92,17 +88,15 @@ def load_python_module(location: str) -> ModuleType:
9288
return mod
9389

9490

95-
def _wrap_config_error(
96-
msg: str, prefix: Iterable[str], e: ConfigError
97-
) -> "ConfigError":
91+
def _wrap_config_error(msg: str, prefix: StrSequence, e: ConfigError) -> "ConfigError":
9892
"""Wrap a relative ConfigError with a new path
9993
10094
This is useful when we have a ConfigError with a relative path due to a problem
10195
parsing part of the config, and we now need to set it in context.
10296
"""
10397
path = prefix
10498
if e.path:
105-
path = itertools.chain(prefix, e.path)
99+
path = tuple(prefix) + tuple(e.path)
106100

107101
e1 = ConfigError(msg, path)
108102

0 commit comments

Comments
 (0)