valentina-python-client 1.7.4__tar.gz → 1.8.0__tar.gz
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.
- {valentina_python_client-1.7.4 → valentina_python_client-1.8.0}/PKG-INFO +3 -1
- {valentina_python_client-1.7.4 → valentina_python_client-1.8.0}/pyproject.toml +7 -4
- {valentina_python_client-1.7.4 → valentina_python_client-1.8.0}/src/vclient/__init__.py +1 -1
- {valentina_python_client-1.7.4 → valentina_python_client-1.8.0}/src/vclient/_codegen.py +29 -0
- {valentina_python_client-1.7.4 → valentina_python_client-1.8.0}/src/vclient/_sync/services/character_traits.py +16 -2
- valentina_python_client-1.8.0/src/vclient/_sync/testing/__init__.py +5 -0
- valentina_python_client-1.8.0/src/vclient/_sync/testing/_client.py +70 -0
- valentina_python_client-1.8.0/src/vclient/testing/__init__.py +97 -0
- valentina_python_client-1.8.0/src/vclient/testing/_client.py +74 -0
- valentina_python_client-1.8.0/src/vclient/testing/_factories.py +271 -0
- valentina_python_client-1.8.0/src/vclient/testing/_router.py +446 -0
- {valentina_python_client-1.7.4 → valentina_python_client-1.8.0}/LICENSE +0 -0
- {valentina_python_client-1.7.4 → valentina_python_client-1.8.0}/README.md +0 -0
- {valentina_python_client-1.7.4 → valentina_python_client-1.8.0}/src/vclient/_sync/__init__.py +0 -0
- {valentina_python_client-1.7.4 → valentina_python_client-1.8.0}/src/vclient/_sync/client.py +0 -0
- {valentina_python_client-1.7.4 → valentina_python_client-1.8.0}/src/vclient/_sync/registry.py +0 -0
- {valentina_python_client-1.7.4 → valentina_python_client-1.8.0}/src/vclient/_sync/services/__init__.py +0 -0
- {valentina_python_client-1.7.4 → valentina_python_client-1.8.0}/src/vclient/_sync/services/base.py +0 -0
- {valentina_python_client-1.7.4 → valentina_python_client-1.8.0}/src/vclient/_sync/services/campaign_book_chapters.py +0 -0
- {valentina_python_client-1.7.4 → valentina_python_client-1.8.0}/src/vclient/_sync/services/campaign_books.py +0 -0
- {valentina_python_client-1.7.4 → valentina_python_client-1.8.0}/src/vclient/_sync/services/campaigns.py +0 -0
- {valentina_python_client-1.7.4 → valentina_python_client-1.8.0}/src/vclient/_sync/services/character_autogen.py +0 -0
- {valentina_python_client-1.7.4 → valentina_python_client-1.8.0}/src/vclient/_sync/services/character_blueprint.py +0 -0
- {valentina_python_client-1.7.4 → valentina_python_client-1.8.0}/src/vclient/_sync/services/characters.py +0 -0
- {valentina_python_client-1.7.4 → valentina_python_client-1.8.0}/src/vclient/_sync/services/companies.py +0 -0
- {valentina_python_client-1.7.4 → valentina_python_client-1.8.0}/src/vclient/_sync/services/developers.py +0 -0
- {valentina_python_client-1.7.4 → valentina_python_client-1.8.0}/src/vclient/_sync/services/dicerolls.py +0 -0
- {valentina_python_client-1.7.4 → valentina_python_client-1.8.0}/src/vclient/_sync/services/dictionary.py +0 -0
- {valentina_python_client-1.7.4 → valentina_python_client-1.8.0}/src/vclient/_sync/services/global_admin.py +0 -0
- {valentina_python_client-1.7.4 → valentina_python_client-1.8.0}/src/vclient/_sync/services/options.py +0 -0
- {valentina_python_client-1.7.4 → valentina_python_client-1.8.0}/src/vclient/_sync/services/system.py +0 -0
- {valentina_python_client-1.7.4 → valentina_python_client-1.8.0}/src/vclient/_sync/services/users.py +0 -0
- {valentina_python_client-1.7.4 → valentina_python_client-1.8.0}/src/vclient/client.py +0 -0
- {valentina_python_client-1.7.4 → valentina_python_client-1.8.0}/src/vclient/config.py +0 -0
- {valentina_python_client-1.7.4 → valentina_python_client-1.8.0}/src/vclient/constants.py +0 -0
- {valentina_python_client-1.7.4 → valentina_python_client-1.8.0}/src/vclient/endpoints.py +0 -0
- {valentina_python_client-1.7.4 → valentina_python_client-1.8.0}/src/vclient/exceptions.py +0 -0
- {valentina_python_client-1.7.4 → valentina_python_client-1.8.0}/src/vclient/models/__init__.py +0 -0
- {valentina_python_client-1.7.4 → valentina_python_client-1.8.0}/src/vclient/models/books.py +0 -0
- {valentina_python_client-1.7.4 → valentina_python_client-1.8.0}/src/vclient/models/campaigns.py +0 -0
- {valentina_python_client-1.7.4 → valentina_python_client-1.8.0}/src/vclient/models/chapters.py +0 -0
- {valentina_python_client-1.7.4 → valentina_python_client-1.8.0}/src/vclient/models/character_autogen.py +0 -0
- {valentina_python_client-1.7.4 → valentina_python_client-1.8.0}/src/vclient/models/character_blueprint.py +0 -0
- {valentina_python_client-1.7.4 → valentina_python_client-1.8.0}/src/vclient/models/character_trait.py +0 -0
- {valentina_python_client-1.7.4 → valentina_python_client-1.8.0}/src/vclient/models/characters.py +0 -0
- {valentina_python_client-1.7.4 → valentina_python_client-1.8.0}/src/vclient/models/companies.py +0 -0
- {valentina_python_client-1.7.4 → valentina_python_client-1.8.0}/src/vclient/models/developers.py +0 -0
- {valentina_python_client-1.7.4 → valentina_python_client-1.8.0}/src/vclient/models/diceroll.py +0 -0
- {valentina_python_client-1.7.4 → valentina_python_client-1.8.0}/src/vclient/models/dictionary.py +0 -0
- {valentina_python_client-1.7.4 → valentina_python_client-1.8.0}/src/vclient/models/global_admin.py +0 -0
- {valentina_python_client-1.7.4 → valentina_python_client-1.8.0}/src/vclient/models/pagination.py +0 -0
- {valentina_python_client-1.7.4 → valentina_python_client-1.8.0}/src/vclient/models/shared.py +0 -0
- {valentina_python_client-1.7.4 → valentina_python_client-1.8.0}/src/vclient/models/system.py +0 -0
- {valentina_python_client-1.7.4 → valentina_python_client-1.8.0}/src/vclient/models/users.py +0 -0
- {valentina_python_client-1.7.4 → valentina_python_client-1.8.0}/src/vclient/py.typed +0 -0
- {valentina_python_client-1.7.4 → valentina_python_client-1.8.0}/src/vclient/registry.py +0 -0
- {valentina_python_client-1.7.4 → valentina_python_client-1.8.0}/src/vclient/services/__init__.py +0 -0
- {valentina_python_client-1.7.4 → valentina_python_client-1.8.0}/src/vclient/services/base.py +0 -0
- {valentina_python_client-1.7.4 → valentina_python_client-1.8.0}/src/vclient/services/campaign_book_chapters.py +0 -0
- {valentina_python_client-1.7.4 → valentina_python_client-1.8.0}/src/vclient/services/campaign_books.py +0 -0
- {valentina_python_client-1.7.4 → valentina_python_client-1.8.0}/src/vclient/services/campaigns.py +0 -0
- {valentina_python_client-1.7.4 → valentina_python_client-1.8.0}/src/vclient/services/character_autogen.py +0 -0
- {valentina_python_client-1.7.4 → valentina_python_client-1.8.0}/src/vclient/services/character_blueprint.py +0 -0
- {valentina_python_client-1.7.4 → valentina_python_client-1.8.0}/src/vclient/services/character_traits.py +0 -0
- {valentina_python_client-1.7.4 → valentina_python_client-1.8.0}/src/vclient/services/characters.py +0 -0
- {valentina_python_client-1.7.4 → valentina_python_client-1.8.0}/src/vclient/services/companies.py +0 -0
- {valentina_python_client-1.7.4 → valentina_python_client-1.8.0}/src/vclient/services/developers.py +0 -0
- {valentina_python_client-1.7.4 → valentina_python_client-1.8.0}/src/vclient/services/dicerolls.py +0 -0
- {valentina_python_client-1.7.4 → valentina_python_client-1.8.0}/src/vclient/services/dictionary.py +0 -0
- {valentina_python_client-1.7.4 → valentina_python_client-1.8.0}/src/vclient/services/global_admin.py +0 -0
- {valentina_python_client-1.7.4 → valentina_python_client-1.8.0}/src/vclient/services/options.py +0 -0
- {valentina_python_client-1.7.4 → valentina_python_client-1.8.0}/src/vclient/services/system.py +0 -0
- {valentina_python_client-1.7.4 → valentina_python_client-1.8.0}/src/vclient/services/users.py +0 -0
- {valentina_python_client-1.7.4 → valentina_python_client-1.8.0}/src/vclient/validate_constants.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: valentina-python-client
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.8.0
|
|
4
4
|
Summary: Async Python client library for the Valentina Noir API
|
|
5
5
|
Author: Nate Landau
|
|
6
6
|
Author-email: Nate Landau <github@natenate.org>
|
|
@@ -19,9 +19,11 @@ Requires-Dist: anyio>=4.12.1
|
|
|
19
19
|
Requires-Dist: httpx>=0.28.1
|
|
20
20
|
Requires-Dist: loguru>=0.7.3
|
|
21
21
|
Requires-Dist: pydantic[email]>=2.12.5
|
|
22
|
+
Requires-Dist: polyfactory>=2.21.0 ; extra == 'testing'
|
|
22
23
|
Requires-Python: >=3.13
|
|
23
24
|
Project-URL: Homepage, https://docs.valentina-noir.com/python-api-client/
|
|
24
25
|
Project-URL: Repository, https://github.com/natelandau/valentina-python-client
|
|
26
|
+
Provides-Extra: testing
|
|
25
27
|
Description-Content-Type: text/markdown
|
|
26
28
|
|
|
27
29
|
# Valentina Python Client
|
|
@@ -10,7 +10,10 @@
|
|
|
10
10
|
name = "valentina-python-client"
|
|
11
11
|
readme = "README.md"
|
|
12
12
|
requires-python = ">=3.13"
|
|
13
|
-
version = "1.
|
|
13
|
+
version = "1.8.0"
|
|
14
|
+
|
|
15
|
+
[project.optional-dependencies]
|
|
16
|
+
testing = ["polyfactory>=2.21.0"]
|
|
14
17
|
|
|
15
18
|
[project.urls]
|
|
16
19
|
Homepage = "https://docs.valentina-noir.com/python-api-client/"
|
|
@@ -39,11 +42,11 @@
|
|
|
39
42
|
"pytest-xdist>=3.8.0",
|
|
40
43
|
"pytest>=9.0.2",
|
|
41
44
|
"respx>=0.22.0",
|
|
42
|
-
"ruff>=0.15.
|
|
45
|
+
"ruff>=0.15.5",
|
|
43
46
|
"shellcheck-py>=0.11.0.1",
|
|
44
|
-
"ty>=0.0.
|
|
47
|
+
"ty>=0.0.21",
|
|
45
48
|
"typos>=1.44.0",
|
|
46
|
-
"vulture>=2.
|
|
49
|
+
"vulture>=2.15",
|
|
47
50
|
"yamllint>=1.38.0",
|
|
48
51
|
]
|
|
49
52
|
docs = ["zensical>=0.0.24"]
|
|
@@ -30,6 +30,7 @@ RENAME_CLASSES: dict[str, str] = {
|
|
|
30
30
|
"SystemService": "SyncSystemService",
|
|
31
31
|
"UsersService": "SyncUsersService",
|
|
32
32
|
"VClient": "SyncVClient",
|
|
33
|
+
"FakeVClient": "SyncFakeVClient",
|
|
33
34
|
}
|
|
34
35
|
|
|
35
36
|
FACTORY_RENAMES: dict[str, str] = {
|
|
@@ -73,6 +74,7 @@ IMPORT_REWRITES: dict[str, str] = {
|
|
|
73
74
|
"vclient.services.options": "vclient._sync.services.options",
|
|
74
75
|
"vclient.services.character_autogen": "vclient._sync.services.character_autogen",
|
|
75
76
|
"vclient.registry": "vclient._sync.registry",
|
|
77
|
+
"vclient.testing._client": "vclient._sync.testing._client",
|
|
76
78
|
}
|
|
77
79
|
|
|
78
80
|
# Combined lookup for renaming any identifier (class or factory function)
|
|
@@ -334,6 +336,22 @@ def _write_sync_init(path: Path) -> None:
|
|
|
334
336
|
path.write_text("\n".join(lines))
|
|
335
337
|
|
|
336
338
|
|
|
339
|
+
def _write_sync_testing_init(path: Path) -> None:
|
|
340
|
+
"""Write the _sync/testing/__init__.py that re-exports public names.
|
|
341
|
+
|
|
342
|
+
Args:
|
|
343
|
+
path: Path to the ``_sync/testing/__init__.py`` file to write.
|
|
344
|
+
"""
|
|
345
|
+
lines = [
|
|
346
|
+
HEADER_COMMENT,
|
|
347
|
+
"from vclient._sync.testing._client import SyncFakeVClient",
|
|
348
|
+
"",
|
|
349
|
+
'__all__ = ["SyncFakeVClient"]',
|
|
350
|
+
"",
|
|
351
|
+
]
|
|
352
|
+
path.write_text("\n".join(lines))
|
|
353
|
+
|
|
354
|
+
|
|
337
355
|
def generate_sync(src_dir: Path) -> None:
|
|
338
356
|
"""Transform all async source files and write them into the ``_sync/`` package.
|
|
339
357
|
|
|
@@ -362,6 +380,17 @@ def generate_sync(src_dir: Path) -> None:
|
|
|
362
380
|
# Write the _sync/__init__.py
|
|
363
381
|
_write_sync_init(sync_dir / "__init__.py")
|
|
364
382
|
|
|
383
|
+
# Transform testing module
|
|
384
|
+
testing_src = src_dir / "testing"
|
|
385
|
+
testing_dst = sync_dir / "testing"
|
|
386
|
+
if testing_src.exists():
|
|
387
|
+
testing_dst.mkdir(exist_ok=True)
|
|
388
|
+
client_source = testing_src / "_client.py"
|
|
389
|
+
if client_source.exists():
|
|
390
|
+
output_path = testing_dst / "_client.py"
|
|
391
|
+
output_path.write_text(transform_file(client_source))
|
|
392
|
+
_write_sync_testing_init(testing_dst / "__init__.py")
|
|
393
|
+
|
|
365
394
|
|
|
366
395
|
if __name__ == "__main__":
|
|
367
396
|
project_root = Path(sys.argv[1]) if len(sys.argv) > 1 else Path("src/vclient")
|
|
@@ -137,14 +137,28 @@ class SyncCharacterTraitsService(SyncBaseService):
|
|
|
137
137
|
)
|
|
138
138
|
return CharacterTrait.model_validate(response.json())
|
|
139
139
|
|
|
140
|
-
def delete(self, character_trait_id: str) -> None:
|
|
140
|
+
def delete(self, character_trait_id: str, currency: TraitModifyCurrency | None = None) -> None:
|
|
141
141
|
"""Delete a character trait.
|
|
142
142
|
|
|
143
143
|
Args:
|
|
144
144
|
character_trait_id: The ID of the trait to delete.
|
|
145
|
+
currency: The currency to use to recoup the cost of the trait.
|
|
146
|
+
|
|
147
|
+
Returns:
|
|
148
|
+
None
|
|
149
|
+
|
|
150
|
+
Raises:
|
|
151
|
+
NotFoundError: If the trait does not exist.
|
|
152
|
+
AuthorizationError: If you don't have access to the character.
|
|
153
|
+
RequestValidationError: If the input parameters fail client-side validation.
|
|
154
|
+
ValidationError: If the request data is invalid.
|
|
145
155
|
"""
|
|
156
|
+
params: dict[str, str | int] = {}
|
|
157
|
+
if currency is not None:
|
|
158
|
+
params["currency"] = currency
|
|
146
159
|
self._delete(
|
|
147
|
-
self._format_endpoint(Endpoints.CHARACTER_TRAIT, character_trait_id=character_trait_id)
|
|
160
|
+
self._format_endpoint(Endpoints.CHARACTER_TRAIT, character_trait_id=character_trait_id),
|
|
161
|
+
params=params or None,
|
|
148
162
|
)
|
|
149
163
|
|
|
150
164
|
def assign(self, trait_id: str, value: int) -> CharacterTrait:
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# AUTO-GENERATED — do not edit. Run 'uv run duty generate_sync' to regenerate.
|
|
2
|
+
"""Fake async API client for testing downstream applications.
|
|
3
|
+
|
|
4
|
+
FakeSyncVClient is a drop-in replacement for SyncVClient that uses httpx.MockTransport
|
|
5
|
+
instead of real HTTP. All real service classes work unmodified.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
from typing import Any
|
|
11
|
+
|
|
12
|
+
import httpx
|
|
13
|
+
|
|
14
|
+
from vclient._sync.client import SyncVClient
|
|
15
|
+
from vclient.testing._router import _FakeRouter
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class SyncFakeVClient(SyncVClient):
|
|
19
|
+
"""A fake SyncVClient for testing that uses mock HTTP transport.
|
|
20
|
+
|
|
21
|
+
Drop-in replacement for SyncVClient that returns auto-generated responses
|
|
22
|
+
for all endpoints. Registers itself as the default client so factory
|
|
23
|
+
functions like sync_campaigns_service() work without configuration.
|
|
24
|
+
|
|
25
|
+
Example:
|
|
26
|
+
```python
|
|
27
|
+
from vclient.testing import FakeSyncVClient
|
|
28
|
+
from vclient import sync_campaigns_service
|
|
29
|
+
|
|
30
|
+
async with FakeSyncVClient() as client:
|
|
31
|
+
campaigns = sync_campaigns_service("user123")
|
|
32
|
+
result = await campaigns.list_all()
|
|
33
|
+
```
|
|
34
|
+
"""
|
|
35
|
+
|
|
36
|
+
def __init__(
|
|
37
|
+
self,
|
|
38
|
+
*,
|
|
39
|
+
default_company_id: str = "fake-company",
|
|
40
|
+
set_as_default: bool = True,
|
|
41
|
+
**kwargs: Any,
|
|
42
|
+
) -> None:
|
|
43
|
+
self._router = _FakeRouter()
|
|
44
|
+
super().__init__(
|
|
45
|
+
base_url="https://fake.valentina-api.test",
|
|
46
|
+
api_key="fake-api-key",
|
|
47
|
+
default_company_id=default_company_id,
|
|
48
|
+
set_as_default=set_as_default,
|
|
49
|
+
**kwargs,
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
def _create_http_client(self) -> httpx.Client:
|
|
53
|
+
"""Create an HTTP client backed by the fake router."""
|
|
54
|
+
return httpx.Client(
|
|
55
|
+
transport=httpx.MockTransport(self._router.handle),
|
|
56
|
+
base_url="https://fake.valentina-api.test",
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
def add_route(
|
|
60
|
+
self, method: str, pattern: str, *, json: dict[str, Any], status_code: int = 200
|
|
61
|
+
) -> None:
|
|
62
|
+
"""Add a custom route override.
|
|
63
|
+
|
|
64
|
+
Args:
|
|
65
|
+
method: HTTP method (GET, POST, PATCH, DELETE, PUT).
|
|
66
|
+
pattern: Endpoint pattern from vclient.endpoints.Endpoints.
|
|
67
|
+
json: The JSON response body to return.
|
|
68
|
+
status_code: HTTP status code to return (default 200).
|
|
69
|
+
"""
|
|
70
|
+
self._router.add_route(method, pattern, json=json, status_code=status_code)
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
"""Testing utilities for downstream applications using vclient.
|
|
2
|
+
|
|
3
|
+
Requires the 'testing' extra: pip install vclient[testing]
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
try:
|
|
7
|
+
import polyfactory # noqa: F401
|
|
8
|
+
except ImportError as e:
|
|
9
|
+
msg = (
|
|
10
|
+
"vclient.testing requires the 'testing' extra. "
|
|
11
|
+
"Install it with: pip install vclient[testing]"
|
|
12
|
+
)
|
|
13
|
+
raise ImportError(msg) from e
|
|
14
|
+
|
|
15
|
+
from vclient._sync.testing import SyncFakeVClient
|
|
16
|
+
from vclient.testing._client import FakeVClient
|
|
17
|
+
from vclient.testing._factories import (
|
|
18
|
+
AssetFactory,
|
|
19
|
+
CampaignBookFactory,
|
|
20
|
+
CampaignChapterFactory,
|
|
21
|
+
CampaignExperienceFactory,
|
|
22
|
+
CampaignFactory,
|
|
23
|
+
CharacterConceptFactory,
|
|
24
|
+
CharacterFactory,
|
|
25
|
+
CharacterTraitFactory,
|
|
26
|
+
CharacterTraitValueOptionsResponseFactory,
|
|
27
|
+
ChargenSessionResponseFactory,
|
|
28
|
+
CompanyFactory,
|
|
29
|
+
CompanyPermissionsFactory,
|
|
30
|
+
DeveloperFactory,
|
|
31
|
+
DeveloperWithApiKeyFactory,
|
|
32
|
+
DicerollFactory,
|
|
33
|
+
DictionaryTermFactory,
|
|
34
|
+
EdgeAndPerksFactory,
|
|
35
|
+
HunterEdgeFactory,
|
|
36
|
+
HunterEdgePerkFactory,
|
|
37
|
+
InventoryItemFactory,
|
|
38
|
+
MeDeveloperFactory,
|
|
39
|
+
MeDeveloperWithApiKeyFactory,
|
|
40
|
+
NewCompanyResponseFactory,
|
|
41
|
+
NoteFactory,
|
|
42
|
+
PerkFactory,
|
|
43
|
+
QuickrollFactory,
|
|
44
|
+
RollStatisticsFactory,
|
|
45
|
+
SheetSectionFactory,
|
|
46
|
+
SystemHealthFactory,
|
|
47
|
+
TraitCategoryFactory,
|
|
48
|
+
TraitFactory,
|
|
49
|
+
UserFactory,
|
|
50
|
+
VampireClanFactory,
|
|
51
|
+
WerewolfAuspiceFactory,
|
|
52
|
+
WerewolfGiftFactory,
|
|
53
|
+
WerewolfRiteFactory,
|
|
54
|
+
WerewolfTribeFactory,
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
__all__ = [
|
|
58
|
+
"AssetFactory",
|
|
59
|
+
"CampaignBookFactory",
|
|
60
|
+
"CampaignChapterFactory",
|
|
61
|
+
"CampaignExperienceFactory",
|
|
62
|
+
"CampaignFactory",
|
|
63
|
+
"CharacterConceptFactory",
|
|
64
|
+
"CharacterFactory",
|
|
65
|
+
"CharacterTraitFactory",
|
|
66
|
+
"CharacterTraitValueOptionsResponseFactory",
|
|
67
|
+
"ChargenSessionResponseFactory",
|
|
68
|
+
"CompanyFactory",
|
|
69
|
+
"CompanyPermissionsFactory",
|
|
70
|
+
"DeveloperFactory",
|
|
71
|
+
"DeveloperWithApiKeyFactory",
|
|
72
|
+
"DicerollFactory",
|
|
73
|
+
"DictionaryTermFactory",
|
|
74
|
+
"EdgeAndPerksFactory",
|
|
75
|
+
"FakeVClient",
|
|
76
|
+
"HunterEdgeFactory",
|
|
77
|
+
"HunterEdgePerkFactory",
|
|
78
|
+
"InventoryItemFactory",
|
|
79
|
+
"MeDeveloperFactory",
|
|
80
|
+
"MeDeveloperWithApiKeyFactory",
|
|
81
|
+
"NewCompanyResponseFactory",
|
|
82
|
+
"NoteFactory",
|
|
83
|
+
"PerkFactory",
|
|
84
|
+
"QuickrollFactory",
|
|
85
|
+
"RollStatisticsFactory",
|
|
86
|
+
"SheetSectionFactory",
|
|
87
|
+
"SyncFakeVClient",
|
|
88
|
+
"SystemHealthFactory",
|
|
89
|
+
"TraitCategoryFactory",
|
|
90
|
+
"TraitFactory",
|
|
91
|
+
"UserFactory",
|
|
92
|
+
"VampireClanFactory",
|
|
93
|
+
"WerewolfAuspiceFactory",
|
|
94
|
+
"WerewolfGiftFactory",
|
|
95
|
+
"WerewolfRiteFactory",
|
|
96
|
+
"WerewolfTribeFactory",
|
|
97
|
+
]
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
"""Fake async API client for testing downstream applications.
|
|
2
|
+
|
|
3
|
+
FakeVClient is a drop-in replacement for VClient that uses httpx.MockTransport
|
|
4
|
+
instead of real HTTP. All real service classes work unmodified.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
from typing import Any
|
|
10
|
+
|
|
11
|
+
import httpx
|
|
12
|
+
|
|
13
|
+
from vclient.client import VClient
|
|
14
|
+
from vclient.testing._router import _FakeRouter
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class FakeVClient(VClient):
|
|
18
|
+
"""A fake VClient for testing that uses mock HTTP transport.
|
|
19
|
+
|
|
20
|
+
Drop-in replacement for VClient that returns auto-generated responses
|
|
21
|
+
for all endpoints. Registers itself as the default client so factory
|
|
22
|
+
functions like campaigns_service() work without configuration.
|
|
23
|
+
|
|
24
|
+
Example:
|
|
25
|
+
```python
|
|
26
|
+
from vclient.testing import FakeVClient
|
|
27
|
+
from vclient import campaigns_service
|
|
28
|
+
|
|
29
|
+
async with FakeVClient() as client:
|
|
30
|
+
campaigns = campaigns_service("user123")
|
|
31
|
+
result = await campaigns.list_all()
|
|
32
|
+
```
|
|
33
|
+
"""
|
|
34
|
+
|
|
35
|
+
def __init__(
|
|
36
|
+
self,
|
|
37
|
+
*,
|
|
38
|
+
default_company_id: str = "fake-company",
|
|
39
|
+
set_as_default: bool = True,
|
|
40
|
+
**kwargs: Any,
|
|
41
|
+
) -> None:
|
|
42
|
+
self._router = _FakeRouter()
|
|
43
|
+
super().__init__(
|
|
44
|
+
base_url="https://fake.valentina-api.test",
|
|
45
|
+
api_key="fake-api-key",
|
|
46
|
+
default_company_id=default_company_id,
|
|
47
|
+
set_as_default=set_as_default,
|
|
48
|
+
**kwargs,
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
def _create_http_client(self) -> httpx.AsyncClient:
|
|
52
|
+
"""Create an HTTP client backed by the fake router."""
|
|
53
|
+
return httpx.AsyncClient(
|
|
54
|
+
transport=httpx.MockTransport(self._router.handle),
|
|
55
|
+
base_url="https://fake.valentina-api.test",
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
def add_route(
|
|
59
|
+
self,
|
|
60
|
+
method: str,
|
|
61
|
+
pattern: str,
|
|
62
|
+
*,
|
|
63
|
+
json: dict[str, Any],
|
|
64
|
+
status_code: int = 200,
|
|
65
|
+
) -> None:
|
|
66
|
+
"""Add a custom route override.
|
|
67
|
+
|
|
68
|
+
Args:
|
|
69
|
+
method: HTTP method (GET, POST, PATCH, DELETE, PUT).
|
|
70
|
+
pattern: Endpoint pattern from vclient.endpoints.Endpoints.
|
|
71
|
+
json: The JSON response body to return.
|
|
72
|
+
status_code: HTTP status code to return (default 200).
|
|
73
|
+
"""
|
|
74
|
+
self._router.add_route(method, pattern, json=json, status_code=status_code)
|
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
"""Polyfactory model factories for all vclient response models."""
|
|
2
|
+
|
|
3
|
+
from polyfactory.factories.pydantic_factory import ModelFactory
|
|
4
|
+
|
|
5
|
+
from vclient.models import (
|
|
6
|
+
Asset,
|
|
7
|
+
Campaign,
|
|
8
|
+
CampaignBook,
|
|
9
|
+
CampaignChapter,
|
|
10
|
+
Character,
|
|
11
|
+
CharacterConcept,
|
|
12
|
+
CharacterTrait,
|
|
13
|
+
CharacterTraitValueOptionsResponse,
|
|
14
|
+
Company,
|
|
15
|
+
CompanyPermissions,
|
|
16
|
+
Developer,
|
|
17
|
+
DeveloperWithApiKey,
|
|
18
|
+
Diceroll,
|
|
19
|
+
DictionaryTerm,
|
|
20
|
+
EdgeAndPerks,
|
|
21
|
+
HunterEdge,
|
|
22
|
+
HunterEdgePerk,
|
|
23
|
+
InventoryItem,
|
|
24
|
+
MeDeveloper,
|
|
25
|
+
MeDeveloperWithApiKey,
|
|
26
|
+
NewCompanyResponse,
|
|
27
|
+
Note,
|
|
28
|
+
Perk,
|
|
29
|
+
Quickroll,
|
|
30
|
+
RollStatistics,
|
|
31
|
+
SheetSection,
|
|
32
|
+
SystemHealth,
|
|
33
|
+
Trait,
|
|
34
|
+
TraitCategory,
|
|
35
|
+
User,
|
|
36
|
+
VampireClan,
|
|
37
|
+
WerewolfAuspice,
|
|
38
|
+
WerewolfGift,
|
|
39
|
+
WerewolfRite,
|
|
40
|
+
WerewolfTribe,
|
|
41
|
+
)
|
|
42
|
+
from vclient.models.character_autogen import ChargenSessionResponse
|
|
43
|
+
from vclient.models.users import CampaignExperience
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
class AssetFactory(ModelFactory[Asset]):
|
|
47
|
+
__model__ = Asset
|
|
48
|
+
__use_defaults__ = True
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
class CampaignFactory(ModelFactory[Campaign]):
|
|
52
|
+
__model__ = Campaign
|
|
53
|
+
__use_defaults__ = True
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
class CampaignBookFactory(ModelFactory[CampaignBook]):
|
|
57
|
+
__model__ = CampaignBook
|
|
58
|
+
__use_defaults__ = True
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
class CampaignChapterFactory(ModelFactory[CampaignChapter]):
|
|
62
|
+
__model__ = CampaignChapter
|
|
63
|
+
__use_defaults__ = True
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
class CampaignExperienceFactory(ModelFactory[CampaignExperience]):
|
|
67
|
+
__model__ = CampaignExperience
|
|
68
|
+
__use_defaults__ = True
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
class CharacterFactory(ModelFactory[Character]):
|
|
72
|
+
__model__ = Character
|
|
73
|
+
__use_defaults__ = True
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
class CharacterConceptFactory(ModelFactory[CharacterConcept]):
|
|
77
|
+
__model__ = CharacterConcept
|
|
78
|
+
__use_defaults__ = True
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
class CharacterTraitFactory(ModelFactory[CharacterTrait]):
|
|
82
|
+
__model__ = CharacterTrait
|
|
83
|
+
__use_defaults__ = True
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
class CharacterTraitValueOptionsResponseFactory(
|
|
87
|
+
ModelFactory[CharacterTraitValueOptionsResponse],
|
|
88
|
+
):
|
|
89
|
+
__model__ = CharacterTraitValueOptionsResponse
|
|
90
|
+
__use_defaults__ = True
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
class ChargenSessionResponseFactory(ModelFactory[ChargenSessionResponse]):
|
|
94
|
+
__model__ = ChargenSessionResponse
|
|
95
|
+
__use_defaults__ = True
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
class CompanyFactory(ModelFactory[Company]):
|
|
99
|
+
__model__ = Company
|
|
100
|
+
__use_defaults__ = True
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
class CompanyPermissionsFactory(ModelFactory[CompanyPermissions]):
|
|
104
|
+
__model__ = CompanyPermissions
|
|
105
|
+
__use_defaults__ = True
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
class DeveloperFactory(ModelFactory[Developer]):
|
|
109
|
+
__model__ = Developer
|
|
110
|
+
__use_defaults__ = True
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
class DeveloperWithApiKeyFactory(ModelFactory[DeveloperWithApiKey]):
|
|
114
|
+
__model__ = DeveloperWithApiKey
|
|
115
|
+
__use_defaults__ = True
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
class DicerollFactory(ModelFactory[Diceroll]):
|
|
119
|
+
__model__ = Diceroll
|
|
120
|
+
__use_defaults__ = True
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
class DictionaryTermFactory(ModelFactory[DictionaryTerm]):
|
|
124
|
+
__model__ = DictionaryTerm
|
|
125
|
+
__use_defaults__ = True
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
class EdgeAndPerksFactory(ModelFactory[EdgeAndPerks]):
|
|
129
|
+
__model__ = EdgeAndPerks
|
|
130
|
+
__use_defaults__ = True
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
class HunterEdgeFactory(ModelFactory[HunterEdge]):
|
|
134
|
+
__model__ = HunterEdge
|
|
135
|
+
__use_defaults__ = True
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
class HunterEdgePerkFactory(ModelFactory[HunterEdgePerk]):
|
|
139
|
+
__model__ = HunterEdgePerk
|
|
140
|
+
__use_defaults__ = True
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
class InventoryItemFactory(ModelFactory[InventoryItem]):
|
|
144
|
+
__model__ = InventoryItem
|
|
145
|
+
__use_defaults__ = True
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
class MeDeveloperFactory(ModelFactory[MeDeveloper]):
|
|
149
|
+
__model__ = MeDeveloper
|
|
150
|
+
__use_defaults__ = True
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
class MeDeveloperWithApiKeyFactory(ModelFactory[MeDeveloperWithApiKey]):
|
|
154
|
+
__model__ = MeDeveloperWithApiKey
|
|
155
|
+
__use_defaults__ = True
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
class NewCompanyResponseFactory(ModelFactory[NewCompanyResponse]):
|
|
159
|
+
__model__ = NewCompanyResponse
|
|
160
|
+
__use_defaults__ = True
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
class NoteFactory(ModelFactory[Note]):
|
|
164
|
+
__model__ = Note
|
|
165
|
+
__use_defaults__ = True
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
class PerkFactory(ModelFactory[Perk]):
|
|
169
|
+
__model__ = Perk
|
|
170
|
+
__use_defaults__ = True
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
class QuickrollFactory(ModelFactory[Quickroll]):
|
|
174
|
+
__model__ = Quickroll
|
|
175
|
+
__use_defaults__ = True
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
class RollStatisticsFactory(ModelFactory[RollStatistics]):
|
|
179
|
+
__model__ = RollStatistics
|
|
180
|
+
__use_defaults__ = True
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
class SheetSectionFactory(ModelFactory[SheetSection]):
|
|
184
|
+
__model__ = SheetSection
|
|
185
|
+
__use_defaults__ = True
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
class SystemHealthFactory(ModelFactory[SystemHealth]):
|
|
189
|
+
__model__ = SystemHealth
|
|
190
|
+
__use_defaults__ = True
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
class TraitCategoryFactory(ModelFactory[TraitCategory]):
|
|
194
|
+
__model__ = TraitCategory
|
|
195
|
+
__use_defaults__ = True
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
class TraitFactory(ModelFactory[Trait]):
|
|
199
|
+
__model__ = Trait
|
|
200
|
+
__use_defaults__ = True
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
class UserFactory(ModelFactory[User]):
|
|
204
|
+
__model__ = User
|
|
205
|
+
__use_defaults__ = True
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
class VampireClanFactory(ModelFactory[VampireClan]):
|
|
209
|
+
__model__ = VampireClan
|
|
210
|
+
__use_defaults__ = True
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
class WerewolfAuspiceFactory(ModelFactory[WerewolfAuspice]):
|
|
214
|
+
__model__ = WerewolfAuspice
|
|
215
|
+
__use_defaults__ = True
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
class WerewolfGiftFactory(ModelFactory[WerewolfGift]):
|
|
219
|
+
__model__ = WerewolfGift
|
|
220
|
+
__use_defaults__ = True
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
class WerewolfRiteFactory(ModelFactory[WerewolfRite]):
|
|
224
|
+
__model__ = WerewolfRite
|
|
225
|
+
__use_defaults__ = True
|
|
226
|
+
|
|
227
|
+
|
|
228
|
+
class WerewolfTribeFactory(ModelFactory[WerewolfTribe]):
|
|
229
|
+
__model__ = WerewolfTribe
|
|
230
|
+
__use_defaults__ = True
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
__all__ = [
|
|
234
|
+
"AssetFactory",
|
|
235
|
+
"CampaignBookFactory",
|
|
236
|
+
"CampaignChapterFactory",
|
|
237
|
+
"CampaignExperienceFactory",
|
|
238
|
+
"CampaignFactory",
|
|
239
|
+
"CharacterConceptFactory",
|
|
240
|
+
"CharacterFactory",
|
|
241
|
+
"CharacterTraitFactory",
|
|
242
|
+
"CharacterTraitValueOptionsResponseFactory",
|
|
243
|
+
"ChargenSessionResponseFactory",
|
|
244
|
+
"CompanyFactory",
|
|
245
|
+
"CompanyPermissionsFactory",
|
|
246
|
+
"DeveloperFactory",
|
|
247
|
+
"DeveloperWithApiKeyFactory",
|
|
248
|
+
"DicerollFactory",
|
|
249
|
+
"DictionaryTermFactory",
|
|
250
|
+
"EdgeAndPerksFactory",
|
|
251
|
+
"HunterEdgeFactory",
|
|
252
|
+
"HunterEdgePerkFactory",
|
|
253
|
+
"InventoryItemFactory",
|
|
254
|
+
"MeDeveloperFactory",
|
|
255
|
+
"MeDeveloperWithApiKeyFactory",
|
|
256
|
+
"NewCompanyResponseFactory",
|
|
257
|
+
"NoteFactory",
|
|
258
|
+
"PerkFactory",
|
|
259
|
+
"QuickrollFactory",
|
|
260
|
+
"RollStatisticsFactory",
|
|
261
|
+
"SheetSectionFactory",
|
|
262
|
+
"SystemHealthFactory",
|
|
263
|
+
"TraitCategoryFactory",
|
|
264
|
+
"TraitFactory",
|
|
265
|
+
"UserFactory",
|
|
266
|
+
"VampireClanFactory",
|
|
267
|
+
"WerewolfAuspiceFactory",
|
|
268
|
+
"WerewolfGiftFactory",
|
|
269
|
+
"WerewolfRiteFactory",
|
|
270
|
+
"WerewolfTribeFactory",
|
|
271
|
+
]
|