Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

mypy typing expansion #206

Draft
wants to merge 7 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 4 additions & 7 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,11 @@ repos:
rev: v1.6.1
hooks:
- id: mypy
exclude : "integration_tests/docker"
exclude : "integration_tests/docker|bin"
language_version: "3.10"
additional_dependencies:
- "types-requests"
- "types-pyyaml"
- "wazo_auth_client@https://github.com/wazo-platform/wazo-auth-client/archive/master.zip"
- "xivo@https://github.com/wazo-platform/xivo-lib-python/archive/master.zip"
- "wazo_bus@https://github.com/wazo-platform/wazo-bus/archive/master.zip"
args: [
"--python-executable=.tox/py39/bin/python"
]
# Automatically update to modern python (as modern as allowed by your Python version)
- repo: https://github.com/asottile/pyupgrade
rev: v3.15.0
Expand Down
12 changes: 10 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,18 @@ ignore = [
profile = "black"
py_version = 39


[tool.mypy]
python_version = "3.10"
show_error_codes = true
check_untyped_defs = true
warn_unused_configs = true
ignore_missing_imports = true
ignore_errors = true

[[tool.mypy.overrides]]
module = ["wazo_dird.plugins.config.*"]
module = [
"wazo_dird.plugins.config.*",
"wazo_dird.auth"
]
ignore_errors = false
ignore_missing_imports = false
3 changes: 3 additions & 0 deletions test-requirements.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
pyhamcrest
pytest
types-requests
types-pyyaml
types-flask
32 changes: 21 additions & 11 deletions wazo_dird/auth.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
# Copyright 2015-2023 The Wazo Authors (see the AUTHORS file)
# Copyright 2015-2024 The Wazo Authors (see the AUTHORS file)
# SPDX-License-Identifier: GPL-3.0-or-later
from __future__ import annotations

import logging
from typing import Any, Callable, TypeVar, cast

from wazo_auth_client import Client
from werkzeug.local import LocalProxy as Proxy
Expand All @@ -11,44 +13,52 @@
from .exception import MasterTenantNotInitiatedException
from .http_server import app

F = TypeVar(
'F',
bound=Callable[..., Any],
)

Decorator = Callable[[F], F]

logger = logging.getLogger(__name__)

auth_config = None
auth_client = None
auth_config: dict[str, Any] | None = None
auth_client: Client | None = None


def set_auth_config(config):
def set_auth_config(config: dict[str, Any]) -> None:
global auth_config
auth_config = config


def client():
def client() -> Client:
global auth_client
if not auth_client:
auth_client = Client(**auth_config)
return auth_client


def required_master_tenant():
return required_tenant(master_tenant_uuid)
def required_master_tenant(*args: Any) -> Decorator[F]:
wrapper = required_tenant(cast(str, master_tenant_uuid))
return wrapper


def init_master_tenant(token):
def init_master_tenant(token: dict[str, Any]) -> None:
tenant_uuid = token['metadata']['tenant_uuid']
app.config['auth']['master_tenant_uuid'] = tenant_uuid


def provide_status(status):
def provide_status(status: dict[str, Any]) -> None:
status['master_tenant']['status'] = (
Status.ok if app.config['auth'].get('master_tenant_uuid') else Status.fail
)


def get_master_tenant_uuid():
def get_master_tenant_uuid() -> str:
if not app:
raise Exception('Flask application is not configured')

tenant_uuid = app.config['auth'].get('master_tenant_uuid')
tenant_uuid: str | None = app.config['auth'].get('master_tenant_uuid')
if not tenant_uuid:
raise MasterTenantNotInitiatedException()

Expand Down
4 changes: 2 additions & 2 deletions wazo_dird/exception.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Copyright 2015-2023 The Wazo Authors (see the AUTHORS file)
# Copyright 2015-2024 The Wazo Authors (see the AUTHORS file)
# SPDX-License-Identifier: GPL-3.0-or-later
from __future__ import annotations

Expand Down Expand Up @@ -210,6 +210,6 @@ def __init__(self, confd_client, error):


class MasterTenantNotInitiatedException(APIException):
def __init__(self):
def __init__(self) -> None:
error_message = 'wazo-dird master tenant is not initiated'
super().__init__(503, error_message, 'matser-tenant-not-initiated')
24 changes: 14 additions & 10 deletions wazo_dird/plugins/config/http.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,32 +2,36 @@
# SPDX-License-Identifier: GPL-3.0-or-later
from __future__ import annotations

from typing import Any, cast

from flask import request
from jsonpatch import JsonPatch

from wazo_dird.auth import required_acl, required_master_tenant
from wazo_dird.http import AuthResource
from wazo_dird.plugins.config_service.plugin import Service as ConfigService

from .schemas import config_patch_schema

ConfigResponse = dict[str, Any]

class Config(AuthResource):
_config_service = None

@classmethod
def configure(cls, config_service):
cls._config_service = config_service
class Config(AuthResource):
def __init__(self, config_service: ConfigService):
self._config_service = config_service

@required_master_tenant()
@required_acl('dird.config.read')
def get(self):
@required_master_tenant()
def get(self) -> ConfigResponse:
config = self._config_service.get_config()
return dict(config)

@required_master_tenant()
@required_acl('dird.config.update')
def patch(self):
config_patch = config_patch_schema.load(request.get_json(), many=True)
@required_master_tenant()
def patch(self) -> tuple[ConfigResponse, int]:
config_patch = config_patch_schema.load(
cast(dict[str, Any], request.get_json()), many=True
)
config = self._config_service.get_config()
patched_config = JsonPatch(config_patch).apply(config)
self._config_service.update_config(patched_config)
Expand Down
5 changes: 3 additions & 2 deletions wazo_dird/plugins/config/plugin.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
# Copyright 2016-2023 The Wazo Authors (see the AUTHORS file)
# Copyright 2016-2024 The Wazo Authors (see the AUTHORS file)
# SPDX-License-Identifier: GPL-3.0-or-later

import logging

from build.lib.wazo_dird.plugin_manager import ViewDependencies
from wazo_dird import BaseViewPlugin

from .http import Config
Expand All @@ -13,7 +14,7 @@
class ConfigViewPlugin(BaseViewPlugin):
url = '/config'

def load(self, dependencies):
def load(self, dependencies: ViewDependencies) -> None:
api = dependencies['api']
config_service = dependencies['services'].get('config')
if not config_service:
Expand Down
8 changes: 6 additions & 2 deletions wazo_dird/plugins/config_service/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

import logging
import threading
from typing import Any

from wazo_bus.resources.auth.events import TenantCreatedEvent

Expand Down Expand Up @@ -140,19 +141,22 @@ def load(self, dependencies):
return Service(config, bus, controller)


ConfigValue = dict[str, Any]


class Service:
# Changing root logger log-level requires application-wide lock.
# This lock will be shared across all instances.
_lock = threading.Lock()

def __init__(self, config, bus, controller):
self._bus = bus
self._config = config
self._config: ConfigValue = config
self._controller = controller

self._bus.subscribe(TenantCreatedEvent.name, self._on_new_tenant_event)

def get_config(self):
def get_config(self) -> ConfigValue:
return self._config

def update_config(self, config: dict) -> None:
Expand Down