Skip to content

Commit

Permalink
Use new typing features from 3.10
Browse files Browse the repository at this point in the history
  • Loading branch information
icgood committed Jan 8, 2022
1 parent 65ccea6 commit 6d34650
Show file tree
Hide file tree
Showing 86 changed files with 463 additions and 518 deletions.
15 changes: 7 additions & 8 deletions pymap/admin/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
from contextlib import AsyncExitStack
from datetime import datetime, timedelta, timezone
from ssl import SSLContext
from typing import Optional

from grpclib.events import listen, RecvRequest
from grpclib.health.check import ServiceStatus
Expand Down Expand Up @@ -59,7 +58,7 @@ def add_arguments(cls, parser: ArgumentParser) -> None:
help=SUPPRESS)

def _init_admin_token(self) -> None:
expiration: Optional[datetime] = None
expiration: datetime | None = None
if self.config.args.admin_token_duration:
duration_sec: int = self.config.args.admin_token_duration
duration = timedelta(seconds=duration_sec)
Expand Down Expand Up @@ -97,9 +96,9 @@ def _get_health(self) -> Handler:
async def start(self, stack: AsyncExitStack) -> None:
self._init_admin_token()
backend = self.backend
path: Optional[str] = self.config.args.admin_path
host: Optional[str] = self.config.args.admin_host
port: Optional[int] = self.config.args.admin_port
path: str | None = self.config.args.admin_path
host: str | None = self.config.args.admin_host
port: int | None = self.config.args.admin_port
server_handlers: list[Handler] = [self._get_health()]
server_handlers.extend(handler(backend) for _, handler in handlers)
ssl = self.config.ssl_context
Expand All @@ -114,15 +113,15 @@ def _new_server(self, server_handlers: Sequence[Handler]) -> Server:
return server

async def _start_local(self, server_handlers: Sequence[Handler],
path: Optional[str]) -> Task[None]:
path: str | None) -> Task[None]:
server = self._new_server(server_handlers)
path = str(socket_file.get_temp(mkdir=True))
await server.start(path=path)
return asyncio.create_task(self._run(server))

async def _start(self, server_handlers: Sequence[Handler],
host: Optional[str], port: Optional[int],
ssl: Optional[SSLContext]) -> Task[None]:
host: str | None, port: int | None,
ssl: SSLContext | None) -> Task[None]:
server = self._new_server(server_handlers)
await server.start(host=host, port=port, ssl=ssl, reuse_address=True)
return asyncio.create_task(self._run(server))
Expand Down
17 changes: 14 additions & 3 deletions pymap/admin/handlers/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from abc import ABCMeta
from collections.abc import Mapping, Set, AsyncGenerator
from contextlib import closing, asynccontextmanager, AsyncExitStack
from typing import Final
from typing import TypeAlias, Final

from pymap.context import cluster_metadata, connection_exit
from pymap.exceptions import InvalidAuth, ResponseError
Expand All @@ -19,6 +19,8 @@

__all__ = ['handlers', 'BaseHandler', 'LoginHandler']

_Metadata: TypeAlias = Mapping[str, str | bytes] | None

#: Registers new admin handler plugins.
handlers: Plugin[type[BaseHandler]] = Plugin('pymap.admin.handlers')

Expand Down Expand Up @@ -68,8 +70,16 @@ async def catch_errors(self, command: str) -> AsyncGenerator[Result, None]:
result.response = bytes(exc.get_response(b'.'))
result.key = type(exc).__name__

def _get_token(self, metadata: _Metadata) -> str:
if metadata is not None:
token = metadata['auth-token']
assert isinstance(token, str)
return token
else:
raise KeyError()

@asynccontextmanager
async def login_as(self, metadata: Mapping[str, str], user: str) \
async def login_as(self, metadata: _Metadata, user: str) \
-> AsyncGenerator[IdentityInterface, None]:
"""Context manager to login and get an identity object.
Expand All @@ -83,7 +93,8 @@ async def login_as(self, metadata: Mapping[str, str], user: str) \
"""
admin_keys = self._get_admin_keys()
try:
creds = self.login.tokens.parse(user, metadata['auth-token'],
token = self._get_token(metadata)
creds = self.login.tokens.parse(user, token,
admin_keys=admin_keys)
except (KeyError, ValueError) as exc:
raise InvalidAuth() from exc
Expand Down
8 changes: 4 additions & 4 deletions pymap/admin/handlers/mailbox.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from __future__ import annotations

from datetime import datetime, timezone
from typing import Optional
from typing import TypeAlias

from grpclib.server import Stream
from pymap.parsing.message import AppendMessage
Expand All @@ -14,7 +14,7 @@

__all__ = ['MailboxHandlers']

_AppendStream = Stream[AppendRequest, AppendResponse]
_AppendStream: TypeAlias = Stream[AppendRequest, AppendResponse]


class MailboxHandlers(MailboxBase, BaseHandler):
Expand Down Expand Up @@ -56,8 +56,8 @@ async def Append(self, stream: _AppendStream) -> None:
when = datetime.fromtimestamp(request.when, timezone.utc)
append_msg = AppendMessage(request.data, when, flag_set,
ExtensionOptions.empty())
validity: Optional[int] = None
uid: Optional[int] = None
validity: int | None = None
uid: int | None = None
async with self.catch_errors('Append') as result, \
self.login_as(stream.metadata, request.user) as identity, \
self.with_session(identity) as session:
Expand Down
10 changes: 5 additions & 5 deletions pymap/admin/handlers/system.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from __future__ import annotations

from datetime import datetime
from typing import Optional
from typing import TypeAlias

from grpclib.server import Stream
from pymap import __version__ as pymap_version
Expand All @@ -16,8 +16,8 @@

__all__ = ['SystemHandlers']

_LoginStream = Stream[LoginRequest, LoginResponse]
_PingStream = Stream[PingRequest, PingResponse]
_LoginStream: TypeAlias = Stream[LoginRequest, LoginResponse]
_PingStream: TypeAlias = Stream[PingRequest, PingResponse]


class SystemHandlers(SystemBase, BaseHandler):
Expand All @@ -43,11 +43,11 @@ async def Login(self, stream: _LoginStream) -> None:
"""
request = await stream.recv_message()
assert request is not None
bearer_token: Optional[str] = None
bearer_token: str | None = None
async with self.catch_errors('Login') as result:
credentials = AuthenticationCredentials(
request.authcid, request.secret, request.authzid)
expiration: Optional[datetime] = None
expiration: datetime | None = None
if request.HasField('token_expiration'):
expiration = datetime.fromtimestamp(request.token_expiration)
identity = await self.login.authenticate(credentials)
Expand Down
24 changes: 12 additions & 12 deletions pymap/admin/handlers/user.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

from __future__ import annotations

from typing import Optional
from typing import TypeAlias

from grpclib.server import Stream
from pymap.user import UserMetadata
Expand All @@ -13,9 +13,9 @@

__all__ = ['UserHandlers']

_GetUserStream = Stream[GetUserRequest, UserResponse]
_SetUserStream = Stream[SetUserRequest, UserResponse]
_DeleteUserStream = Stream[DeleteUserRequest, UserResponse]
_GetUserStream: TypeAlias = Stream[GetUserRequest, UserResponse]
_SetUserStream: TypeAlias = Stream[SetUserRequest, UserResponse]
_DeleteUserStream: TypeAlias = Stream[DeleteUserRequest, UserResponse]


class UserHandlers(UserBase, BaseHandler):
Expand All @@ -39,10 +39,10 @@ async def GetUser(self, stream: _GetUserStream) -> None:
"""
request = await stream.recv_message()
assert request is not None
username: Optional[str] = None
user_data: Optional[UserData] = None
async with self.catch_errors('GetUser') as result, \
self.login_as(stream.metadata, request.user) as identity:
username: str | None = None
user_data: UserData | None = None
async with (self.catch_errors('GetUser') as result,
self.login_as(stream.metadata, request.user) as identity):
username = identity.name
metadata = await identity.get()
user_data = UserData(params=metadata.params)
Expand All @@ -64,8 +64,8 @@ async def SetUser(self, stream: _SetUserStream) -> None:
"""
request = await stream.recv_message()
assert request is not None
async with self.catch_errors('SetUser') as result, \
self.login_as(stream.metadata, request.user) as identity:
async with (self.catch_errors('SetUser') as result,
self.login_as(stream.metadata, request.user) as identity):
user_data = request.data
password = self.config.hash_context.hash(user_data.password) \
if user_data.HasField('password') else None
Expand All @@ -87,8 +87,8 @@ async def DeleteUser(self, stream: _DeleteUserStream) -> None:
"""
request = await stream.recv_message()
assert request is not None
async with self.catch_errors('DeleteUser') as result, \
self.login_as(stream.metadata, request.user) as identity:
async with (self.catch_errors('DeleteUser') as result,
self.login_as(stream.metadata, request.user) as identity):
await identity.delete()
resp = UserResponse(result=result, username=request.user)
await stream.send_message(resp)
10 changes: 5 additions & 5 deletions pymap/backend/dict/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from contextlib import closing, asynccontextmanager, AsyncExitStack
from datetime import datetime, timezone
from secrets import token_bytes
from typing import Any, Optional, Final
from typing import Any, Final

from pkg_resources import resource_listdir, resource_stream
from pysasl.creds import AuthenticationCredentials
Expand Down Expand Up @@ -173,8 +173,8 @@ def tokens(self) -> AllTokens:
async def authenticate(self, credentials: AuthenticationCredentials) \
-> Identity:
authcid = credentials.authcid
token_key: Optional[bytes] = None
role: Optional[str] = None
token_key: bytes | None = None
role: str | None = None
if credentials.authcid_type == 'login-token':
if authcid in self.tokens_dict:
authcid, token_key = self.tokens_dict[authcid]
Expand All @@ -195,7 +195,7 @@ async def authenticate(self, credentials: AuthenticationCredentials) \
class Identity(IdentityInterface):
"""The identity implementation for the dict backend."""

def __init__(self, name: str, login: Login, role: Optional[str]) -> None:
def __init__(self, name: str, login: Login, role: str | None) -> None:
super().__init__()
self.login: Final = login
self.config: Final = login.config
Expand All @@ -206,7 +206,7 @@ def __init__(self, name: str, login: Login, role: Optional[str]) -> None:
def name(self) -> str:
return self._name

async def new_token(self, *, expiration: datetime = None) -> Optional[str]:
async def new_token(self, *, expiration: datetime = None) -> str | None:
token_id = uuid.uuid4().hex
token_key = token_bytes()
self.login.tokens_dict[token_id] = (self.name, token_key)
Expand Down
7 changes: 3 additions & 4 deletions pymap/backend/dict/filter.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
from __future__ import annotations

from collections.abc import Sequence
from typing import Optional

from pymap.filter import PluginFilterSet

Expand All @@ -14,7 +13,7 @@ class FilterSet(PluginFilterSet[bytes]):
def __init__(self) -> None:
super().__init__('sieve', bytes)
self._filters: dict[str, bytes] = {}
self._active: Optional[str] = None
self._active: str | None = None

async def put(self, name: str, value: bytes) -> None:
self._filters[name] = value
Expand Down Expand Up @@ -48,11 +47,11 @@ async def set_active(self, name: str) -> None:
async def get(self, name: str) -> bytes:
return self._filters[name]

async def get_active(self) -> Optional[bytes]:
async def get_active(self) -> bytes | None:
if self._active is None:
return None
else:
return self._filters[self._active]

async def get_all(self) -> tuple[Optional[str], Sequence[str]]:
async def get_all(self) -> tuple[str | None, Sequence[str]]:
return self._active, list(self._filters.keys())
7 changes: 3 additions & 4 deletions pymap/backend/dict/mailbox.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
from collections.abc import Iterable, Sequence, AsyncIterable
from datetime import datetime
from itertools import islice
from typing import Optional
from weakref import finalize, WeakKeyDictionary, WeakValueDictionary

from pymap.bytes import HashStream
Expand Down Expand Up @@ -254,7 +253,7 @@ async def append(self, append_msg: AppendMessage, *,
return message

async def copy(self, uid: int, destination: MailboxData, *,
recent: bool = False) -> Optional[int]:
recent: bool = False) -> int | None:
async with self.messages_lock.read_lock():
try:
message = self._messages[uid]
Expand All @@ -269,7 +268,7 @@ async def copy(self, uid: int, destination: MailboxData, *,
return dest_uid

async def move(self, uid: int, destination: MailboxData, *,
recent: bool = False) -> Optional[int]:
recent: bool = False) -> int | None:
async with self.messages_lock.write_lock():
try:
message = self._messages.pop(uid)
Expand Down Expand Up @@ -337,7 +336,7 @@ async def snapshot(self) -> MailboxSnapshot:
exists = 0
recent = 0
unseen = 0
first_unseen: Optional[int] = None
first_unseen: int | None = None
next_uid = self._max_uid + 1
async for msg in self.messages():
exists += 1
Expand Down
6 changes: 3 additions & 3 deletions pymap/backend/mailbox.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

from abc import abstractmethod
from collections.abc import Iterable, Sequence, AsyncIterable
from typing import TypeVar, Optional, Protocol
from typing import TypeVar, Protocol

from pymap.concurrent import Event
from pymap.flags import FlagOp
Expand Down Expand Up @@ -98,7 +98,7 @@ async def append(self, append_msg: AppendMessage, *,

@abstractmethod
async def copy(self: MailboxDataT, uid: int, destination: MailboxDataT, *,
recent: bool = False) -> Optional[int]:
recent: bool = False) -> int | None:
"""Copies a message, if it exists, from this mailbox to the
*destination* mailbox.
Expand All @@ -112,7 +112,7 @@ async def copy(self: MailboxDataT, uid: int, destination: MailboxDataT, *,

@abstractmethod
async def move(self: MailboxDataT, uid: int, destination: MailboxDataT, *,
recent: bool = False) -> Optional[int]:
recent: bool = False) -> int | None:
"""Moves a message, if it exists, from this mailbox to the
*destination* mailbox.
Expand Down

0 comments on commit 6d34650

Please sign in to comment.