tigrbl-tests 0.3.2.dev1__py3-none-any.whl → 0.3.3.dev1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,98 @@
1
+ import httpx
2
+ import pytest
3
+ import pytest_asyncio
4
+ from fastapi import Security
5
+ from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer
6
+
7
+ from tigrbl import Base, TigrblApi, TigrblApp
8
+ from tigrbl.engine.shortcuts import mem
9
+ from tigrbl.orm.mixins import GUIDPk
10
+ from tigrbl.specs import F, IO, S, acol
11
+ from tigrbl.types import Mapped, String
12
+
13
+ from .uvicorn_utils import run_uvicorn_in_task, stop_uvicorn_server
14
+
15
+
16
+ bearer = HTTPBearer()
17
+
18
+
19
+ def auth_dependency(
20
+ credentials: HTTPAuthorizationCredentials = Security(bearer),
21
+ ) -> HTTPAuthorizationCredentials:
22
+ return credentials
23
+
24
+
25
+ class Kappa(Base, GUIDPk):
26
+ __tablename__ = "kappa_api_app_usage"
27
+ __allow_unmapped__ = True
28
+
29
+ name: Mapped[str] = acol(
30
+ storage=S(type_=String, nullable=False),
31
+ field=F(py_type=str),
32
+ io=IO(in_verbs=("create",), out_verbs=("create", "read", "list")),
33
+ )
34
+
35
+ __tigrbl_cols__ = {"id": GUIDPk.id, "name": name}
36
+
37
+
38
+ class KappaApi(TigrblApi):
39
+ MODELS = (Kappa,)
40
+
41
+
42
+ @pytest_asyncio.fixture()
43
+ async def running_api_app():
44
+ api = KappaApi(engine=mem(async_=False))
45
+ api.set_auth(authn=auth_dependency, allow_anon=False)
46
+ api.include_models([Kappa])
47
+ api.initialize()
48
+
49
+ class KappaApp(TigrblApp):
50
+ APIS = (api,)
51
+
52
+ app = KappaApp(engine=mem(async_=False))
53
+ app.include_router(api)
54
+
55
+ base_url, server, task = await run_uvicorn_in_task(app)
56
+ try:
57
+ yield base_url
58
+ finally:
59
+ await stop_uvicorn_server(server, task)
60
+
61
+
62
+ @pytest.mark.i9n
63
+ @pytest.mark.asyncio
64
+ async def test_tigrbl_api_app_deploys_and_serves_openapi(running_api_app) -> None:
65
+ base_url = running_api_app
66
+
67
+ async with httpx.AsyncClient() as client:
68
+ openapi_resp = await client.get(f"{base_url}/openapi.json")
69
+
70
+ assert openapi_resp.status_code == 200
71
+ openapi = openapi_resp.json()
72
+ paths = openapi["paths"]
73
+
74
+ assert "/kappa" in paths
75
+ assert "/kappa/{item_id}" in paths
76
+ assert {"get", "post", "delete"}.issubset(paths["/kappa"])
77
+ assert {"get", "patch", "put", "delete"}.issubset(paths["/kappa/{item_id}"])
78
+
79
+ security_schemes = openapi.get("components", {}).get("securitySchemes", {})
80
+ assert "HTTPBearer" in security_schemes
81
+
82
+
83
+ @pytest.mark.i9n
84
+ @pytest.mark.asyncio
85
+ async def test_tigrbl_api_app_handles_authenticated_request(running_api_app) -> None:
86
+ base_url = running_api_app
87
+ headers = {"Authorization": "Bearer demo"}
88
+
89
+ async with httpx.AsyncClient() as client:
90
+ resp = await client.post(
91
+ f"{base_url}/kappa",
92
+ json={"name": "Kappa"},
93
+ headers=headers,
94
+ )
95
+
96
+ assert resp.status_code == 201
97
+ payload = resp.json()
98
+ assert payload["name"] == "Kappa"
@@ -0,0 +1,105 @@
1
+ import httpx
2
+ import pytest
3
+ import pytest_asyncio
4
+ from fastapi import Security
5
+ from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer
6
+
7
+ from tigrbl import Base, TigrblApi
8
+ from tigrbl.engine.shortcuts import mem
9
+ from tigrbl.orm.mixins import GUIDPk
10
+ from tigrbl.specs import F, IO, S, acol
11
+ from tigrbl.types import App, Mapped, String
12
+
13
+ from .uvicorn_utils import run_uvicorn_in_task, stop_uvicorn_server
14
+
15
+
16
+ bearer = HTTPBearer()
17
+
18
+
19
+ def auth_dependency(
20
+ credentials: HTTPAuthorizationCredentials = Security(bearer),
21
+ ) -> HTTPAuthorizationCredentials:
22
+ return credentials
23
+
24
+
25
+ class Alpha(Base, GUIDPk):
26
+ __tablename__ = "alpha_api_usage"
27
+ __allow_unmapped__ = True
28
+
29
+ name: Mapped[str] = acol(
30
+ storage=S(type_=String, nullable=False),
31
+ field=F(py_type=str),
32
+ io=IO(in_verbs=("create",), out_verbs=("create", "read", "list")),
33
+ )
34
+
35
+ __tigrbl_cols__ = {"id": GUIDPk.id, "name": name}
36
+
37
+
38
+ class Beta(Base, GUIDPk):
39
+ __tablename__ = "beta_api_usage"
40
+ __allow_unmapped__ = True
41
+
42
+ name: Mapped[str] = acol(
43
+ storage=S(type_=String, nullable=False),
44
+ field=F(py_type=str),
45
+ io=IO(in_verbs=("create",), out_verbs=("create", "read", "list")),
46
+ )
47
+
48
+ __tigrbl_cols__ = {"id": GUIDPk.id, "name": name}
49
+
50
+
51
+ @pytest_asyncio.fixture()
52
+ async def running_api():
53
+ app = App()
54
+ api = TigrblApi(engine=mem(async_=False))
55
+ api.set_auth(authn=auth_dependency, allow_anon=False)
56
+ api.include_models([Alpha, Beta])
57
+ api.initialize()
58
+ app.include_router(api)
59
+
60
+ base_url, server, task = await run_uvicorn_in_task(app)
61
+ try:
62
+ yield base_url
63
+ finally:
64
+ await stop_uvicorn_server(server, task)
65
+
66
+
67
+ @pytest.mark.i9n
68
+ @pytest.mark.asyncio
69
+ async def test_tigrbl_api_deploys_and_serves_openapi(running_api) -> None:
70
+ base_url = running_api
71
+
72
+ async with httpx.AsyncClient() as client:
73
+ openapi_resp = await client.get(f"{base_url}/openapi.json")
74
+
75
+ assert openapi_resp.status_code == 200
76
+ openapi = openapi_resp.json()
77
+ paths = openapi["paths"]
78
+
79
+ assert "/alpha" in paths
80
+ assert "/alpha/{item_id}" in paths
81
+ assert "/beta" in paths
82
+ assert "/beta/{item_id}" in paths
83
+ assert {"get", "post", "delete"}.issubset(paths["/alpha"])
84
+ assert {"get", "patch", "put", "delete"}.issubset(paths["/alpha/{item_id}"])
85
+
86
+ security_schemes = openapi.get("components", {}).get("securitySchemes", {})
87
+ assert "HTTPBearer" in security_schemes
88
+
89
+
90
+ @pytest.mark.i9n
91
+ @pytest.mark.asyncio
92
+ async def test_tigrbl_api_handles_authenticated_request(running_api) -> None:
93
+ base_url = running_api
94
+ headers = {"Authorization": "Bearer demo"}
95
+
96
+ async with httpx.AsyncClient() as client:
97
+ resp = await client.post(
98
+ f"{base_url}/alpha",
99
+ json={"name": "Alpha"},
100
+ headers=headers,
101
+ )
102
+
103
+ assert resp.status_code == 201
104
+ payload = resp.json()
105
+ assert payload["name"] == "Alpha"
@@ -0,0 +1,67 @@
1
+ import httpx
2
+ import pytest
3
+ import pytest_asyncio
4
+
5
+ from tigrbl import Base, TigrblApi
6
+ from tigrbl.engine.shortcuts import mem
7
+ from tigrbl.orm.mixins import GUIDPk
8
+ from tigrbl.specs import F, IO, S, acol
9
+ from tigrbl.types import App, Mapped, String
10
+
11
+ from .uvicorn_utils import run_uvicorn_in_task, stop_uvicorn_server
12
+
13
+
14
+ class Gadget(Base, GUIDPk):
15
+ __tablename__ = "gadgets_api"
16
+ __resource__ = "gadget"
17
+
18
+ name: Mapped[str] = acol(
19
+ storage=S(String, nullable=False),
20
+ field=F(py_type=str),
21
+ io=IO(in_verbs=("create",), out_verbs=("create", "read", "list")),
22
+ )
23
+
24
+
25
+ @pytest_asyncio.fixture()
26
+ async def running_api_app():
27
+ api = TigrblApi(
28
+ engine=mem(async_=False),
29
+ models=[Gadget],
30
+ prefix="/gadgets",
31
+ system_prefix="/diagnostics",
32
+ )
33
+ await api.initialize()
34
+
35
+ app = App()
36
+ app.include_router(api.router)
37
+ api.attach_diagnostics(app=app)
38
+
39
+ base_url, server, task = await run_uvicorn_in_task(app)
40
+ try:
41
+ yield base_url
42
+ finally:
43
+ await stop_uvicorn_server(server, task)
44
+
45
+
46
+ @pytest.mark.i9n
47
+ @pytest.mark.asyncio
48
+ async def test_tigrbl_api_create_gadget(running_api_app):
49
+ async with httpx.AsyncClient() as client:
50
+ response = await client.post(
51
+ f"{running_api_app}/gadgets/gadget", json={"name": "gyro"}
52
+ )
53
+
54
+ assert response.status_code == 201
55
+ payload = response.json()
56
+ assert payload["name"] == "gyro"
57
+ assert "id" in payload
58
+
59
+
60
+ @pytest.mark.i9n
61
+ @pytest.mark.asyncio
62
+ async def test_tigrbl_api_healthz(running_api_app):
63
+ async with httpx.AsyncClient() as client:
64
+ response = await client.get(f"{running_api_app}/diagnostics/healthz")
65
+
66
+ assert response.status_code == 200
67
+ assert response.json()["ok"] is True
@@ -0,0 +1,149 @@
1
+ import httpx
2
+ import pytest
3
+ import pytest_asyncio
4
+
5
+ from tigrbl import Base, TigrblApi, TigrblApp
6
+ from tigrbl.engine.shortcuts import mem
7
+ from tigrbl.orm.mixins import GUIDPk
8
+ from tigrbl.specs import F, IO, S, acol
9
+ from tigrbl.types import Mapped, String
10
+
11
+ from .uvicorn_utils import run_uvicorn_in_task, stop_uvicorn_server
12
+
13
+
14
+ class AlphaWidget(Base, GUIDPk):
15
+ __tablename__ = "alpha_widgets_alt"
16
+ __resource__ = "alpha-widget"
17
+
18
+ name: Mapped[str] = acol(
19
+ storage=S(String, nullable=False),
20
+ field=F(py_type=str),
21
+ io=IO(in_verbs=("create",), out_verbs=("create", "read", "list")),
22
+ )
23
+
24
+
25
+ class BetaWidget(Base, GUIDPk):
26
+ __tablename__ = "beta_widgets_alt"
27
+ __resource__ = "beta-widget"
28
+
29
+ name: Mapped[str] = acol(
30
+ storage=S(String, nullable=False),
31
+ field=F(py_type=str),
32
+ io=IO(in_verbs=("create",), out_verbs=("create", "read", "list")),
33
+ )
34
+
35
+
36
+ class ZetaWidget(Base, GUIDPk):
37
+ __tablename__ = "zeta_widgets_alt"
38
+ __resource__ = "zeta-widget"
39
+
40
+ name: Mapped[str] = acol(
41
+ storage=S(String, nullable=False),
42
+ field=F(py_type=str),
43
+ io=IO(in_verbs=("create",), out_verbs=("create", "read", "list")),
44
+ )
45
+
46
+
47
+ @pytest_asyncio.fixture()
48
+ async def running_app_with_apis():
49
+ engine = mem(async_=False)
50
+ alpha_api = TigrblApi(engine=engine, models=[AlphaWidget], prefix="/alpha")
51
+ beta_api = TigrblApi(engine=engine)
52
+ beta_api.include_model(BetaWidget)
53
+ zeta_api = TigrblApi(engine=engine)
54
+ zeta_api.include_model(ZetaWidget)
55
+
56
+ app = TigrblApp(engine=engine, apis=[alpha_api, (zeta_api, "/zeta")])
57
+ app.include_api(beta_api, prefix="/beta")
58
+ await app.initialize()
59
+
60
+ base_url, server, task = await run_uvicorn_in_task(app)
61
+ try:
62
+ yield base_url
63
+ finally:
64
+ await stop_uvicorn_server(server, task)
65
+
66
+
67
+ @pytest_asyncio.fixture()
68
+ async def running_app_with_api_router():
69
+ engine = mem(async_=False)
70
+ alpha_api = TigrblApi(engine=engine)
71
+ alpha_api.include_model(AlphaWidget)
72
+ beta_api = TigrblApi(engine=engine)
73
+ beta_api.include_model(BetaWidget)
74
+
75
+ app = TigrblApp(engine=engine, apis=[alpha_api])
76
+ app.include_api(beta_api, prefix="/beta")
77
+ app.include_api(alpha_api.router, prefix="/alpha")
78
+ await app.initialize()
79
+
80
+ base_url, server, task = await run_uvicorn_in_task(app)
81
+ try:
82
+ yield base_url
83
+ finally:
84
+ await stop_uvicorn_server(server, task)
85
+
86
+
87
+ @pytest.mark.i9n
88
+ @pytest.mark.asyncio
89
+ async def test_tigrbl_app_api_list_alpha(running_app_with_apis):
90
+ async with httpx.AsyncClient() as client:
91
+ response = await client.post(
92
+ f"{running_app_with_apis}/alpha/alpha-widget", json={"name": "ace"}
93
+ )
94
+
95
+ assert response.status_code == 201
96
+ payload = response.json()
97
+ assert payload["name"] == "ace"
98
+
99
+
100
+ @pytest.mark.i9n
101
+ @pytest.mark.asyncio
102
+ async def test_tigrbl_app_include_api_beta(running_app_with_apis):
103
+ async with httpx.AsyncClient() as client:
104
+ response = await client.post(
105
+ f"{running_app_with_apis}/beta/beta-widget", json={"name": "bolt"}
106
+ )
107
+
108
+ assert response.status_code == 201
109
+ payload = response.json()
110
+ assert payload["name"] == "bolt"
111
+
112
+
113
+ @pytest.mark.i9n
114
+ @pytest.mark.asyncio
115
+ async def test_tigrbl_app_api_list_zeta(running_app_with_apis):
116
+ async with httpx.AsyncClient() as client:
117
+ response = await client.post(
118
+ f"{running_app_with_apis}/zeta/zeta-widget", json={"name": "zen"}
119
+ )
120
+
121
+ assert response.status_code == 201
122
+ payload = response.json()
123
+ assert payload["name"] == "zen"
124
+
125
+
126
+ @pytest.mark.i9n
127
+ @pytest.mark.asyncio
128
+ async def test_tigrbl_app_include_api_router_alpha(running_app_with_api_router):
129
+ async with httpx.AsyncClient() as client:
130
+ response = await client.post(
131
+ f"{running_app_with_api_router}/alpha/alpha-widget", json={"name": "ace"}
132
+ )
133
+
134
+ assert response.status_code == 201
135
+ payload = response.json()
136
+ assert payload["name"] == "ace"
137
+
138
+
139
+ @pytest.mark.i9n
140
+ @pytest.mark.asyncio
141
+ async def test_tigrbl_app_include_api_router_beta(running_app_with_api_router):
142
+ async with httpx.AsyncClient() as client:
143
+ response = await client.post(
144
+ f"{running_app_with_api_router}/beta/beta-widget", json={"name": "bolt"}
145
+ )
146
+
147
+ assert response.status_code == 201
148
+ payload = response.json()
149
+ assert payload["name"] == "bolt"
@@ -0,0 +1,80 @@
1
+ import httpx
2
+ import pytest
3
+ import pytest_asyncio
4
+
5
+ from tigrbl import Base, TigrblApi, TigrblApp
6
+ from tigrbl.engine.shortcuts import mem
7
+ from tigrbl.orm.mixins import GUIDPk
8
+ from tigrbl.specs import F, IO, S, acol
9
+ from tigrbl.types import Mapped, String
10
+
11
+ from .uvicorn_utils import run_uvicorn_in_task, stop_uvicorn_server
12
+
13
+
14
+ class AlphaWidget(Base, GUIDPk):
15
+ __tablename__ = "alpha_widgets"
16
+ __resource__ = "alpha-widget"
17
+
18
+ name: Mapped[str] = acol(
19
+ storage=S(String, nullable=False),
20
+ field=F(py_type=str),
21
+ io=IO(in_verbs=("create",), out_verbs=("create", "read", "list")),
22
+ )
23
+
24
+
25
+ class BetaWidget(Base, GUIDPk):
26
+ __tablename__ = "beta_widgets"
27
+ __resource__ = "beta-widget"
28
+
29
+ name: Mapped[str] = acol(
30
+ storage=S(String, nullable=False),
31
+ field=F(py_type=str),
32
+ io=IO(in_verbs=("create",), out_verbs=("create", "read", "list")),
33
+ )
34
+
35
+
36
+ @pytest_asyncio.fixture()
37
+ async def running_multi_api_app():
38
+ engine = mem(async_=False)
39
+ alpha_api = TigrblApi(engine=engine)
40
+ alpha_api.include_model(AlphaWidget)
41
+
42
+ beta_api = TigrblApi(engine=engine)
43
+ beta_api.include_model(BetaWidget)
44
+
45
+ app = TigrblApp(engine=engine, apis=[alpha_api])
46
+ app.include_router(beta_api, prefix="/beta")
47
+ app.include_router(alpha_api.router, prefix="/alpha")
48
+ await app.initialize()
49
+
50
+ base_url, server, task = await run_uvicorn_in_task(app)
51
+ try:
52
+ yield base_url
53
+ finally:
54
+ await stop_uvicorn_server(server, task)
55
+
56
+
57
+ @pytest.mark.i9n
58
+ @pytest.mark.asyncio
59
+ async def test_tigrbl_app_routes_alpha_api(running_multi_api_app):
60
+ async with httpx.AsyncClient() as client:
61
+ response = await client.post(
62
+ f"{running_multi_api_app}/alpha/alpha-widget", json={"name": "ace"}
63
+ )
64
+
65
+ assert response.status_code == 201
66
+ payload = response.json()
67
+ assert payload["name"] == "ace"
68
+
69
+
70
+ @pytest.mark.i9n
71
+ @pytest.mark.asyncio
72
+ async def test_tigrbl_app_routes_beta_api(running_multi_api_app):
73
+ async with httpx.AsyncClient() as client:
74
+ response = await client.post(
75
+ f"{running_multi_api_app}/beta/beta-widget", json={"name": "bolt"}
76
+ )
77
+
78
+ assert response.status_code == 201
79
+ payload = response.json()
80
+ assert payload["name"] == "bolt"
@@ -0,0 +1,103 @@
1
+ import httpx
2
+ import pytest
3
+ import pytest_asyncio
4
+ from fastapi import Security
5
+ from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer
6
+
7
+ from tigrbl import Base, TigrblApp
8
+ from tigrbl.engine.shortcuts import mem
9
+ from tigrbl.orm.mixins import GUIDPk
10
+ from tigrbl.specs import F, IO, S, acol
11
+ from tigrbl.types import Mapped, String
12
+
13
+ from .uvicorn_utils import run_uvicorn_in_task, stop_uvicorn_server
14
+
15
+
16
+ bearer = HTTPBearer()
17
+
18
+
19
+ def auth_dependency(
20
+ credentials: HTTPAuthorizationCredentials = Security(bearer),
21
+ ) -> HTTPAuthorizationCredentials:
22
+ return credentials
23
+
24
+
25
+ class Gamma(Base, GUIDPk):
26
+ __tablename__ = "gamma_app_usage"
27
+ __allow_unmapped__ = True
28
+
29
+ name: Mapped[str] = acol(
30
+ storage=S(type_=String, nullable=False),
31
+ field=F(py_type=str),
32
+ io=IO(in_verbs=("create",), out_verbs=("create", "read", "list")),
33
+ )
34
+
35
+ __tigrbl_cols__ = {"id": GUIDPk.id, "name": name}
36
+
37
+
38
+ class Delta(Base, GUIDPk):
39
+ __tablename__ = "delta_app_usage"
40
+ __allow_unmapped__ = True
41
+
42
+ name: Mapped[str] = acol(
43
+ storage=S(type_=String, nullable=False),
44
+ field=F(py_type=str),
45
+ io=IO(in_verbs=("create",), out_verbs=("create", "read", "list")),
46
+ )
47
+
48
+ __tigrbl_cols__ = {"id": GUIDPk.id, "name": name}
49
+
50
+
51
+ @pytest_asyncio.fixture()
52
+ async def running_app():
53
+ app = TigrblApp(engine=mem(async_=False))
54
+ app.set_auth(authn=auth_dependency, allow_anon=False)
55
+ app.include_models([Gamma, Delta])
56
+ app.initialize()
57
+
58
+ base_url, server, task = await run_uvicorn_in_task(app)
59
+ try:
60
+ yield base_url
61
+ finally:
62
+ await stop_uvicorn_server(server, task)
63
+
64
+
65
+ @pytest.mark.i9n
66
+ @pytest.mark.asyncio
67
+ async def test_tigrbl_app_deploys_and_serves_openapi(running_app) -> None:
68
+ base_url = running_app
69
+
70
+ async with httpx.AsyncClient() as client:
71
+ openapi_resp = await client.get(f"{base_url}/openapi.json")
72
+
73
+ assert openapi_resp.status_code == 200
74
+ openapi = openapi_resp.json()
75
+ paths = openapi["paths"]
76
+
77
+ assert "/gamma" in paths
78
+ assert "/gamma/{item_id}" in paths
79
+ assert "/delta" in paths
80
+ assert "/delta/{item_id}" in paths
81
+ assert {"get", "post", "delete"}.issubset(paths["/gamma"])
82
+ assert {"get", "patch", "put", "delete"}.issubset(paths["/gamma/{item_id}"])
83
+
84
+ security_schemes = openapi.get("components", {}).get("securitySchemes", {})
85
+ assert "HTTPBearer" in security_schemes
86
+
87
+
88
+ @pytest.mark.i9n
89
+ @pytest.mark.asyncio
90
+ async def test_tigrbl_app_handles_authenticated_request(running_app) -> None:
91
+ base_url = running_app
92
+ headers = {"Authorization": "Bearer demo"}
93
+
94
+ async with httpx.AsyncClient() as client:
95
+ resp = await client.post(
96
+ f"{base_url}/gamma",
97
+ json={"name": "Gamma"},
98
+ headers=headers,
99
+ )
100
+
101
+ assert resp.status_code == 201
102
+ payload = resp.json()
103
+ assert payload["name"] == "Gamma"
@@ -0,0 +1,58 @@
1
+ import httpx
2
+ import pytest
3
+ import pytest_asyncio
4
+
5
+ from tigrbl import Base, TigrblApp
6
+ from tigrbl.engine.shortcuts import mem
7
+ from tigrbl.orm.mixins import GUIDPk
8
+ from tigrbl.specs import F, IO, S, acol
9
+ from tigrbl.types import Mapped, String
10
+
11
+ from .uvicorn_utils import run_uvicorn_in_task, stop_uvicorn_server
12
+
13
+
14
+ class Widget(Base, GUIDPk):
15
+ __tablename__ = "widgets_app"
16
+ __resource__ = "widget"
17
+
18
+ name: Mapped[str] = acol(
19
+ storage=S(String, nullable=False),
20
+ field=F(py_type=str),
21
+ io=IO(in_verbs=("create",), out_verbs=("create", "read", "list")),
22
+ )
23
+
24
+
25
+ @pytest_asyncio.fixture()
26
+ async def running_app():
27
+ app = TigrblApp(engine=mem(async_=False))
28
+ app.include_model(Widget)
29
+ app.attach_diagnostics()
30
+ await app.initialize()
31
+
32
+ base_url, server, task = await run_uvicorn_in_task(app)
33
+ try:
34
+ yield base_url
35
+ finally:
36
+ await stop_uvicorn_server(server, task)
37
+
38
+
39
+ @pytest.mark.i9n
40
+ @pytest.mark.asyncio
41
+ async def test_tigrbl_app_create_widget(running_app):
42
+ async with httpx.AsyncClient() as client:
43
+ response = await client.post(f"{running_app}/widget", json={"name": "alpha"})
44
+
45
+ assert response.status_code == 201
46
+ payload = response.json()
47
+ assert payload["name"] == "alpha"
48
+ assert "id" in payload
49
+
50
+
51
+ @pytest.mark.i9n
52
+ @pytest.mark.asyncio
53
+ async def test_tigrbl_app_healthz(running_app):
54
+ async with httpx.AsyncClient() as client:
55
+ response = await client.get(f"{running_app}/system/healthz")
56
+
57
+ assert response.status_code == 200
58
+ assert response.json()["ok"] is True
@@ -15,7 +15,7 @@ def test_app_spec_defaults_and_merge():
15
15
  spec = mro_collect_app_spec(ChildApp)
16
16
  assert spec.title == "Base"
17
17
  assert spec.version == "1.0"
18
- assert spec.apis == ("base", "base", "child")
18
+ assert spec.apis == ("child", "base")
19
19
  assert spec.ops == ("read",)
20
20
  assert spec.models == ()
21
21
  assert spec.schemas == ()
@@ -32,7 +32,7 @@ class Model(SpecA, SpecB, Base, GUIDPk):
32
32
  def test_collect_table_spec_merges_mro():
33
33
  spec = mro_collect_table_spec(Model)
34
34
  assert spec.model is Model
35
- assert spec.engine == "db_b"
35
+ assert spec.engine == "db_a"
36
36
  assert spec.ops == ("a", "b")
37
37
  assert spec.columns == ("col_a", "col_b")
38
38
  assert spec.schemas == ("SchemaA", "SchemaB")
@@ -0,0 +1,27 @@
1
+ from types import SimpleNamespace
2
+
3
+ from tigrbl.specs import F, S, acol
4
+ from tigrbl.table import Table
5
+ from tigrbl.types import Integer, Mapped
6
+
7
+
8
+ class Widget(Table):
9
+ __tablename__ = "widgets_namespace_init"
10
+
11
+ id: Mapped[int] = acol(
12
+ storage=S(type_=Integer, primary_key=True), field=F(py_type=int)
13
+ )
14
+
15
+
16
+ def test_table_initializes_model_namespaces() -> None:
17
+ assert isinstance(Widget.ops, SimpleNamespace)
18
+ assert Widget.ops is Widget.opspecs
19
+ assert isinstance(Widget.schemas, SimpleNamespace)
20
+ assert isinstance(Widget.hooks, SimpleNamespace)
21
+ assert isinstance(Widget.handlers, SimpleNamespace)
22
+ assert isinstance(Widget.rpc, SimpleNamespace)
23
+ assert isinstance(Widget.rest, SimpleNamespace)
24
+ assert hasattr(Widget.rest, "router")
25
+ assert isinstance(Widget.__tigrbl_hooks__, dict)
26
+ assert isinstance(Widget.columns, SimpleNamespace)
27
+ assert Widget.columns.id is Widget.__tigrbl_cols__["id"]
@@ -0,0 +1,43 @@
1
+ from types import SimpleNamespace
2
+
3
+ from tigrbl.specs import F, S, acol
4
+ from tigrbl.table import Table
5
+ from tigrbl.types import Integer, Mapped
6
+
7
+
8
+ class BaseWidget(Table):
9
+ __abstract__ = True
10
+
11
+ id: Mapped[int] = acol(
12
+ storage=S(type_=Integer, primary_key=True), field=F(py_type=int)
13
+ )
14
+
15
+
16
+ class WidgetAlpha(BaseWidget):
17
+ __tablename__ = "widgets_namespace_alpha"
18
+
19
+
20
+ class WidgetBeta(BaseWidget):
21
+ __tablename__ = "widgets_namespace_beta"
22
+
23
+
24
+ def test_model_namespaces_are_per_class() -> None:
25
+ assert isinstance(WidgetAlpha.ops, SimpleNamespace)
26
+ assert isinstance(WidgetBeta.ops, SimpleNamespace)
27
+ assert WidgetAlpha.ops is WidgetAlpha.opspecs
28
+ assert WidgetBeta.ops is WidgetBeta.opspecs
29
+ assert WidgetAlpha.ops is not WidgetBeta.ops
30
+ assert WidgetAlpha.schemas is not WidgetBeta.schemas
31
+ assert WidgetAlpha.hooks is not WidgetBeta.hooks
32
+ assert WidgetAlpha.handlers is not WidgetBeta.handlers
33
+ assert WidgetAlpha.rpc is not WidgetBeta.rpc
34
+ assert WidgetAlpha.rest is not WidgetBeta.rest
35
+ assert WidgetAlpha.__tigrbl_hooks__ is not WidgetBeta.__tigrbl_hooks__
36
+
37
+
38
+ def test_model_namespace_mutations_do_not_bleed() -> None:
39
+ WidgetAlpha.ops.by_alias["alpha_only"] = ["alpha"]
40
+ assert "alpha_only" not in WidgetBeta.ops.by_alias
41
+
42
+ WidgetAlpha.schemas.alpha_only = "alpha_schema"
43
+ assert not hasattr(WidgetBeta.schemas, "alpha_only")
@@ -0,0 +1,83 @@
1
+ import pytest
2
+ from fastapi import Security
3
+ from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer
4
+
5
+ from tigrbl import Base, TigrblApi, TigrblApp
6
+ from tigrbl.engine.shortcuts import mem
7
+ from tigrbl.orm.mixins import GUIDPk
8
+ from tigrbl.specs import F, IO, S, acol
9
+ from tigrbl.types import Mapped, String
10
+
11
+
12
+ def _auth_dependency(
13
+ credentials: HTTPAuthorizationCredentials = Security(HTTPBearer()),
14
+ ) -> HTTPAuthorizationCredentials:
15
+ return credentials
16
+
17
+
18
+ class Iota(Base, GUIDPk):
19
+ __tablename__ = "iota_api_app_cfg"
20
+ __allow_unmapped__ = True
21
+
22
+ name: Mapped[str] = acol(
23
+ storage=S(type_=String, nullable=False),
24
+ field=F(py_type=str),
25
+ io=IO(in_verbs=("create",), out_verbs=("read", "list")),
26
+ )
27
+
28
+ __tigrbl_cols__ = {"id": GUIDPk.id, "name": name}
29
+
30
+
31
+ class IotaApi(TigrblApi):
32
+ MODELS = (Iota,)
33
+
34
+
35
+ @pytest.mark.unit
36
+ def test_tigrbl_api_app_constructor_configuration_applies_metadata() -> None:
37
+ api = IotaApi(
38
+ engine=mem(async_=False),
39
+ jsonrpc_prefix="/rpcx",
40
+ system_prefix="/systemx",
41
+ )
42
+
43
+ class IotaApp(TigrblApp):
44
+ APIS = (api,)
45
+
46
+ app = IotaApp(engine=mem(async_=False), title="Iota App", version="9.9.9")
47
+
48
+ api_dir = dir(api)
49
+ app_dir = dir(app)
50
+
51
+ assert "jsonrpc_prefix" in api_dir
52
+ assert "system_prefix" in api_dir
53
+ assert "TITLE" in app_dir
54
+ assert "VERSION" in app_dir
55
+ assert api.jsonrpc_prefix == "/rpcx"
56
+ assert api.system_prefix == "/systemx"
57
+ assert app.TITLE == "Iota App"
58
+ assert app.VERSION == "9.9.9"
59
+ assert app.apis == [api]
60
+
61
+
62
+ @pytest.mark.unit
63
+ def test_tigrbl_api_app_post_instantiation_updates_auth_state() -> None:
64
+ api = IotaApi(engine=mem(async_=False))
65
+
66
+ class IotaApp(TigrblApp):
67
+ APIS = (api,)
68
+
69
+ app = IotaApp(engine=mem(async_=False))
70
+ api.set_auth(authn=_auth_dependency, allow_anon=False)
71
+ app.set_auth(authn=_auth_dependency, allow_anon=False)
72
+
73
+ api_dir = dir(api)
74
+ app_dir = dir(app)
75
+
76
+ assert "_authn" in api_dir
77
+ assert "_allow_anon" in api_dir
78
+ assert api._authn is _auth_dependency
79
+ assert api._allow_anon is False
80
+ assert "_authn" in app_dir
81
+ assert "_allow_anon" in app_dir
82
+ assert app._authn is _auth_dependency
83
+ assert app._allow_anon is False
@@ -0,0 +1,42 @@
1
+ import pytest
2
+
3
+ from tigrbl import Base, TigrblApi, TigrblApp
4
+ from tigrbl.engine.shortcuts import mem
5
+ from tigrbl.orm.mixins import GUIDPk
6
+ from tigrbl.specs import F, IO, S, acol
7
+ from tigrbl.types import Mapped, String
8
+
9
+
10
+ class Theta(Base, GUIDPk):
11
+ __tablename__ = "theta_api_app_inst"
12
+ __allow_unmapped__ = True
13
+
14
+ name: Mapped[str] = acol(
15
+ storage=S(type_=String, nullable=False),
16
+ field=F(py_type=str),
17
+ io=IO(in_verbs=("create",), out_verbs=("read", "list")),
18
+ )
19
+
20
+ __tigrbl_cols__ = {"id": GUIDPk.id, "name": name}
21
+
22
+
23
+ class ThetaApi(TigrblApi):
24
+ MODELS = (Theta,)
25
+
26
+
27
+ @pytest.mark.unit
28
+ def test_tigrbl_api_app_instantiation_sets_composed_state() -> None:
29
+ api = ThetaApi(engine=mem(async_=False))
30
+
31
+ class ThetaApp(TigrblApp):
32
+ APIS = (api,)
33
+
34
+ app = ThetaApp(engine=mem(async_=False))
35
+
36
+ api_dir = dir(api)
37
+ app_dir = dir(app)
38
+
39
+ assert "models" in api_dir
40
+ assert api.models["Theta"] is Theta
41
+ assert "apis" in app_dir
42
+ assert app.apis == [api]
@@ -0,0 +1,38 @@
1
+ import pytest
2
+
3
+ from tigrbl import Base, TigrblApi, TigrblApp
4
+ from tigrbl.orm.mixins import GUIDPk
5
+ from tigrbl.specs import F, IO, S, acol
6
+ from tigrbl.types import Mapped, String
7
+
8
+
9
+ class Zeta(Base, GUIDPk):
10
+ __tablename__ = "zeta_api_app_decl"
11
+ __allow_unmapped__ = True
12
+
13
+ name: Mapped[str] = acol(
14
+ storage=S(type_=String, nullable=False),
15
+ field=F(py_type=str),
16
+ io=IO(in_verbs=("create",), out_verbs=("read", "list")),
17
+ )
18
+
19
+ __tigrbl_cols__ = {"id": GUIDPk.id, "name": name}
20
+
21
+
22
+ class ZetaApi(TigrblApi):
23
+ MODELS = (Zeta,)
24
+
25
+
26
+ class ZetaApp(TigrblApp):
27
+ APIS = (ZetaApi,)
28
+
29
+
30
+ @pytest.mark.unit
31
+ def test_tigrbl_api_app_subclass_declares_composition() -> None:
32
+ api_dir = dir(ZetaApi)
33
+ app_dir = dir(ZetaApp)
34
+
35
+ assert "MODELS" in api_dir
36
+ assert "APIS" in app_dir
37
+ assert ZetaApi.MODELS == (Zeta,)
38
+ assert ZetaApp.APIS == (ZetaApi,)
@@ -0,0 +1,47 @@
1
+ import pytest
2
+ from fastapi import Security
3
+ from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer
4
+
5
+ from tigrbl import TigrblApi
6
+ from tigrbl.engine.shortcuts import mem
7
+
8
+
9
+ def _auth_dependency(
10
+ credentials: HTTPAuthorizationCredentials = Security(HTTPBearer()),
11
+ ) -> HTTPAuthorizationCredentials:
12
+ return credentials
13
+
14
+
15
+ @pytest.mark.unit
16
+ def test_tigrbl_api_constructor_configuration_sets_prefixes() -> None:
17
+ def sample_hook() -> None:
18
+ return None
19
+
20
+ api = TigrblApi(
21
+ engine=mem(async_=False),
22
+ jsonrpc_prefix="/rpcx",
23
+ system_prefix="/systemx",
24
+ api_hooks={"*": {"pre": [sample_hook]}},
25
+ )
26
+
27
+ api_dir = dir(api)
28
+
29
+ assert "jsonrpc_prefix" in api_dir
30
+ assert "system_prefix" in api_dir
31
+ assert "_api_hooks_map" in api_dir
32
+ assert api.jsonrpc_prefix == "/rpcx"
33
+ assert api.system_prefix == "/systemx"
34
+ assert api._api_hooks_map == {"*": {"pre": [sample_hook]}}
35
+
36
+
37
+ @pytest.mark.unit
38
+ def test_tigrbl_api_post_instantiation_set_auth_updates_state() -> None:
39
+ api = TigrblApi(engine=mem(async_=False))
40
+ api.set_auth(authn=_auth_dependency, allow_anon=False)
41
+
42
+ api_dir = dir(api)
43
+
44
+ assert "_authn" in api_dir
45
+ assert "_allow_anon" in api_dir
46
+ assert api._authn is _auth_dependency
47
+ assert api._allow_anon is False
@@ -0,0 +1,37 @@
1
+ import pytest
2
+
3
+ from tigrbl import Base, TigrblApi
4
+ from tigrbl.engine.shortcuts import mem
5
+ from tigrbl.orm.mixins import GUIDPk
6
+ from tigrbl.specs import F, IO, S, acol
7
+ from tigrbl.types import Mapped, String
8
+
9
+
10
+ class Widget(Base, GUIDPk):
11
+ __tablename__ = "widgets_api_inst"
12
+ __allow_unmapped__ = True
13
+
14
+ name: Mapped[str] = acol(
15
+ storage=S(type_=String, nullable=False),
16
+ field=F(py_type=str),
17
+ io=IO(in_verbs=("create",), out_verbs=("read", "list")),
18
+ )
19
+
20
+ __tigrbl_cols__ = {"id": GUIDPk.id, "name": name}
21
+
22
+
23
+ class WidgetApi(TigrblApi):
24
+ MODELS = (Widget,)
25
+
26
+
27
+ @pytest.mark.unit
28
+ def test_tigrbl_api_instantiation_sets_containers() -> None:
29
+ api = WidgetApi(engine=mem(async_=False))
30
+ api_dir = dir(api)
31
+
32
+ assert "models" in api_dir
33
+ assert "routers" in api_dir
34
+ assert "schemas" in api_dir
35
+ assert "jsonrpc_prefix" in api_dir
36
+ assert "system_prefix" in api_dir
37
+ assert api.models["Widget"] is Widget
@@ -0,0 +1,37 @@
1
+ import pytest
2
+
3
+ from tigrbl import Base, TigrblApi
4
+ from tigrbl.orm.mixins import GUIDPk
5
+ from tigrbl.specs import F, IO, S, acol
6
+ from tigrbl.types import Mapped, String
7
+
8
+
9
+ class Widget(Base, GUIDPk):
10
+ __tablename__ = "widgets_api_decl"
11
+ __allow_unmapped__ = True
12
+
13
+ name: Mapped[str] = acol(
14
+ storage=S(type_=String, nullable=False),
15
+ field=F(py_type=str),
16
+ io=IO(in_verbs=("create",), out_verbs=("read", "list")),
17
+ )
18
+
19
+ __tigrbl_cols__ = {"id": GUIDPk.id, "name": name}
20
+
21
+
22
+ class WidgetApi(TigrblApi):
23
+ PREFIX = "/widgets"
24
+ TAGS = ("widgets",)
25
+ MODELS = (Widget,)
26
+
27
+
28
+ @pytest.mark.unit
29
+ def test_tigrbl_api_subclass_declares_metadata() -> None:
30
+ class_dir = dir(WidgetApi)
31
+
32
+ assert "MODELS" in class_dir
33
+ assert "TAGS" in class_dir
34
+ assert "PREFIX" in class_dir
35
+ assert WidgetApi.MODELS == (Widget,)
36
+ assert WidgetApi.TAGS == ("widgets",)
37
+ assert WidgetApi.PREFIX == "/widgets"
@@ -0,0 +1,47 @@
1
+ import pytest
2
+ from fastapi import Security
3
+ from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer
4
+
5
+ from tigrbl import TigrblApp
6
+ from tigrbl.engine.shortcuts import mem
7
+
8
+
9
+ def _auth_dependency(
10
+ credentials: HTTPAuthorizationCredentials = Security(HTTPBearer()),
11
+ ) -> HTTPAuthorizationCredentials:
12
+ return credentials
13
+
14
+
15
+ @pytest.mark.unit
16
+ def test_tigrbl_app_constructor_configuration_sets_metadata() -> None:
17
+ app = TigrblApp(
18
+ engine=mem(async_=False),
19
+ title="Configured App",
20
+ version="2.3.4",
21
+ jsonrpc_prefix="/rpcx",
22
+ system_prefix="/systemx",
23
+ )
24
+
25
+ app_dir = dir(app)
26
+
27
+ assert "TITLE" in app_dir
28
+ assert "VERSION" in app_dir
29
+ assert "jsonrpc_prefix" in app_dir
30
+ assert "system_prefix" in app_dir
31
+ assert app.TITLE == "Configured App"
32
+ assert app.VERSION == "2.3.4"
33
+ assert app.jsonrpc_prefix == "/rpcx"
34
+ assert app.system_prefix == "/systemx"
35
+
36
+
37
+ @pytest.mark.unit
38
+ def test_tigrbl_app_post_instantiation_set_auth_updates_state() -> None:
39
+ app = TigrblApp(engine=mem(async_=False))
40
+ app.set_auth(authn=_auth_dependency, allow_anon=False)
41
+
42
+ app_dir = dir(app)
43
+
44
+ assert "_authn" in app_dir
45
+ assert "_allow_anon" in app_dir
46
+ assert app._authn is _auth_dependency
47
+ assert app._allow_anon is False
@@ -0,0 +1,37 @@
1
+ import pytest
2
+
3
+ from tigrbl import Base, TigrblApp
4
+ from tigrbl.engine.shortcuts import mem
5
+ from tigrbl.orm.mixins import GUIDPk
6
+ from tigrbl.specs import F, IO, S, acol
7
+ from tigrbl.types import Mapped, String
8
+
9
+
10
+ class Widget(Base, GUIDPk):
11
+ __tablename__ = "widgets_app_inst"
12
+ __allow_unmapped__ = True
13
+
14
+ name: Mapped[str] = acol(
15
+ storage=S(type_=String, nullable=False),
16
+ field=F(py_type=str),
17
+ io=IO(in_verbs=("create",), out_verbs=("read", "list")),
18
+ )
19
+
20
+ __tigrbl_cols__ = {"id": GUIDPk.id, "name": name}
21
+
22
+
23
+ class WidgetApp(TigrblApp):
24
+ MODELS = (Widget,)
25
+
26
+
27
+ @pytest.mark.unit
28
+ def test_tigrbl_app_instantiation_sets_containers() -> None:
29
+ app = WidgetApp(engine=mem(async_=False))
30
+ app_dir = dir(app)
31
+
32
+ assert "models" in app_dir
33
+ assert "routers" in app_dir
34
+ assert "schemas" in app_dir
35
+ assert "jsonrpc_prefix" in app_dir
36
+ assert "system_prefix" in app_dir
37
+ assert app.models["Widget"] is Widget
@@ -0,0 +1,37 @@
1
+ import pytest
2
+
3
+ from tigrbl import Base, TigrblApp
4
+ from tigrbl.orm.mixins import GUIDPk
5
+ from tigrbl.specs import F, IO, S, acol
6
+ from tigrbl.types import Mapped, String
7
+
8
+
9
+ class Widget(Base, GUIDPk):
10
+ __tablename__ = "widgets_app_decl"
11
+ __allow_unmapped__ = True
12
+
13
+ name: Mapped[str] = acol(
14
+ storage=S(type_=String, nullable=False),
15
+ field=F(py_type=str),
16
+ io=IO(in_verbs=("create",), out_verbs=("read", "list")),
17
+ )
18
+
19
+ __tigrbl_cols__ = {"id": GUIDPk.id, "name": name}
20
+
21
+
22
+ class WidgetApp(TigrblApp):
23
+ TITLE = "Widget App"
24
+ VERSION = "1.0.0"
25
+ MODELS = (Widget,)
26
+
27
+
28
+ @pytest.mark.unit
29
+ def test_tigrbl_app_subclass_declares_metadata() -> None:
30
+ class_dir = dir(WidgetApp)
31
+
32
+ assert "TITLE" in class_dir
33
+ assert "VERSION" in class_dir
34
+ assert "MODELS" in class_dir
35
+ assert WidgetApp.TITLE == "Widget App"
36
+ assert WidgetApp.VERSION == "1.0.0"
37
+ assert WidgetApp.MODELS == (Widget,)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tigrbl-tests
3
- Version: 0.3.2.dev1
3
+ Version: 0.3.3.dev1
4
4
  Summary: Test suite and fixtures for the Tigrbl framework.
5
5
  License-Expression: Apache-2.0
6
6
  License-File: LICENSE
@@ -30,6 +30,7 @@ Requires-Dist: python-dotenv
30
30
  Requires-Dist: requests (>=2.32.3)
31
31
  Requires-Dist: ruff (>=0.9.9)
32
32
  Requires-Dist: tigrbl
33
+ Requires-Dist: tigrbl_client
33
34
  Description-Content-Type: text/markdown
34
35
 
35
36
  ![Tigrbl Logo](https://github.com/swarmauri/swarmauri-sdk/blob/a170683ecda8ca1c4f912c966d4499649ffb8224/assets/tigrbl.brand.theme.svg)
@@ -100,4 +101,18 @@ Use pytest selectors to focus on specific suites:
100
101
  pytest standards/tigrbl_tests/tests/unit
101
102
  ```
102
103
 
104
+ ## Examples Curriculum 📚
105
+
106
+ The `examples/` directory contains downstream-facing pytest lessons that
107
+ demonstrate how to implement Tigrbl in real applications. These lessons are
108
+ organized as a multi-module curriculum with uvicorn-backed usage examples and
109
+ system diagnostics validation. See the full curriculum plan for the learning
110
+ sequence and module descriptions.[^tigrbl-examples]
111
+ Run the examples from the `pkgs` directory:
112
+
113
+ ```bash
114
+ uv run --package tigrbl-tests --directory standards/tigrbl_tests pytest examples
115
+ ```
116
+
117
+ [^tigrbl-examples]: examples/README.md
103
118
 
@@ -43,6 +43,13 @@ tests/i9n/test_schema_ctx_spec_integration.py,sha256=gQB0YdqjGfkoflcbzdkrVLouefh
43
43
  tests/i9n/test_sqlite_attachments.py,sha256=Dvv2Exhbs7P47kOLQjg5TyruXYJqZIQdnqZvoitVy5Y,1216
44
44
  tests/i9n/test_storage_spec_integration.py,sha256=hHxn0odPOLSIXY9Rx5ZwgOZS5DPFtutIhw5JYlEFmPg,3918
45
45
  tests/i9n/test_symmetry_parity.py,sha256=7b2iVc0e7I84bOLgyWvFA3Zg-maGOGTLtTcX5gCX1Zg,919
46
+ tests/i9n/test_tigrbl_api_app_usage_uvicorn.py,sha256=FaE81foEFgZ8w9son4m4XSxYLV9-Ss034WkJjgpPlDU,2692
47
+ tests/i9n/test_tigrbl_api_usage_uvicorn.py,sha256=9ThMl7YsFgRZUU7Lk4R-1c5NNqn2YcDeOL6L9w37WZI,2933
48
+ tests/i9n/test_tigrbl_api_uvicorn.py,sha256=_3_z_OnKhL7JdSPzxCv7Bq0bFmm9GOyiAmp3TroRdm4,1764
49
+ tests/i9n/test_tigrbl_app_include_api_uvicorn.py,sha256=LzjwmchWqgHexYt7ebA7aPj1jM29J8q-lPCKoXp7dhg,4396
50
+ tests/i9n/test_tigrbl_app_multi_api_uvicorn.py,sha256=sFDkspBHhYSLfmMsXgzHKBIHFFpYuo7Znj0URr3bowE,2270
51
+ tests/i9n/test_tigrbl_app_usage_uvicorn.py,sha256=qUfSOk5ye509JwEJl9i6ViXtKA-LI0JAV8IdWCU_Mgw,2889
52
+ tests/i9n/test_tigrbl_app_uvicorn.py,sha256=a06Zypy1kA5glvyHb3iaBmBJso7WGoT0ZmwHu0Bv1iY,1572
46
53
  tests/i9n/test_v3_bulk_rest_endpoints.py,sha256=3nNXJ6l3Ady4wi5UnEVmrw76crw9Ur7Ys53wq6RwBAI,3928
47
54
  tests/i9n/test_v3_default_rest_ops.py,sha256=X_wJB7bmCaK6c9U6oPZlgQmRXdF2PeuYCqQYboJFxDo,4752
48
55
  tests/i9n/test_v3_default_rpc_ops.py,sha256=mnDi5DNP6gKIi31Uin7rLlxvyY47u0U_2HvK61XqpB8,7552
@@ -163,7 +170,7 @@ tests/unit/test_schemas_binding.py,sha256=TifSTTDJwN18ewb3dYTczjD7h5oWfLEh1MwPV_
163
170
  tests/unit/test_security_per_route.py,sha256=b_6KKWDaTVWAO5XTfcNIG2pxMoNhZOcPBVKlz3Bz5KQ,1512
164
171
  tests/unit/test_should_wire_canonical.py,sha256=ANlw1UFm77UI5LDaVWZZmBHSh1kUiJzY4hm1blLW158,1662
165
172
  tests/unit/test_spec_api.py,sha256=LUiDDLmW9oBZQXvT-29FjX_ZHXy9FPN13-f4gQ6i5tI,1130
166
- tests/unit/test_spec_app.py,sha256=6bppvI1orwKaoC7MNjByKNhjTgxnc4liOzeHGBHae5s,761
173
+ tests/unit/test_spec_app.py,sha256=fdEMeAlepypgmqCxsQawfEOMSE5d3fia1LOwsxC95t8,753
167
174
  tests/unit/test_spec_column.py,sha256=ja3IDQi5U2WtTUHRd4deniyZ6EZkwz3mylKH8CLgf7I,867
168
175
  tests/unit/test_spec_engine.py,sha256=D2pU-NCGMh0gsX-PhL5ZkJyTeO09NkATSK8WY-ynHaw,1938
169
176
  tests/unit/test_spec_field.py,sha256=68X7qtA3H2P9LQKEJTW14YVPQJ-cENBrXyVmMBwj430,491
@@ -181,8 +188,19 @@ tests/unit/test_sys_tx_async_begin.py,sha256=q0apjmNnxZcGqCkpD8I0uPFsLPxJN_1ZBjF
181
188
  tests/unit/test_sys_tx_begin.py,sha256=ElKZIxeK98O60Eo3uMGx8tuoP9nFlFYpYja5eLCears,1429
182
189
  tests/unit/test_sys_tx_commit.py,sha256=HOTCtKusz7iGr-PkW_gcId1NzpGMRXBUxUydpd5PbHc,1813
183
190
  tests/unit/test_table_base_exports.py,sha256=8GcLU0vY_j0_d5Y7PqQKMgz0L4rD3iPXMBn1u6dPz6E,666
184
- tests/unit/test_table_collect_spec.py,sha256=SFUcdZpVbUFxQkms8v1_BZs4sgYEYiTZPSkD4UctJDo,1050
191
+ tests/unit/test_table_collect_spec.py,sha256=Gs_QnfKb9rYILHMv1q7w43gUvvS6UnpXy8vsI74IQTE,1050
185
192
  tests/unit/test_table_columns_namespace.py,sha256=IVtpdg5dRHqyqc6WW0hndLJ7uNhnjivJ0GOJLebl_1w,581
193
+ tests/unit/test_table_namespace_init.py,sha256=53CnG1hMRUBD_KAU50FpKvUilk4QhBT0qbY2ECkP9Fc,945
194
+ tests/unit/test_table_namespace_isolation.py,sha256=6pWz1yLdrPNoOGzOjwe9_GBRHosrOaNSshRscq9ytIs,1394
195
+ tests/unit/test_tigrbl_api_app_configuration.py,sha256=aa0lXbJJnycUIZN3DGEgYmPIENRZi5-K-xHVEDiA6jQ,2269
196
+ tests/unit/test_tigrbl_api_app_instantiation.py,sha256=SlmotlemN4G4NNsY3UCXYF0shIClgSadbBmqTT2jbWM,1016
197
+ tests/unit/test_tigrbl_api_app_subclass_definition.py,sha256=yMoQZAmQqzK6V0fMUeYXGPx1nv7zFJ3wYc1E7-awY_I,886
198
+ tests/unit/test_tigrbl_api_configuration.py,sha256=O1J2FCbrr9acujY976gsGgpfRLoabfO_esYxwtcyRkU,1312
199
+ tests/unit/test_tigrbl_api_instantiation.py,sha256=w4edFjjIezW-cmBw_N4VHpLR0Z38zwRGvAzCMm5i4fw,960
200
+ tests/unit/test_tigrbl_api_subclass_definition.py,sha256=VL5aK7dgasH2TVlcKqoyEdmlNxuUbguJy1T8dqirR3Q,935
201
+ tests/unit/test_tigrbl_app_configuration.py,sha256=78ygfvj86Yv3YBOSnqBAm1fnPxNmTqg728owWnw_U2g,1303
202
+ tests/unit/test_tigrbl_app_instantiation.py,sha256=QyNzcwD7uuunrpjIcFMFuisPJo73D06yaDnVtEf2Hh0,960
203
+ tests/unit/test_tigrbl_app_subclass_definition.py,sha256=loeowe-FikGpGpiNIkBM8KgQgLSZv1mFCbut_stHFg4,935
186
204
  tests/unit/test_v3_favicon_endpoint.py,sha256=mlquQ6ZF83JeJDdtxS2p7kTnBeeNdMNDWhfYlhFssjc,485
187
205
  tests/unit/test_v3_healthz_endpoint.py,sha256=6WCjROm_3bQg5H__t7Z0BkVghHrpopgpvXTQ_iJKJpw,988
188
206
  tests/unit/test_v3_op_alias.py,sha256=lSb8xpA9Asmaz7VefFDJLwbNBHP_mN4hSVJr1NVvOI4,2353
@@ -190,7 +208,7 @@ tests/unit/test_v3_op_ctx_attributes.py,sha256=ygRtYSYYtDFCTIRVHX2DFYTliP15NcmVi
190
208
  tests/unit/test_v3_schemas_and_decorators.py,sha256=1wmg7pmzQNjjbQPRjO8gkCM6BQpMRbeO2jmtDMSYXLU,3818
191
209
  tests/unit/test_v3_storage_spec_attributes.py,sha256=iXpjD4GlLddhJ_jC2veND2s6usXdOm-S9sKKfQl9XK0,6540
192
210
  tests/unit/test_verbosity.py,sha256=92dIDc-LBIzjR1d90aL077R29rYJztibKYQGTjI6G68,1945
193
- tigrbl_tests-0.3.2.dev1.dist-info/METADATA,sha256=13f3TinTYP6fvcN7lqFmDg5dEkbs8C6ktVZiJyoz8FM,3300
194
- tigrbl_tests-0.3.2.dev1.dist-info/WHEEL,sha256=3ny-bZhpXrU6vSQ1UPG34FoxZBp3lVcvK0LkgUz6VLk,88
195
- tigrbl_tests-0.3.2.dev1.dist-info/licenses/LICENSE,sha256=djUXOlCxLVszShEpZXshZ7v33G-2qIC_j9KXpWKZSzQ,11359
196
- tigrbl_tests-0.3.2.dev1.dist-info/RECORD,,
211
+ tigrbl_tests-0.3.3.dev1.dist-info/METADATA,sha256=mE6ccLvpw3lzMwkPIGP6iXuag8tRJCy3OkkXdpo7iqg,3892
212
+ tigrbl_tests-0.3.3.dev1.dist-info/WHEEL,sha256=3ny-bZhpXrU6vSQ1UPG34FoxZBp3lVcvK0LkgUz6VLk,88
213
+ tigrbl_tests-0.3.3.dev1.dist-info/licenses/LICENSE,sha256=djUXOlCxLVszShEpZXshZ7v33G-2qIC_j9KXpWKZSzQ,11359
214
+ tigrbl_tests-0.3.3.dev1.dist-info/RECORD,,