Esempio n. 1
0
    def test_either_right_functor_law2(self) -> None:
        """fmap (f . g) x = fmap f (fmap g x)"""
        def f(x: int) -> int:
            return x + 10

        def g(x: int) -> int:
            return x * 10

        self.assertEqual(
            Right(42).map(f).map(g),
            Right(42).map(lambda x: g(f(x))))
Esempio n. 2
0
def test_dispatch_to_response_with_global_methods():
    @method
    def ping():
        return Success("pong")

    response = dispatch_to_response('{"jsonrpc": "2.0", "method": "ping", "id": 1}')
    assert response == Right(SuccessResponse("pong", 1))
Esempio n. 3
0
def test_validate_result_object_method():
    class FooClass:
        def foo(self, one, two):
            return "bar"

    f = FooClass().foo
    assert validate_args(Request("f", ["one", "two"], NOID), NOCONTEXT, f) == Right(f)
Esempio n. 4
0
def test_to_serializable_SuccessResponse():
    assert to_serializable(Right(SuccessResponse(sentinel.result,
                                                 sentinel.id))) == {
                                                     "jsonrpc": "2.0",
                                                     "result": sentinel.result,
                                                     "id": sentinel.id,
                                                 }
Esempio n. 5
0
def get_method(methods: Methods, method_name: str) -> Either[ErrorResult, Method]:
    """Get the requested method from the methods dict.

    Returns: Either the function to be called, or a Method Not Found result.
    """
    try:
        return Right(methods[method_name])
    except KeyError:
        return Left(MethodNotFoundResult(method_name))
Esempio n. 6
0
    def validate_price_range(ctx: dict) -> Either:
        price_query = price_range

        if not price_query:
            return Right(ctx)

        try:
            price_query = price_query.strip().split(',')
            price_query.sort()
            lower_limit, upper_limit = map(int, price_query)
            if lower_limit < 0 or upper_limit < 0:
                raise ValueError
            price_query = Q(categories__services__price__range=(lower_limit,
                                                                upper_limit))
            return Right(
                dict(condition=ctx.get('condition').add(price_query, Q.AND)))
        except ValueError:
            return Left(dict(error_code=ListDoctors.INVALID_PRICE_RANGE))
Esempio n. 7
0
async def test_dispatch_to_response_pure_success():
    assert (await dispatch_to_response_pure(
        deserializer=default_deserializer,
        validator=default_validator,
        post_process=identity,
        context=NOCONTEXT,
        methods={"ping": ping},
        request='{"jsonrpc": "2.0", "method": "ping", "id": 1}',
    ) == Right(SuccessResponse("pong", 1)))
Esempio n. 8
0
def test_dispatch_deserialized():
    assert (
        dispatch_deserialized(
            methods={"ping": ping},
            context=NOCONTEXT,
            post_process=identity,
            deserialized={"jsonrpc": "2.0", "method": "ping", "id": 1},
        )
        == Right(SuccessResponse("pong", 1))
    )
Esempio n. 9
0
async def test_dispatch_deserialized():
    assert (await dispatch_deserialized(
        {"ping": ping},
        NOCONTEXT,
        identity,
        {
            "jsonrpc": "2.0",
            "method": "ping",
            "id": 1
        },
    ) == Right(SuccessResponse("pong", 1)))
Esempio n. 10
0
def validate_args(
    request: Request, context: Any, func: Method
) -> Either[ErrorResult, Method]:
    """Ensure the method can be called with the arguments given.

    Returns: Either the function to be called, or an Invalid Params error result.
    """
    try:
        signature(func).bind(*extract_args(request, context), **extract_kwargs(request))
    except TypeError as exc:
        return Left(InvalidParamsResult(str(exc)))
    return Right(func)
Esempio n. 11
0
    def generate_filter(ctx: dict) -> Right:
        condition = ctx.get('condition')

        if district:
            condition.add(Q(district=district.strip().lower()), Q.AND)
        if category:
            condition.add(Q(categories__query_name=category.strip().lower()),
                          Q.AND)
        if language:
            condition.add(Q(languages__query_name=language.strip().lower()),
                          Q.AND)

        return Right(dict(condition=condition))
Esempio n. 12
0
def get_doctor_by_id(doctor_id: str) -> dict:
    def get_doctor_object(ctx: dict) -> Either:
        doctor = Doctor.objects.filter(pk=ctx.get('doctor_id')).first()
        if not doctor:
            return Left(dict(ctx, error_code=GetDoctor.DOCTOR_NOT_FOUND))
        return Right(dict(doctor=DoctorSerializer(doctor).data))

    try:
        result: Either = Right(dict(doctor_id=doctor_id)) | get_doctor_object

        return result.value
    except Exception:
        return dict(error_code=GetDoctor.INTERNAL_SERVER_ERROR)
Esempio n. 13
0
def deserialize_request(
    deserializer: Callable[[str], Deserialized], request: str
) -> Either[ErrorResponse, Deserialized]:
    """Parse the JSON request string.

    Returns: Either the deserialized request or a "Parse Error" response.
    """
    try:
        return Right(deserializer(request))
    # Since the deserializer is unknown, the specific exception that will be raised is
    # also unknown. Any exception raised we assume the request is invalid, return a
    # parse error response.
    except Exception as exc:
        return Left(ParseErrorResponse(str(exc)))
Esempio n. 14
0
def list_doctors(district: Union[str, None] = None,
                 category: Union[str, None] = None,
                 language: Union[str, None] = None,
                 price_range: Union[str, None] = None) -> dict:
    def validate_price_range(ctx: dict) -> Either:
        price_query = price_range

        if not price_query:
            return Right(ctx)

        try:
            price_query = price_query.strip().split(',')
            price_query.sort()
            lower_limit, upper_limit = map(int, price_query)
            if lower_limit < 0 or upper_limit < 0:
                raise ValueError
            price_query = Q(categories__services__price__range=(lower_limit,
                                                                upper_limit))
            return Right(
                dict(condition=ctx.get('condition').add(price_query, Q.AND)))
        except ValueError:
            return Left(dict(error_code=ListDoctors.INVALID_PRICE_RANGE))

    def generate_filter(ctx: dict) -> Right:
        condition = ctx.get('condition')

        if district:
            condition.add(Q(district=district.strip().lower()), Q.AND)
        if category:
            condition.add(Q(categories__query_name=category.strip().lower()),
                          Q.AND)
        if language:
            condition.add(Q(languages__query_name=language.strip().lower()),
                          Q.AND)

        return Right(dict(condition=condition))

    def filter_doctors(ctx: dict) -> Right:
        doctors = Doctor.objects.filter(ctx.get('condition')).distinct()
        if not doctors:
            return Right(dict(doctors=list()))
        return Right(dict(doctors=DoctorSerializer(doctors, many=True).data))

    try:
        result: Either = Right(dict(condition=Q())) | validate_price_range |\
                         generate_filter | filter_doctors
        return result.value

    except Exception:
        return dict(error_code=ListDoctors.INTERNAL_SERVER_ERROR)
Esempio n. 15
0
def test_examples_positionals():
    def subtract(minuend, subtrahend):
        return Success(minuend - subtrahend)

    response = dispatch_to_response_pure(
        methods={"subtract": subtract},
        context=NOCONTEXT,
        validator=default_validator,
        post_process=identity,
        deserializer=default_deserializer,
        request='{"jsonrpc": "2.0", "method": "subtract", "params": [42, 23], "id": 1}',
    )
    assert response == Right(SuccessResponse(19, 1))

    # Second example
    response = dispatch_to_response_pure(
        methods={"subtract": subtract},
        context=NOCONTEXT,
        validator=default_validator,
        post_process=identity,
        deserializer=default_deserializer,
        request='{"jsonrpc": "2.0", "method": "subtract", "params": [23, 42], "id": 2}',
    )
    assert response == Right(SuccessResponse(-19, 2))
Esempio n. 16
0
def test_examples_nameds():
    def subtract(**kwargs):
        return Success(kwargs["minuend"] - kwargs["subtrahend"])

    response = dispatch_to_response_pure(
        methods={"subtract": subtract},
        context=NOCONTEXT,
        validator=default_validator,
        post_process=identity,
        deserializer=default_deserializer,
        request='{"jsonrpc": "2.0", "method": "subtract", "params": {"subtrahend": 23, "minuend": 42}, "id": 3}',
    )
    assert response == Right(SuccessResponse(19, 3))

    # Second example
    response = dispatch_to_response_pure(
        methods={"subtract": subtract},
        context=NOCONTEXT,
        validator=default_validator,
        post_process=identity,
        deserializer=default_deserializer,
        request='{"jsonrpc": "2.0", "method": "subtract", "params": {"minuend": 42, "subtrahend": 23}, "id": 4}',
    )
    assert response == Right(SuccessResponse(19, 4))
Esempio n. 17
0
def validate_request(
    validator: Callable[[Deserialized], Deserialized], request: Deserialized
) -> Either[ErrorResponse, Deserialized]:
    """Validate the request against a JSON-RPC schema.

    Ensures the parsed request is valid JSON-RPC.

    Returns: Either the same request passed in or an Invalid request response.
    """
    try:
        validator(request)
    # Since the validator is unknown, the specific exception that will be raised is also
    # unknown. Any exception raised we assume the request is invalid and  return an
    # "invalid request" response.
    except Exception as exc:
        return Left(InvalidRequestResponse("The request failed schema validation"))
    return Right(request)
Esempio n. 18
0
def to_response(request: Request, result: Result) -> Response:
    """Maps a Request plus a Result to a Response. A Response is just a Result plus the
    id from the original Request.

    Raises: AssertionError if the request is a notification. Notifications can't be
        responded to. If a notification is given and AssertionError is raised, we should
        respond with Server Error, because notifications should have been removed by
        this stage.

    Returns: A Response.
    """
    assert request.id is not NOID
    return (
        Left(ErrorResponse(**result._error._asdict(), id=request.id))
        if isinstance(result, Left)
        else Right(SuccessResponse(**result._value._asdict(), id=request.id))
    )
Esempio n. 19
0
 def test_either_right_map(self) -> None:
     a = Right(42).map(lambda x: x * 10)
     self.assertEqual(a, Right(420))
Esempio n. 20
0
 def test_right_applicative_3(self) -> None:
     a = Right.pure(lambda x, y: x + y).apply(Right(42)).apply(
         Left("error"))
     self.assertEqual(a, Left("error"))
Esempio n. 21
0
 def test_right_applicative_1(self) -> None:
     a = Right.pure(lambda x, y: x + y).apply(Right(2)).apply(Right(40))
     self.assertNotEqual(a, Left(42))
     self.assertEqual(a, Right(42))
Esempio n. 22
0
 def test_right_applicative_3(self):
     a = Right.pure(lambda x, y: x+y).apply(Right(42)).apply(Left("error"))
     self.assertEquals(a, Left("error"))
Esempio n. 23
0
async def test_call():
    assert await call(Request("ping", [], 1), NOCONTEXT,
                      ping) == Right(SuccessResult("pong"))
Esempio n. 24
0
def Success(*args: Any, **kwargs: Any) -> Either[ErrorResult, SuccessResult]:
    return Right(SuccessResult(*args, **kwargs))
Esempio n. 25
0
 def test_either_monad_right_bind_right(self) -> None:
     m = Right(42).bind(lambda x: Right(x * 10))
     self.assertEqual(m, Right(420))
Esempio n. 26
0
async def test_dispatch_to_response():
    assert await dispatch_to_response(
        '{"jsonrpc": "2.0", "method": "ping", "id": 1}', {"ping": ping}
    ) == Right(SuccessResponse("pong", 1))
Esempio n. 27
0
 def test_either_monad_right_bind_left(self) -> None:
     """Nothing >>= \\x -> return (x*10)"""
     m = Left("error").bind(lambda x: Right(x * 10))
     self.assertEqual(m, Left("error"))
Esempio n. 28
0
def test_Success():
    assert Success() == Right(SuccessResult(None))
Esempio n. 29
0
async def test_dispatch_request():
    request = Request("ping", [], 1)
    assert await dispatch_request({"ping": ping}, NOCONTEXT, request) == (
        request,
        Right(SuccessResult("pong")),
    )
Esempio n. 30
0
    def test_either_right_functor_law1(self) -> None:
        """fmap id = id"""

        self.assertEqual(Right(3).map(lambda x: x), Right(3))
Esempio n. 31
0
 def filter_doctors(ctx: dict) -> Right:
     doctors = Doctor.objects.filter(ctx.get('condition')).distinct()
     if not doctors:
         return Right(dict(doctors=list()))
     return Right(dict(doctors=DoctorSerializer(doctors, many=True).data))
Esempio n. 32
0
 def test_right_applicative_1(self):
     a = Right.pure(lambda x, y: x+y).apply(Right(2)).apply(Right(40))
     self.assertNotEquals(a, Left(42))
     self.assertEquals(a, Right(42))