Skip to content
Permalink
Browse files

Define type protocol for flask_login-compliant user class

See
https://mypy.readthedocs.io/en/latest/protocols.html#simple-user-defined-protocols.

The `typing-extensions` requirement can be removed once PEP544 has
been accepted.
  • Loading branch information...
lukasjuhrich committed Mar 1, 2019
1 parent 1113796 commit 2e9a33fda28a55740284906ceea07f7360779f21
Showing with 22 additions and 7 deletions.
  1. +1 −0 build/requirements/requirements.txt
  2. +6 −6 sipa/backends/datasource.py
  3. +2 −1 sipa/backends/extension.py
  4. +13 −0 sipa/backends/types.py
@@ -18,3 +18,4 @@ blinker~=1.4.0
factory-boy~=2.9.2
psycopg2~=2.7.3
Flask-QRcode~=2.0.2
typing-extensions~=3.7.2
@@ -1,11 +1,12 @@
from __future__ import annotations
from ipaddress import IPv4Network, IPv4Address
from typing import Callable, Dict, List
from typing import Callable, Dict, List, Type

from flask import Flask

from sipa.utils import argstr, compare_all_attributes, xor_hashes
from .logging import logger
from .types import UserLike


InitContextCallable = Callable[[Flask], None]
@@ -17,7 +18,7 @@ class DataSource:
This class provides information about the backend you defined, for
instance the user class.
"""
def __init__(self, name: str, user_class: type, mail_server: str,
def __init__(self, name: str, user_class: Type[UserLike], mail_server: str,
webmailer_url: str = None,
support_mail: str = None,
init_context: InitContextCallable = None) -> None:
@@ -27,11 +28,10 @@ def __init__(self, name: str, user_class: type, mail_server: str,
#: what you register onto your `Backends` object.
self.name = name

class _user_class(user_class):
class _user_class(user_class): # type: ignore
datasource = self
#: the user_class used in the sense of ``flask_login``. See
#: :py:class:`~.user.BaseUser`
self.user_class = _user_class
#: the user_class used in the sense of ``flask_login``.
self.user_class: Type[UserLike] = _user_class

#: The mail server to be appended to a user's login in order
#: to construct the mail address.
@@ -12,6 +12,7 @@
from .datasource import DataSource, Dormitory
from .logging import logger
from .exceptions import InvalidConfiguration
from .types import UserLike


def evaluates_uniquely(objects, func) -> bool:
@@ -282,7 +283,7 @@ def preferred_dormitory_name(self) -> Optional[str]:
if dormitory:
return dormitory.name

def user_from_ip(self, ip: str) -> Optional[object]:
def user_from_ip(self, ip: str) -> Optional[UserLike]:
"""Return the User that corresponds to ``ip`` according to the
datasource.
@@ -0,0 +1,13 @@
from typing_extensions import Protocol


# noinspection PyPropertyDefinition
class UserLike(Protocol):
@property
def is_active(self) -> bool: ...

@property
def is_authenticated(self) -> bool: ...

@property
def is_anonymous(self) -> bool: ...

0 comments on commit 2e9a33f

Please sign in to comment.
You can’t perform that action at this time.