Skip to content

Commit

Permalink
chore: add some type checker exceptions
Browse files Browse the repository at this point in the history
  • Loading branch information
edeckers committed Jul 28, 2022
1 parent 678c2e9 commit dfcbff6
Show file tree
Hide file tree
Showing 6 changed files with 49 additions and 45 deletions.
7 changes: 4 additions & 3 deletions src/huemon/commands/internal/discover_command.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,7 @@
from huemon.sinks.sink_interface import SinkInterface
from huemon.utils.assertions import assert_exists_e, assert_num_args_e
from huemon.utils.common import fst
from huemon.utils.errors import HueError
from huemon.utils.monads.either import Either, if_left, if_right, left, right, rights
from huemon.utils.monads.either import Either, rights
from huemon.utils.monads.maybe import Maybe, maybe, of
from huemon.utils.paths import create_local_path
from huemon.utils.plugins import get_discovery_plugins_path
Expand Down Expand Up @@ -114,7 +113,9 @@ def exec(self, arguments: List[str]):
"Running `%s` command (arguments=%s)", DiscoverCommand.name(), arguments
)

error, param = assert_num_args_e(1, arguments, DiscoverCommand.name()) | fst
error, param = assert_num_args_e(1, arguments, DiscoverCommand.name()).fmap(
fst # type: ignore
)

if error:
self.processor.process(error)
Expand Down
59 changes: 31 additions & 28 deletions src/huemon/infrastructure/plugin_loader.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,23 +6,23 @@
import importlib.util
import inspect
from importlib.machinery import ModuleSpec
from modulefinder import Module
from pathlib import Path
from types import ModuleType
from typing import List, Tuple, Type, TypeVar, cast

from huemon.utils.common import fst, snd
from huemon.utils.errors import E_CODE_PLUGIN_LOADER, HueError
from huemon.utils.monads.either import Either, left, right
from huemon.utils.monads.maybe import Maybe

TA = TypeVar("TA")
TB = TypeVar("TB")


def __error(message: str) -> HueError:
return HueError(E_CODE_PLUGIN_LOADER, message)


def __lerror(message: str) -> Either[HueError, TA]:
def __lerror(message: str) -> Either[HueError, TB]:
return left(__error(message))


Expand All @@ -43,8 +43,8 @@ def __read_members_from_module(sub_class):
)


def __load_module(sm: Tuple[ModuleSpec, Module]):
spec, module = sm
def __load_module(spec_and_module: Tuple[ModuleSpec, ModuleType]):
spec, module = spec_and_module

Maybe.of(spec.loader).fmap(lambda loader: loader.exec_module(module))

Expand All @@ -54,30 +54,33 @@ def __load_module(sm: Tuple[ModuleSpec, Module]):
def __get_plugin_type(
module_name: str, path: str, sub_class: Type[TA]
) -> Either[HueError, Type[TA]]:
return (
Maybe.of(importlib.util.spec_from_file_location(module_name, path))
.maybe(
__lerror("ModuleSpec could not be loaded from the provided path"),
right,
)
.bind(
lambda spec: Maybe.of(spec.loader).maybe(
__lerror("ModuleSpec has no loader"), lambda _: right(spec)
)
)
.bind(
lambda spec: Maybe.of(importlib.util.module_from_spec(spec)).maybe(
__lerror("Module could not be loaded from ModuleSpec"),
lambda module: right((spec, module)),
),

maybe_spec = Maybe.of(importlib.util.spec_from_file_location(module_name, path))

error_or_spec: Either[HueError, ModuleSpec] = maybe_spec.maybe(
__lerror("ModuleSpec could not be loaded from the provided path"),
right, # type: ignore
).bind(
lambda spec: Maybe.of(spec.loader).maybe( # type: ignore
__lerror("ModuleSpec has no loader"), lambda _: right(spec)
)
.bind(__load_module)
.fmap(__read_members_from_module(sub_class))
.bind(
lambda plugin_types: Maybe.of(len(plugin_types) > 0).maybe(
__lerror(f"No plugin of type `{sub_class}` found"),
lambda _: right(plugin_types[0][1]),
)
)

error_or_module: Either[
HueError, Tuple[ModuleSpec, ModuleType]
] = error_or_spec.bind(
lambda spec: Maybe.of(importlib.util.module_from_spec(spec)).maybe(
__lerror("Module could not be loaded from ModuleSpec"),
lambda module: right((spec, module)), # type: ignore
),
).bind(
__load_module
)

return error_or_module.fmap(__read_members_from_module(sub_class)).bind(
lambda plugin_types: Maybe.of(len(plugin_types) > 0).maybe(
__lerror(f"No plugin of type `{sub_class}` found"),
lambda _: right(plugin_types[0][1]),
)
)

Expand Down
4 changes: 2 additions & 2 deletions src/huemon/utils/assertions.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# This source code is licensed under the MPL-2.0 license found in the
# LICENSE file in the root directory of this source tree.

from typing import List
from typing import List, Sequence

from huemon.utils.errors import (
E_CODE_ASSERT_EXISTS,
Expand All @@ -29,7 +29,7 @@ def assert_num_args(expected_number_of_arguments: int, arguments: list, context:

def assert_num_args_e(
expected_number_of_arguments: int, arguments: List[str], context: str
) -> Either[HueError, List[str]]:
) -> Either[HueError, Sequence[str]]:
try:
assert_num_args(expected_number_of_arguments, arguments, context)

Expand Down
6 changes: 3 additions & 3 deletions src/huemon/utils/common.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
from typing import Sequence, TypeVar

TA = TypeVar("TA")
TS = TypeVar("TS")


def fst(seq: Sequence[TA]) -> TA:
def fst(seq: Sequence[TS]) -> TS:
return seq[0]


def snd(seq: Sequence[TA]) -> TA:
def snd(seq: Sequence[TS]) -> TS:
return seq[1]
16 changes: 8 additions & 8 deletions src/huemon/utils/monads/either.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,18 @@
from __future__ import annotations

from argparse import ArgumentTypeError
from typing import Callable, List, Tuple, TypeVar, Union, cast
from typing import Callable, Generic, List, TypeVar, Union, cast

TA = TypeVar("TA")
TB = TypeVar("TB")
TC = TypeVar("TC")


class Either(Tuple[TA, TB]): # pylint: disable=too-few-public-methods
class Either(Generic[TA, TB]): # pylint: disable=too-few-public-methods
value: Union[TA, TB]

def __new__(cls, _):
return super(Either, cls).__new__(cls)
# def __new__(cls, _):
# return super(Either, cls).__new__(cls)

def __init__(self, value: Union[TA, TB]):
self.value = value
Expand All @@ -28,7 +28,7 @@ def __len__(self):
def __iter__(self):
return (self.if_right(None), self.if_left(None)).__iter__()

def __or__(self, map_: Callable[[TB], TC]) -> Either[TA, TC]:
def __or__(self, map_: Callable[[TB], TC]):
return self.fmap(map_)

def __ge__(self, map_: Callable[[TB], Either[TA, TC]]) -> Either[TA, TC]:
Expand Down Expand Up @@ -114,7 +114,7 @@ def either(
)


def fmap(em0: Either[TC, TA], map_: Callable[[TA], TB]) -> Either[TC, TB]:
def fmap(em0: Either[TA, TB], map_: Callable[[TB], TC]) -> Either[TA, TC]:
return bind(em0, lambda m0: pure(map_(m0)))


Expand Down Expand Up @@ -147,7 +147,7 @@ def rights(eithers: List[Either[TA, TB]]) -> List[TB]:


def right(value: TB) -> Either[TA, TB]:
return pure(value)
return _Right(value)


pure = _Right # pylint: disable=invalid-name
pure = right = _Right # pylint: disable=invalid-name
2 changes: 1 addition & 1 deletion src/huemon/utils/monads/maybe.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
class Maybe(Generic[TA]): # pylint: disable=too-few-public-methods
value: TA

def __or__(self, map_: Callable[[TA], TB]) -> Maybe[TA, TB]:
def __or__(self, map_: Callable[[TA], TB]) -> Maybe[TB]:
return self.fmap(map_)

def __ge__(self, map_: Callable[[TA], Maybe[TB]]) -> Maybe[TB]:
Expand Down

0 comments on commit dfcbff6

Please sign in to comment.