Skip to content

Commit d0f4e71

Browse files
author
vvcheremushkin
committed
inject attributes into methods
1 parent aa26cf7 commit d0f4e71

File tree

4 files changed

+93
-1
lines changed

4 files changed

+93
-1
lines changed

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ def get_packages(package):
2929
"starlette<=1",
3030
"apispec<3",
3131
],
32-
version="0.0.6",
32+
version="0.0.7",
3333
url="https://github.com/slv0/start_resty",
3434
license="BSD",
3535
description="The web framework",

star_resty/inject.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import operator
2+
from typing import TypeVar, Type, Optional, Generic
3+
4+
from star_resty import Method
5+
6+
__all__ = ('attr',)
7+
8+
T = TypeVar('T')
9+
10+
11+
class InjectAttr(Generic[T]):
12+
__slots__ = ('_func',)
13+
14+
def __init__(self, name=None):
15+
if name:
16+
self._func = operator.attrgetter(name)
17+
else:
18+
self._func = None
19+
20+
def __set_name__(self, owner, name):
21+
if self._func is None:
22+
self._func = operator.attrgetter(name)
23+
24+
def __get__(self, instance: Optional[Method], owner: Type[Method]) -> T:
25+
if instance is None:
26+
return self
27+
28+
return self._func(instance.request.app)
29+
30+
31+
def attr(_: Optional[Type[T]] = None, *, name: Optional[str] = None) -> T:
32+
return InjectAttr[T](name)

star_resty/method/meta.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ def dump(content):
4545
return response_schema.dump(content)
4646
except MarshmallowError as e:
4747
raise DumpError(e) from e
48+
except (ValueError, TypeError) as e:
49+
raise DumpError(e) from e
4850

4951
return dump
5052

tests/test_inject.py

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import pytest
2+
from starlette.applications import Starlette
3+
from starlette.testclient import TestClient
4+
5+
from star_resty import Method, inject
6+
from tests.utils.method import SearchUserResponse
7+
8+
9+
class Repository:
10+
11+
@staticmethod
12+
async def get_user():
13+
return {'id': 2}
14+
15+
16+
class GetUser(Method):
17+
response_schema = SearchUserResponse
18+
19+
users_repository = inject.attr(Repository)
20+
21+
async def execute(self):
22+
return await self.users_repository.get_user()
23+
24+
25+
class GetUserInjByName(Method):
26+
response_schema = SearchUserResponse
27+
28+
users_repository = inject.attr(Repository, name='user_api')
29+
30+
async def execute(self):
31+
return await self.users_repository.get_user()
32+
33+
34+
@pytest.fixture()
35+
def app():
36+
return Starlette()
37+
38+
39+
def test_inject_attr(app):
40+
app.users_repository = Repository()
41+
app.add_route('/user', GetUser.as_endpoint(), methods=['GET'])
42+
43+
client = TestClient(app)
44+
resp = client.get('/user')
45+
assert resp.status_code == 200
46+
body = resp.json()
47+
assert body == {'id': 2}
48+
49+
50+
def test_inject_attr_by_name(app):
51+
app.user_api = Repository()
52+
app.add_route('/user', GetUserInjByName.as_endpoint(), methods=['GET'])
53+
54+
client = TestClient(app)
55+
resp = client.get('/user')
56+
assert resp.status_code == 200
57+
body = resp.json()
58+
assert body == {'id': 2}

0 commit comments

Comments
 (0)