From 68e1b9a26e16f826bbebd3680645a7b8b178db03 Mon Sep 17 00:00:00 2001 From: Patrick Cloke Date: Thu, 18 Nov 2021 13:54:11 -0500 Subject: [PATCH 01/10] Add missing type hints to appservice. --- synapse/config/__main__.py | 3 ++- synapse/config/appservice.py | 23 ++++++++++++++--------- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/synapse/config/__main__.py b/synapse/config/__main__.py index c555f5f91407..b2a7a89a3563 100644 --- a/synapse/config/__main__.py +++ b/synapse/config/__main__.py @@ -13,12 +13,13 @@ # See the License for the specific language governing permissions and # limitations under the License. import sys +from typing import List from synapse.config._base import ConfigError from synapse.config.homeserver import HomeServerConfig -def main(args): +def main(args: List[str]) -> None: action = args[1] if len(args) > 1 and args[1] == "read" else None # If we're reading a key in the config file, then `args[1]` will be `read` and `args[2]` # will be the key to read. diff --git a/synapse/config/appservice.py b/synapse/config/appservice.py index 1ebea88db2a2..e4bb7224a410 100644 --- a/synapse/config/appservice.py +++ b/synapse/config/appservice.py @@ -1,4 +1,5 @@ # Copyright 2015, 2016 OpenMarket Ltd +# Copyright 2021 The Matrix.org Foundation C.I.C. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -13,14 +14,14 @@ # limitations under the License. import logging -from typing import Dict +from typing import Dict, List from urllib import parse as urlparse import yaml from netaddr import IPSet from synapse.appservice import ApplicationService -from synapse.types import UserID +from synapse.types import JsonDict, UserID from ._base import Config, ConfigError @@ -30,12 +31,12 @@ class AppServiceConfig(Config): section = "appservice" - def read_config(self, config, **kwargs): + def read_config(self, config, **kwargs) -> None: self.app_service_config_files = config.get("app_service_config_files", []) self.notify_appservices = config.get("notify_appservices", True) self.track_appservice_user_ips = config.get("track_appservice_user_ips", False) - def generate_config_section(cls, **kwargs): + def generate_config_section(cls, **kwargs) -> str: return """\ # A list of application service config files to use # @@ -50,7 +51,9 @@ def generate_config_section(cls, **kwargs): """ -def load_appservices(hostname, config_files): +def load_appservices( + hostname: str, config_files: List[str] +) -> List[ApplicationService]: """Returns a list of Application Services from the config files.""" if not isinstance(config_files, list): logger.warning("Expected %s to be a list of AS config files.", config_files) @@ -93,7 +96,9 @@ def load_appservices(hostname, config_files): return appservices -def _load_appservice(hostname, as_info, config_filename): +def _load_appservice( + hostname: str, as_info: JsonDict, config_filename: str +) -> ApplicationService: required_string_fields = ["id", "as_token", "hs_token", "sender_localpart"] for field in required_string_fields: if not isinstance(as_info.get(field), str): @@ -115,9 +120,9 @@ def _load_appservice(hostname, as_info, config_filename): user_id = user.to_string() # Rate limiting for users of this AS is on by default (excludes sender) - rate_limited = True - if isinstance(as_info.get("rate_limited"), bool): - rate_limited = as_info.get("rate_limited") + rate_limited = as_info.get("rate_limited") + if not isinstance(rate_limited, bool): + rate_limited = True # namespace checks if not isinstance(as_info.get("namespaces"), dict): From 77b855c01f40330b597beb6702ce3d009e537d71 Mon Sep 17 00:00:00 2001 From: Patrick Cloke Date: Thu, 18 Nov 2021 14:02:40 -0500 Subject: [PATCH 02/10] Add missing type hints to SSO config modules. --- synapse/config/cas.py | 5 ++-- synapse/config/oidc.py | 58 ++++++++++++++++++++--------------------- synapse/config/saml2.py | 17 ++++++------ synapse/config/sso.py | 12 ++++----- 4 files changed, 47 insertions(+), 45 deletions(-) diff --git a/synapse/config/cas.py b/synapse/config/cas.py index 3f818140432f..6f2754092e76 100644 --- a/synapse/config/cas.py +++ b/synapse/config/cas.py @@ -1,4 +1,5 @@ # Copyright 2015, 2016 OpenMarket Ltd +# Copyright 2021 The Matrix.org Foundation C.I.C. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -28,7 +29,7 @@ class CasConfig(Config): section = "cas" - def read_config(self, config, **kwargs): + def read_config(self, config, **kwargs) -> None: cas_config = config.get("cas_config", None) self.cas_enabled = cas_config and cas_config.get("enabled", True) @@ -51,7 +52,7 @@ def read_config(self, config, **kwargs): self.cas_displayname_attribute = None self.cas_required_attributes = [] - def generate_config_section(self, config_dir_path, server_name, **kwargs): + def generate_config_section(self, config_dir_path, server_name, **kwargs) -> str: return """\ # Enable Central Authentication Service (CAS) for registration and login. # diff --git a/synapse/config/oidc.py b/synapse/config/oidc.py index 42f113cd249d..79c400fe30b8 100644 --- a/synapse/config/oidc.py +++ b/synapse/config/oidc.py @@ -14,7 +14,7 @@ # limitations under the License. from collections import Counter -from typing import Collection, Iterable, List, Mapping, Optional, Tuple, Type +from typing import Any, Collection, Iterable, List, Mapping, Optional, Tuple, Type import attr @@ -36,7 +36,7 @@ class OIDCConfig(Config): section = "oidc" - def read_config(self, config, **kwargs): + def read_config(self, config, **kwargs) -> None: self.oidc_providers = tuple(_parse_oidc_provider_configs(config)) if not self.oidc_providers: return @@ -66,7 +66,7 @@ def oidc_enabled(self) -> bool: # OIDC is enabled if we have a provider return bool(self.oidc_providers) - def generate_config_section(self, config_dir_path, server_name, **kwargs): + def generate_config_section(self, config_dir_path, server_name, **kwargs) -> str: return """\ # List of OpenID Connect (OIDC) / OAuth 2.0 identity providers, for registration # and login. @@ -495,89 +495,89 @@ def _parse_oidc_config_dict( ) -@attr.s(slots=True, frozen=True) +@attr.s(slots=True, frozen=True, auto_attribs=True) class OidcProviderClientSecretJwtKey: # a pem-encoded signing key - key = attr.ib(type=str) + key: str # properties to include in the JWT header - jwt_header = attr.ib(type=Mapping[str, str]) + jwt_header: Mapping[str, str] # properties to include in the JWT payload. - jwt_payload = attr.ib(type=Mapping[str, str]) + jwt_payload: Mapping[str, str] -@attr.s(slots=True, frozen=True) +@attr.s(slots=True, frozen=True, auto_attribs=True) class OidcProviderConfig: # a unique identifier for this identity provider. Used in the 'user_external_ids' # table, as well as the query/path parameter used in the login protocol. - idp_id = attr.ib(type=str) + idp_id: str # user-facing name for this identity provider. - idp_name = attr.ib(type=str) + idp_name: str # Optional MXC URI for icon for this IdP. - idp_icon = attr.ib(type=Optional[str]) + idp_icon: Optional[str] # Optional brand identifier for this IdP. - idp_brand = attr.ib(type=Optional[str]) + idp_brand: Optional[str] # whether the OIDC discovery mechanism is used to discover endpoints - discover = attr.ib(type=bool) + discover: bool # the OIDC issuer. Used to validate tokens and (if discovery is enabled) to # discover the provider's endpoints. - issuer = attr.ib(type=str) + issuer: str # oauth2 client id to use - client_id = attr.ib(type=str) + client_id: str # oauth2 client secret to use. if `None`, use client_secret_jwt_key to generate # a secret. - client_secret = attr.ib(type=Optional[str]) + client_secret: Optional[str] # key to use to construct a JWT to use as a client secret. May be `None` if # `client_secret` is set. - client_secret_jwt_key = attr.ib(type=Optional[OidcProviderClientSecretJwtKey]) + client_secret_jwt_key: Optional[OidcProviderClientSecretJwtKey] # auth method to use when exchanging the token. # Valid values are 'client_secret_basic', 'client_secret_post' and # 'none'. - client_auth_method = attr.ib(type=str) + client_auth_method: str # list of scopes to request - scopes = attr.ib(type=Collection[str]) + scopes: Collection[str] # the oauth2 authorization endpoint. Required if discovery is disabled. - authorization_endpoint = attr.ib(type=Optional[str]) + authorization_endpoint: Optional[str] # the oauth2 token endpoint. Required if discovery is disabled. - token_endpoint = attr.ib(type=Optional[str]) + token_endpoint: Optional[str] # the OIDC userinfo endpoint. Required if discovery is disabled and the # "openid" scope is not requested. - userinfo_endpoint = attr.ib(type=Optional[str]) + userinfo_endpoint: Optional[str] # URI where to fetch the JWKS. Required if discovery is disabled and the # "openid" scope is used. - jwks_uri = attr.ib(type=Optional[str]) + jwks_uri: Optional[str] # Whether to skip metadata verification - skip_verification = attr.ib(type=bool) + skip_verification: bool # Whether to fetch the user profile from the userinfo endpoint. Valid # values are: "auto" or "userinfo_endpoint". - user_profile_method = attr.ib(type=str) + user_profile_method: str # whether to allow a user logging in via OIDC to match a pre-existing account # instead of failing - allow_existing_users = attr.ib(type=bool) + allow_existing_users: bool # the class of the user mapping provider - user_mapping_provider_class = attr.ib(type=Type) + user_mapping_provider_class: Type # the config of the user mapping provider - user_mapping_provider_config = attr.ib() + user_mapping_provider_config: Any # required attributes to require in userinfo to allow login/registration - attribute_requirements = attr.ib(type=List[SsoAttributeRequirement]) + attribute_requirements: List[SsoAttributeRequirement] diff --git a/synapse/config/saml2.py b/synapse/config/saml2.py index ba2b0905ffe8..e02a83847557 100644 --- a/synapse/config/saml2.py +++ b/synapse/config/saml2.py @@ -1,5 +1,5 @@ # Copyright 2018 New Vector Ltd -# Copyright 2019 The Matrix.org Foundation C.I.C. +# Copyright 2019-2021 The Matrix.org Foundation C.I.C. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -18,6 +18,7 @@ from synapse.config.sso import SsoAttributeRequirement from synapse.python_dependencies import DependencyException, check_requirements +from synapse.types import JsonDict from synapse.util.module_loader import load_module, load_python_module from ._base import Config, ConfigError @@ -33,7 +34,7 @@ ) -def _dict_merge(merge_dict, into_dict): +def _dict_merge(merge_dict: dict, into_dict: dict) -> None: """Do a deep merge of two dicts Recursively merges `merge_dict` into `into_dict`: @@ -43,8 +44,8 @@ def _dict_merge(merge_dict, into_dict): the value from `merge_dict`. Args: - merge_dict (dict): dict to merge - into_dict (dict): target dict + merge_dict: dict to merge + into_dict: target dict """ for k, v in merge_dict.items(): if k not in into_dict: @@ -64,7 +65,7 @@ def _dict_merge(merge_dict, into_dict): class SAML2Config(Config): section = "saml2" - def read_config(self, config, **kwargs): + def read_config(self, config, **kwargs) -> None: self.saml2_enabled = False saml2_config = config.get("saml2_config") @@ -184,7 +185,7 @@ def read_config(self, config, **kwargs): def _default_saml_config_dict( self, required_attributes: set, optional_attributes: set - ): + ) -> JsonDict: """Generate a configuration dictionary with required and optional attributes that will be needed to process new user registration @@ -195,7 +196,7 @@ def _default_saml_config_dict( additional information to Synapse user accounts, but are not required Returns: - dict: A SAML configuration dictionary + A SAML configuration dictionary """ import saml2 @@ -222,7 +223,7 @@ def _default_saml_config_dict( }, } - def generate_config_section(self, config_dir_path, server_name, **kwargs): + def generate_config_section(self, config_dir_path, server_name, **kwargs) -> str: return """\ ## Single sign-on integration ## diff --git a/synapse/config/sso.py b/synapse/config/sso.py index 60aacb13ea40..e4a424326124 100644 --- a/synapse/config/sso.py +++ b/synapse/config/sso.py @@ -1,4 +1,4 @@ -# Copyright 2020 The Matrix.org Foundation C.I.C. +# Copyright 2020-2021 The Matrix.org Foundation C.I.C. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -29,13 +29,13 @@ ---------------------------------------------------------------------------------------""" -@attr.s(frozen=True) +@attr.s(frozen=True, auto_attribs=True) class SsoAttributeRequirement: """Object describing a single requirement for SSO attributes.""" - attribute = attr.ib(type=str) + attribute: str # If a value is not given, than the attribute must simply exist. - value = attr.ib(type=Optional[str]) + value: Optional[str] JSON_SCHEMA = { "type": "object", @@ -49,7 +49,7 @@ class SSOConfig(Config): section = "sso" - def read_config(self, config, **kwargs): + def read_config(self, config, **kwargs) -> None: sso_config: Dict[str, Any] = config.get("sso") or {} # The sso-specific template_dir @@ -106,7 +106,7 @@ def read_config(self, config, **kwargs): ) self.sso_client_whitelist.append(login_fallback_url) - def generate_config_section(self, **kwargs): + def generate_config_section(self, **kwargs) -> str: return """\ # Additional settings to use with single-sign on systems such as OpenID Connect, # SAML2 and CAS. From 93f73beda06351b3fbc35367a7f537472a9d2076 Mon Sep 17 00:00:00 2001 From: Patrick Cloke Date: Thu, 18 Nov 2021 14:11:22 -0500 Subject: [PATCH 03/10] Add type hints to caches. --- synapse/config/cache.py | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/synapse/config/cache.py b/synapse/config/cache.py index f05445553473..d9d85f98e155 100644 --- a/synapse/config/cache.py +++ b/synapse/config/cache.py @@ -1,4 +1,4 @@ -# Copyright 2019 Matrix.org Foundation C.I.C. +# Copyright 2019-2021 Matrix.org Foundation C.I.C. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -17,6 +17,8 @@ import threading from typing import Callable, Dict, Optional +import attr + from synapse.python_dependencies import DependencyException, check_requirements from ._base import Config, ConfigError @@ -34,13 +36,13 @@ _DEFAULT_EVENT_CACHE_SIZE = "10K" +@attr.s(slots=True, auto_attribs=True) class CacheProperties: - def __init__(self): - # The default factor size for all caches - self.default_factor_size = float( - os.environ.get(_CACHE_PREFIX, _DEFAULT_FACTOR_SIZE) - ) - self.resize_all_caches_func = None + # The default factor size for all caches + default_factor_size: float = float( + os.environ.get(_CACHE_PREFIX, _DEFAULT_FACTOR_SIZE) + ) + resize_all_caches_func: Optional[Callable[[], None]] = None properties = CacheProperties() @@ -62,7 +64,7 @@ def _canonicalise_cache_name(cache_name: str) -> str: def add_resizable_cache( cache_name: str, cache_resize_callback: Callable[[float], None] -): +) -> None: """Register a cache that's size can dynamically change Args: @@ -91,7 +93,7 @@ class CacheConfig(Config): _environ = os.environ @staticmethod - def reset(): + def reset() -> None: """Resets the caches to their defaults. Used for tests.""" properties.default_factor_size = float( os.environ.get(_CACHE_PREFIX, _DEFAULT_FACTOR_SIZE) @@ -100,7 +102,7 @@ def reset(): with _CACHES_LOCK: _CACHES.clear() - def generate_config_section(self, **kwargs): + def generate_config_section(self, **kwargs) -> str: return """\ ## Caching ## @@ -162,7 +164,7 @@ def generate_config_section(self, **kwargs): #sync_response_cache_duration: 2m """ - def read_config(self, config, **kwargs): + def read_config(self, config, **kwargs) -> None: self.event_cache_size = self.parse_size( config.get("event_cache_size", _DEFAULT_EVENT_CACHE_SIZE) ) @@ -232,7 +234,7 @@ def read_config(self, config, **kwargs): # needing an instance of Config properties.resize_all_caches_func = self.resize_all_caches - def resize_all_caches(self): + def resize_all_caches(self) -> None: """Ensure all cache sizes are up to date For each cache, run the mapped callback function with either From 24c9d69a2b3145ffa013ef9bd4ed061c301fa73d Mon Sep 17 00:00:00 2001 From: Patrick Cloke Date: Thu, 18 Nov 2021 14:27:05 -0500 Subject: [PATCH 04/10] Add type hints to add_arguments and read_arguments. --- synapse/config/database.py | 13 +++++++------ synapse/config/logger.py | 5 +++-- synapse/config/registration.py | 7 +++++-- synapse/config/server.py | 5 +++-- synapse/config/workers.py | 4 +++- 5 files changed, 21 insertions(+), 13 deletions(-) diff --git a/synapse/config/database.py b/synapse/config/database.py index 651e31b57621..06ccf15cd9f8 100644 --- a/synapse/config/database.py +++ b/synapse/config/database.py @@ -1,5 +1,5 @@ # Copyright 2014-2016 OpenMarket Ltd -# Copyright 2020 The Matrix.org Foundation C.I.C. +# Copyright 2020-2021 The Matrix.org Foundation C.I.C. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -12,6 +12,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +import argparse import logging import os @@ -119,7 +120,7 @@ def __init__(self, *args, **kwargs): self.databases = [] - def read_config(self, config, **kwargs): + def read_config(self, config, **kwargs) -> None: # We *experimentally* support specifying multiple databases via the # `databases` key. This is a map from a label to database config in the # same format as the `database` config option, plus an extra @@ -163,12 +164,12 @@ def read_config(self, config, **kwargs): self.databases = [DatabaseConnectionConfig("master", database_config)] self.set_databasepath(database_path) - def generate_config_section(self, data_dir_path, **kwargs): + def generate_config_section(self, data_dir_path, **kwargs) -> str: return DEFAULT_CONFIG % { "database_path": os.path.join(data_dir_path, "homeserver.db") } - def read_arguments(self, args): + def read_arguments(self, args: argparse.Namespace) -> None: """ Cases for the cli input: - If no databases are configured and no database_path is set, raise. @@ -194,7 +195,7 @@ def read_arguments(self, args): else: logger.warning(NON_SQLITE_DATABASE_PATH_WARNING) - def set_databasepath(self, database_path): + def set_databasepath(self, database_path: str) -> None: if database_path != ":memory:": database_path = self.abspath(database_path) @@ -202,7 +203,7 @@ def set_databasepath(self, database_path): self.databases[0].config["args"]["database"] = database_path @staticmethod - def add_arguments(parser): + def add_arguments(parser: argparse.ArgumentParser) -> None: db_group = parser.add_argument_group("database") db_group.add_argument( "-d", diff --git a/synapse/config/logger.py b/synapse/config/logger.py index 63aab0babe66..a9e5c932a0bc 100644 --- a/synapse/config/logger.py +++ b/synapse/config/logger.py @@ -1,4 +1,5 @@ # Copyright 2014-2016 OpenMarket Ltd +# Copyright 2021 The Matrix.org Foundation C.I.C. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -161,14 +162,14 @@ def generate_config_section(self, config_dir_path, server_name, **kwargs): % locals() ) - def read_arguments(self, args): + def read_arguments(self, args: argparse.Namespace) -> None: if args.no_redirect_stdio is not None: self.no_redirect_stdio = args.no_redirect_stdio if args.log_file is not None: raise ConfigError(LOG_FILE_ERROR) @staticmethod - def add_arguments(parser): + def add_arguments(parser: argparse.ArgumentParser) -> None: logging_group = parser.add_argument_group("logging") logging_group.add_argument( "-n", diff --git a/synapse/config/registration.py b/synapse/config/registration.py index 1ddad7cb7096..d52e272dffbd 100644 --- a/synapse/config/registration.py +++ b/synapse/config/registration.py @@ -1,4 +1,5 @@ # Copyright 2015, 2016 OpenMarket Ltd +# Copyright 2021 The Matrix.org Foundation C.I.C. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -13,6 +14,8 @@ # limitations under the License. from typing import Optional +import argparse + from synapse.api.constants import RoomCreationPreset from synapse.config._base import Config, ConfigError from synapse.types import RoomAlias, UserID @@ -362,7 +365,7 @@ def generate_config_section(self, generate_secrets=False, **kwargs): ) @staticmethod - def add_arguments(parser): + def add_arguments(parser: argparse.ArgumentParser) -> None: reg_group = parser.add_argument_group("registration") reg_group.add_argument( "--enable-registration", @@ -371,6 +374,6 @@ def add_arguments(parser): help="Enable registration for new users.", ) - def read_arguments(self, args): + def read_arguments(self, args: argparse.Namespace) -> None: if args.enable_registration is not None: self.enable_registration = strtobool(str(args.enable_registration)) diff --git a/synapse/config/server.py b/synapse/config/server.py index 8445e9dd0509..b40b3c6a0cef 100644 --- a/synapse/config/server.py +++ b/synapse/config/server.py @@ -12,6 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. +import argparse import itertools import logging import os.path @@ -1223,7 +1224,7 @@ def generate_config_section( % locals() ) - def read_arguments(self, args): + def read_arguments(self, args: argparse.Namespace) -> None: if args.manhole is not None: self.manhole = args.manhole if args.daemonize is not None: @@ -1232,7 +1233,7 @@ def read_arguments(self, args): self.print_pidfile = args.print_pidfile @staticmethod - def add_arguments(parser): + def add_arguments(parser: argparse.ArgumentParser) -> None: server_group = parser.add_argument_group("server") server_group.add_argument( "-D", diff --git a/synapse/config/workers.py b/synapse/config/workers.py index 450799203112..576f519188bb 100644 --- a/synapse/config/workers.py +++ b/synapse/config/workers.py @@ -1,4 +1,5 @@ # Copyright 2016 OpenMarket Ltd +# Copyright 2021 The Matrix.org Foundation C.I.C. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -12,6 +13,7 @@ # See the License for the specific language governing permissions and # limitations under the License. +import argparse from typing import List, Union import attr @@ -343,7 +345,7 @@ def generate_config_section(self, config_dir_path, server_name, **kwargs): #worker_replication_secret: "" """ - def read_arguments(self, args): + def read_arguments(self, args: argparse.Namespace) -> None: # We support a bunch of command line arguments that override options in # the config. A lot of these options have a worker_* prefix when running # on workers so we also have to override them when command line options From 6b8e8a6c31b4b2449220b7d27bb2e0a1741578f4 Mon Sep 17 00:00:00 2001 From: Patrick Cloke Date: Thu, 18 Nov 2021 14:35:52 -0500 Subject: [PATCH 05/10] Add missing type hints to logger. --- synapse/config/logger.py | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/synapse/config/logger.py b/synapse/config/logger.py index a9e5c932a0bc..ea69b9bd9b50 100644 --- a/synapse/config/logger.py +++ b/synapse/config/logger.py @@ -19,7 +19,7 @@ import sys import threading from string import Template -from typing import TYPE_CHECKING, Any, Dict +from typing import TYPE_CHECKING, Any, Dict, Optional import yaml from zope.interface import implementer @@ -41,6 +41,7 @@ from ._base import Config, ConfigError if TYPE_CHECKING: + from synapse.config.homeserver import HomeServerConfig from synapse.server import HomeServer DEFAULT_LOG_CONFIG = Template( @@ -142,13 +143,13 @@ class LoggingConfig(Config): section = "logging" - def read_config(self, config, **kwargs): + def read_config(self, config, **kwargs) -> None: if config.get("log_file"): raise ConfigError(LOG_FILE_ERROR) self.log_config = self.abspath(config.get("log_config")) self.no_redirect_stdio = config.get("no_redirect_stdio", False) - def generate_config_section(self, config_dir_path, server_name, **kwargs): + def generate_config_section(self, config_dir_path, server_name, **kwargs) -> str: log_config = os.path.join(config_dir_path, server_name + ".log.config") return ( """\ @@ -198,7 +199,9 @@ def generate_files(self, config: Dict[str, Any], config_dir_path: str) -> None: log_config_file.write(DEFAULT_LOG_CONFIG.substitute(log_file=log_file)) -def _setup_stdlib_logging(config, log_config_path, logBeginner: LogBeginner) -> None: +def _setup_stdlib_logging( + config: "HomeServerConfig", log_config_path: Optional[str], logBeginner: LogBeginner +) -> None: """ Set up Python standard library logging. """ @@ -231,7 +234,7 @@ def _setup_stdlib_logging(config, log_config_path, logBeginner: LogBeginner) -> log_metadata_filter = MetadataFilter({"server_name": config.server.server_name}) old_factory = logging.getLogRecordFactory() - def factory(*args, **kwargs): + def factory(*args: Any, **kwargs: Any) -> logging.LogRecord: record = old_factory(*args, **kwargs) log_context_filter.filter(record) log_metadata_filter.filter(record) @@ -298,7 +301,7 @@ def _load_logging_config(log_config_path: str) -> None: logging.config.dictConfig(log_config) -def _reload_logging_config(log_config_path): +def _reload_logging_config(log_config_path: Optional[str]) -> None: """ Reload the log configuration from the file and apply it. """ @@ -312,8 +315,8 @@ def _reload_logging_config(log_config_path): def setup_logging( hs: "HomeServer", - config, - use_worker_options=False, + config: "HomeServerConfig", + use_worker_options: bool = False, logBeginner: LogBeginner = globalLogBeginner, ) -> None: """ From 28a293b4fd2a479b739919bcb84a24b1768f1a84 Mon Sep 17 00:00:00 2001 From: Patrick Cloke Date: Fri, 19 Nov 2021 13:39:41 -0500 Subject: [PATCH 06/10] Add missing type hints to server helpers. --- synapse/app/_base.py | 3 ++- synapse/config/server.py | 15 ++++++++++----- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/synapse/app/_base.py b/synapse/app/_base.py index 807ee3d46ef1..5fc59c1be11d 100644 --- a/synapse/app/_base.py +++ b/synapse/app/_base.py @@ -32,6 +32,7 @@ Iterable, List, NoReturn, + Optional, Tuple, cast, ) @@ -129,7 +130,7 @@ def start_worker_reactor( def start_reactor( appname: str, soft_file_limit: int, - gc_thresholds: Tuple[int, int, int], + gc_thresholds: Optional[Tuple[int, int, int]], pid_file: str, daemonize: bool, print_pidfile: bool, diff --git a/synapse/config/server.py b/synapse/config/server.py index b40b3c6a0cef..ba5b95426338 100644 --- a/synapse/config/server.py +++ b/synapse/config/server.py @@ -28,6 +28,7 @@ from twisted.conch.ssh.keys import Key from synapse.api.room_versions import KNOWN_ROOM_VERSIONS +from synapse.types import JsonDict from synapse.util.module_loader import load_module from synapse.util.stringutils import parse_and_validate_server_name @@ -1275,14 +1276,16 @@ def read_gc_intervals(self, durations) -> Optional[Tuple[float, float, float]]: ) -def is_threepid_reserved(reserved_threepids, threepid): +def is_threepid_reserved( + reserved_threepids: List[JsonDict], threepid: JsonDict +) -> bool: """Check the threepid against the reserved threepid config Args: - reserved_threepids([dict]) - list of reserved threepids - threepid(dict) - The threepid to test for + reserved_threepids: List of reserved threepids + threepid: The threepid to test for Returns: - boolean Is the threepid undertest reserved_user + Is the threepid undertest reserved_user """ for tp in reserved_threepids: @@ -1291,7 +1294,9 @@ def is_threepid_reserved(reserved_threepids, threepid): return False -def read_gc_thresholds(thresholds): +def read_gc_thresholds( + thresholds: Optional[List[Any]], +) -> Optional[Tuple[int, int, int]]: """Reads the three integer thresholds for garbage collection. Ensures that the thresholds are integers if thresholds are supplied. """ From 67976b543b6585d725bfa190c69dc8aba3093bf8 Mon Sep 17 00:00:00 2001 From: Patrick Cloke Date: Fri, 19 Nov 2021 13:47:50 -0500 Subject: [PATCH 07/10] Add missing type hints to repository. --- synapse/config/repository.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/synapse/config/repository.py b/synapse/config/repository.py index 69906a98d48a..b129b9dd681c 100644 --- a/synapse/config/repository.py +++ b/synapse/config/repository.py @@ -15,11 +15,12 @@ import logging import os from collections import namedtuple -from typing import Dict, List +from typing import Dict, List, Tuple from urllib.request import getproxies_environment # type: ignore from synapse.config.server import DEFAULT_IP_RANGE_BLACKLIST, generate_ip_set from synapse.python_dependencies import DependencyException, check_requirements +from synapse.types import JsonDict from synapse.util.module_loader import load_module from ._base import Config, ConfigError @@ -57,7 +58,9 @@ ) -def parse_thumbnail_requirements(thumbnail_sizes): +def parse_thumbnail_requirements( + thumbnail_sizes: List[JsonDict], +) -> Dict[str, Tuple[ThumbnailRequirement, ...]]: """Takes a list of dictionaries with "width", "height", and "method" keys and creates a map from image media types to the thumbnail size, thumbnailing method, and thumbnail media type to precalculate @@ -69,7 +72,7 @@ def parse_thumbnail_requirements(thumbnail_sizes): Dictionary mapping from media type string to list of ThumbnailRequirement tuples. """ - requirements: Dict[str, List] = {} + requirements: Dict[str, List[ThumbnailRequirement]] = {} for size in thumbnail_sizes: width = size["width"] height = size["height"] From f61c961d666e3e5d5d19a427ec5c9d00e84a39bd Mon Sep 17 00:00:00 2001 From: Patrick Cloke Date: Tue, 30 Nov 2021 10:52:46 -0500 Subject: [PATCH 08/10] Newsfragment --- changelog.d/11465.misc | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/11465.misc diff --git a/changelog.d/11465.misc b/changelog.d/11465.misc new file mode 100644 index 000000000000..aadc938b2be3 --- /dev/null +++ b/changelog.d/11465.misc @@ -0,0 +1 @@ +Add missing type hints to `synapse.config` module. From f1eb99ea8f79b734ec60eaa605501fc5221f76c2 Mon Sep 17 00:00:00 2001 From: Patrick Cloke Date: Tue, 30 Nov 2021 12:53:17 -0500 Subject: [PATCH 09/10] Review comments. --- synapse/config/saml2.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/synapse/config/saml2.py b/synapse/config/saml2.py index e02a83847557..ec9d9f65e7b5 100644 --- a/synapse/config/saml2.py +++ b/synapse/config/saml2.py @@ -14,7 +14,7 @@ # limitations under the License. import logging -from typing import Any, List +from typing import Any, List, Set from synapse.config.sso import SsoAttributeRequirement from synapse.python_dependencies import DependencyException, check_requirements @@ -45,7 +45,7 @@ def _dict_merge(merge_dict: dict, into_dict: dict) -> None: Args: merge_dict: dict to merge - into_dict: target dict + into_dict: target dict to be modified """ for k, v in merge_dict.items(): if k not in into_dict: @@ -184,7 +184,7 @@ def read_config(self, config, **kwargs) -> None: ) def _default_saml_config_dict( - self, required_attributes: set, optional_attributes: set + self, required_attributes: Set[str], optional_attributes: Set[str] ) -> JsonDict: """Generate a configuration dictionary with required and optional attributes that will be needed to process new user registration From 8e129c85514b96ba767a116387fcbc4201a95f86 Mon Sep 17 00:00:00 2001 From: Patrick Cloke Date: Tue, 30 Nov 2021 14:00:37 -0500 Subject: [PATCH 10/10] Lint --- synapse/config/registration.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/synapse/config/registration.py b/synapse/config/registration.py index d52e272dffbd..47853199f477 100644 --- a/synapse/config/registration.py +++ b/synapse/config/registration.py @@ -12,9 +12,8 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -from typing import Optional - import argparse +from typing import Optional from synapse.api.constants import RoomCreationPreset from synapse.config._base import Config, ConfigError