valentina-python-client 1.20.1__tar.gz → 1.21.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.20.1 → valentina_python_client-1.21.0}/PKG-INFO +1 -1
- {valentina_python_client-1.20.1 → valentina_python_client-1.21.0}/pyproject.toml +1 -1
- {valentina_python_client-1.20.1 → valentina_python_client-1.21.0}/src/vclient/__init__.py +5 -1
- {valentina_python_client-1.20.1 → valentina_python_client-1.21.0}/src/vclient/_codegen.py +5 -0
- {valentina_python_client-1.20.1 → valentina_python_client-1.21.0}/src/vclient/_sync/__init__.py +2 -0
- {valentina_python_client-1.20.1 → valentina_python_client-1.21.0}/src/vclient/_sync/client.py +15 -0
- {valentina_python_client-1.20.1 → valentina_python_client-1.21.0}/src/vclient/_sync/registry.py +24 -0
- {valentina_python_client-1.20.1 → valentina_python_client-1.21.0}/src/vclient/_sync/services/__init__.py +2 -0
- valentina_python_client-1.21.0/src/vclient/_sync/services/user_lookup.py +68 -0
- {valentina_python_client-1.20.1 → valentina_python_client-1.21.0}/src/vclient/client.py +15 -0
- {valentina_python_client-1.20.1 → valentina_python_client-1.21.0}/src/vclient/endpoints.py +3 -0
- {valentina_python_client-1.20.1 → valentina_python_client-1.21.0}/src/vclient/models/__init__.py +4 -0
- valentina_python_client-1.21.0/src/vclient/models/user_lookup.py +22 -0
- {valentina_python_client-1.20.1 → valentina_python_client-1.21.0}/src/vclient/registry.py +24 -0
- {valentina_python_client-1.20.1 → valentina_python_client-1.21.0}/src/vclient/services/__init__.py +2 -0
- valentina_python_client-1.21.0/src/vclient/services/user_lookup.py +67 -0
- {valentina_python_client-1.20.1 → valentina_python_client-1.21.0}/src/vclient/testing/__init__.py +2 -0
- {valentina_python_client-1.20.1 → valentina_python_client-1.21.0}/src/vclient/testing/_factories.py +8 -0
- {valentina_python_client-1.20.1 → valentina_python_client-1.21.0}/src/vclient/testing/_router.py +3 -0
- {valentina_python_client-1.20.1 → valentina_python_client-1.21.0}/src/vclient/testing/_routes.py +3 -0
- {valentina_python_client-1.20.1 → valentina_python_client-1.21.0}/LICENSE +0 -0
- {valentina_python_client-1.20.1 → valentina_python_client-1.21.0}/README.md +0 -0
- {valentina_python_client-1.20.1 → valentina_python_client-1.21.0}/src/vclient/_sync/services/base.py +0 -0
- {valentina_python_client-1.20.1 → valentina_python_client-1.21.0}/src/vclient/_sync/services/campaign_book_chapters.py +0 -0
- {valentina_python_client-1.20.1 → valentina_python_client-1.21.0}/src/vclient/_sync/services/campaign_books.py +0 -0
- {valentina_python_client-1.20.1 → valentina_python_client-1.21.0}/src/vclient/_sync/services/campaigns.py +0 -0
- {valentina_python_client-1.20.1 → valentina_python_client-1.21.0}/src/vclient/_sync/services/character_autogen.py +0 -0
- {valentina_python_client-1.20.1 → valentina_python_client-1.21.0}/src/vclient/_sync/services/character_blueprint.py +0 -0
- {valentina_python_client-1.20.1 → valentina_python_client-1.21.0}/src/vclient/_sync/services/character_traits.py +0 -0
- {valentina_python_client-1.20.1 → valentina_python_client-1.21.0}/src/vclient/_sync/services/characters.py +0 -0
- {valentina_python_client-1.20.1 → valentina_python_client-1.21.0}/src/vclient/_sync/services/companies.py +0 -0
- {valentina_python_client-1.20.1 → valentina_python_client-1.21.0}/src/vclient/_sync/services/developers.py +0 -0
- {valentina_python_client-1.20.1 → valentina_python_client-1.21.0}/src/vclient/_sync/services/dicerolls.py +0 -0
- {valentina_python_client-1.20.1 → valentina_python_client-1.21.0}/src/vclient/_sync/services/dictionary.py +0 -0
- {valentina_python_client-1.20.1 → valentina_python_client-1.21.0}/src/vclient/_sync/services/global_admin.py +0 -0
- {valentina_python_client-1.20.1 → valentina_python_client-1.21.0}/src/vclient/_sync/services/options.py +0 -0
- {valentina_python_client-1.20.1 → valentina_python_client-1.21.0}/src/vclient/_sync/services/system.py +0 -0
- {valentina_python_client-1.20.1 → valentina_python_client-1.21.0}/src/vclient/_sync/services/users.py +0 -0
- {valentina_python_client-1.20.1 → valentina_python_client-1.21.0}/src/vclient/_sync/testing/__init__.py +0 -0
- {valentina_python_client-1.20.1 → valentina_python_client-1.21.0}/src/vclient/_sync/testing/_client.py +0 -0
- {valentina_python_client-1.20.1 → valentina_python_client-1.21.0}/src/vclient/config.py +0 -0
- {valentina_python_client-1.20.1 → valentina_python_client-1.21.0}/src/vclient/constants.py +0 -0
- {valentina_python_client-1.20.1 → valentina_python_client-1.21.0}/src/vclient/exceptions.py +0 -0
- {valentina_python_client-1.20.1 → valentina_python_client-1.21.0}/src/vclient/models/books.py +0 -0
- {valentina_python_client-1.20.1 → valentina_python_client-1.21.0}/src/vclient/models/campaigns.py +0 -0
- {valentina_python_client-1.20.1 → valentina_python_client-1.21.0}/src/vclient/models/chapters.py +0 -0
- {valentina_python_client-1.20.1 → valentina_python_client-1.21.0}/src/vclient/models/character_autogen.py +0 -0
- {valentina_python_client-1.20.1 → valentina_python_client-1.21.0}/src/vclient/models/character_blueprint.py +0 -0
- {valentina_python_client-1.20.1 → valentina_python_client-1.21.0}/src/vclient/models/character_trait.py +0 -0
- {valentina_python_client-1.20.1 → valentina_python_client-1.21.0}/src/vclient/models/characters.py +0 -0
- {valentina_python_client-1.20.1 → valentina_python_client-1.21.0}/src/vclient/models/companies.py +0 -0
- {valentina_python_client-1.20.1 → valentina_python_client-1.21.0}/src/vclient/models/developers.py +0 -0
- {valentina_python_client-1.20.1 → valentina_python_client-1.21.0}/src/vclient/models/diceroll.py +0 -0
- {valentina_python_client-1.20.1 → valentina_python_client-1.21.0}/src/vclient/models/dictionary.py +0 -0
- {valentina_python_client-1.20.1 → valentina_python_client-1.21.0}/src/vclient/models/full_sheet.py +0 -0
- {valentina_python_client-1.20.1 → valentina_python_client-1.21.0}/src/vclient/models/global_admin.py +0 -0
- {valentina_python_client-1.20.1 → valentina_python_client-1.21.0}/src/vclient/models/pagination.py +0 -0
- {valentina_python_client-1.20.1 → valentina_python_client-1.21.0}/src/vclient/models/shared.py +0 -0
- {valentina_python_client-1.20.1 → valentina_python_client-1.21.0}/src/vclient/models/system.py +0 -0
- {valentina_python_client-1.20.1 → valentina_python_client-1.21.0}/src/vclient/models/users.py +0 -0
- {valentina_python_client-1.20.1 → valentina_python_client-1.21.0}/src/vclient/py.typed +0 -0
- {valentina_python_client-1.20.1 → valentina_python_client-1.21.0}/src/vclient/services/base.py +0 -0
- {valentina_python_client-1.20.1 → valentina_python_client-1.21.0}/src/vclient/services/campaign_book_chapters.py +0 -0
- {valentina_python_client-1.20.1 → valentina_python_client-1.21.0}/src/vclient/services/campaign_books.py +0 -0
- {valentina_python_client-1.20.1 → valentina_python_client-1.21.0}/src/vclient/services/campaigns.py +0 -0
- {valentina_python_client-1.20.1 → valentina_python_client-1.21.0}/src/vclient/services/character_autogen.py +0 -0
- {valentina_python_client-1.20.1 → valentina_python_client-1.21.0}/src/vclient/services/character_blueprint.py +0 -0
- {valentina_python_client-1.20.1 → valentina_python_client-1.21.0}/src/vclient/services/character_traits.py +0 -0
- {valentina_python_client-1.20.1 → valentina_python_client-1.21.0}/src/vclient/services/characters.py +0 -0
- {valentina_python_client-1.20.1 → valentina_python_client-1.21.0}/src/vclient/services/companies.py +0 -0
- {valentina_python_client-1.20.1 → valentina_python_client-1.21.0}/src/vclient/services/developers.py +0 -0
- {valentina_python_client-1.20.1 → valentina_python_client-1.21.0}/src/vclient/services/dicerolls.py +0 -0
- {valentina_python_client-1.20.1 → valentina_python_client-1.21.0}/src/vclient/services/dictionary.py +0 -0
- {valentina_python_client-1.20.1 → valentina_python_client-1.21.0}/src/vclient/services/global_admin.py +0 -0
- {valentina_python_client-1.20.1 → valentina_python_client-1.21.0}/src/vclient/services/options.py +0 -0
- {valentina_python_client-1.20.1 → valentina_python_client-1.21.0}/src/vclient/services/system.py +0 -0
- {valentina_python_client-1.20.1 → valentina_python_client-1.21.0}/src/vclient/services/users.py +0 -0
- {valentina_python_client-1.20.1 → valentina_python_client-1.21.0}/src/vclient/testing/_client.py +0 -0
- {valentina_python_client-1.20.1 → valentina_python_client-1.21.0}/src/vclient/validate_constants.py +0 -0
|
@@ -49,6 +49,7 @@ from vclient._sync import ( # noqa: E402
|
|
|
49
49
|
sync_global_admin_service,
|
|
50
50
|
sync_options_service,
|
|
51
51
|
sync_system_service,
|
|
52
|
+
sync_user_lookup_service,
|
|
52
53
|
sync_users_service,
|
|
53
54
|
)
|
|
54
55
|
from vclient.client import VClient # noqa: E402
|
|
@@ -67,6 +68,7 @@ from vclient.registry import ( # noqa: E402
|
|
|
67
68
|
global_admin_service,
|
|
68
69
|
options_service,
|
|
69
70
|
system_service,
|
|
71
|
+
user_lookup_service,
|
|
70
72
|
users_service,
|
|
71
73
|
)
|
|
72
74
|
|
|
@@ -100,9 +102,11 @@ __all__ = (
|
|
|
100
102
|
"sync_global_admin_service",
|
|
101
103
|
"sync_options_service",
|
|
102
104
|
"sync_system_service",
|
|
105
|
+
"sync_user_lookup_service",
|
|
103
106
|
"sync_users_service",
|
|
104
107
|
"system_service",
|
|
108
|
+
"user_lookup_service",
|
|
105
109
|
"users_service",
|
|
106
110
|
)
|
|
107
111
|
|
|
108
|
-
__version__ = "1.
|
|
112
|
+
__version__ = "1.21.0"
|
|
@@ -28,6 +28,7 @@ RENAME_CLASSES: dict[str, str] = {
|
|
|
28
28
|
"GlobalAdminService": "SyncGlobalAdminService",
|
|
29
29
|
"OptionsService": "SyncOptionsService",
|
|
30
30
|
"SystemService": "SyncSystemService",
|
|
31
|
+
"UserLookupService": "SyncUserLookupService",
|
|
31
32
|
"UsersService": "SyncUsersService",
|
|
32
33
|
"VClient": "SyncVClient",
|
|
33
34
|
"FakeVClient": "SyncFakeVClient",
|
|
@@ -49,6 +50,7 @@ FACTORY_RENAMES: dict[str, str] = {
|
|
|
49
50
|
"dicerolls_service": "sync_dicerolls_service",
|
|
50
51
|
"options_service": "sync_options_service",
|
|
51
52
|
"character_autogen_service": "sync_character_autogen_service",
|
|
53
|
+
"user_lookup_service": "sync_user_lookup_service",
|
|
52
54
|
"configure_default_client": "sync_configure_default_client",
|
|
53
55
|
"clear_default_client": "sync_clear_default_client",
|
|
54
56
|
"default_client": "sync_default_client",
|
|
@@ -73,6 +75,7 @@ IMPORT_REWRITES: dict[str, str] = {
|
|
|
73
75
|
"vclient.services.dicerolls": "vclient._sync.services.dicerolls",
|
|
74
76
|
"vclient.services.options": "vclient._sync.services.options",
|
|
75
77
|
"vclient.services.character_autogen": "vclient._sync.services.character_autogen",
|
|
78
|
+
"vclient.services.user_lookup": "vclient._sync.services.user_lookup",
|
|
76
79
|
"vclient.registry": "vclient._sync.registry",
|
|
77
80
|
"vclient.testing._client": "vclient._sync.testing._client",
|
|
78
81
|
}
|
|
@@ -307,6 +310,7 @@ def _write_sync_init(path: Path) -> None:
|
|
|
307
310
|
" sync_global_admin_service,",
|
|
308
311
|
" sync_options_service,",
|
|
309
312
|
" sync_system_service,",
|
|
313
|
+
" sync_user_lookup_service,",
|
|
310
314
|
" sync_users_service,",
|
|
311
315
|
")",
|
|
312
316
|
"",
|
|
@@ -329,6 +333,7 @@ def _write_sync_init(path: Path) -> None:
|
|
|
329
333
|
' "sync_global_admin_service",',
|
|
330
334
|
' "sync_options_service",',
|
|
331
335
|
' "sync_system_service",',
|
|
336
|
+
' "sync_user_lookup_service",',
|
|
332
337
|
' "sync_users_service",',
|
|
333
338
|
"]",
|
|
334
339
|
"",
|
{valentina_python_client-1.20.1 → valentina_python_client-1.21.0}/src/vclient/_sync/__init__.py
RENAMED
|
@@ -19,6 +19,7 @@ from vclient._sync.registry import (
|
|
|
19
19
|
sync_global_admin_service,
|
|
20
20
|
sync_options_service,
|
|
21
21
|
sync_system_service,
|
|
22
|
+
sync_user_lookup_service,
|
|
22
23
|
sync_users_service,
|
|
23
24
|
)
|
|
24
25
|
|
|
@@ -41,5 +42,6 @@ __all__ = [
|
|
|
41
42
|
"sync_global_admin_service",
|
|
42
43
|
"sync_options_service",
|
|
43
44
|
"sync_system_service",
|
|
45
|
+
"sync_user_lookup_service",
|
|
44
46
|
"sync_users_service",
|
|
45
47
|
]
|
{valentina_python_client-1.20.1 → valentina_python_client-1.21.0}/src/vclient/_sync/client.py
RENAMED
|
@@ -37,6 +37,7 @@ if TYPE_CHECKING:
|
|
|
37
37
|
SyncGlobalAdminService,
|
|
38
38
|
SyncOptionsService,
|
|
39
39
|
SyncSystemService,
|
|
40
|
+
SyncUserLookupService,
|
|
40
41
|
SyncUsersService,
|
|
41
42
|
)
|
|
42
43
|
|
|
@@ -147,6 +148,7 @@ class SyncVClient:
|
|
|
147
148
|
self._developer: SyncDeveloperService | None = None
|
|
148
149
|
self._global_admin: SyncGlobalAdminService | None = None
|
|
149
150
|
self._system: SyncSystemService | None = None
|
|
151
|
+
self._user_lookup: SyncUserLookupService | None = None
|
|
150
152
|
if set_as_default:
|
|
151
153
|
from vclient._sync.registry import sync_configure_default_client
|
|
152
154
|
|
|
@@ -278,6 +280,19 @@ class SyncVClient:
|
|
|
278
280
|
self._system = SyncSystemService(self)
|
|
279
281
|
return self._system
|
|
280
282
|
|
|
283
|
+
@property
|
|
284
|
+
def user_lookup(self) -> "SyncUserLookupService":
|
|
285
|
+
"""Access the User Lookup service for cross-company user discovery.
|
|
286
|
+
|
|
287
|
+
Returns:
|
|
288
|
+
The SyncUserLookupService instance for user lookup operations.
|
|
289
|
+
"""
|
|
290
|
+
if self._user_lookup is None:
|
|
291
|
+
from vclient._sync.services.user_lookup import SyncUserLookupService
|
|
292
|
+
|
|
293
|
+
self._user_lookup = SyncUserLookupService(self)
|
|
294
|
+
return self._user_lookup
|
|
295
|
+
|
|
281
296
|
def users(self, company_id: str | None = None) -> "SyncUsersService":
|
|
282
297
|
"""Get a SyncUsersService scoped to a specific company.
|
|
283
298
|
|
{valentina_python_client-1.20.1 → valentina_python_client-1.21.0}/src/vclient/_sync/registry.py
RENAMED
|
@@ -38,6 +38,7 @@ if TYPE_CHECKING:
|
|
|
38
38
|
SyncGlobalAdminService,
|
|
39
39
|
SyncOptionsService,
|
|
40
40
|
SyncSystemService,
|
|
41
|
+
SyncUserLookupService,
|
|
41
42
|
SyncUsersService,
|
|
42
43
|
)
|
|
43
44
|
_default_client: "SyncVClient | None" = None
|
|
@@ -189,6 +190,29 @@ def sync_system_service() -> "SyncSystemService":
|
|
|
189
190
|
return SyncSystemService(sync_default_client())
|
|
190
191
|
|
|
191
192
|
|
|
193
|
+
def sync_user_lookup_service() -> "SyncUserLookupService":
|
|
194
|
+
"""Create a SyncUserLookupService using the default client.
|
|
195
|
+
|
|
196
|
+
Discover which companies a person has a user record in by searching
|
|
197
|
+
via email, Discord ID, Google ID, or GitHub ID.
|
|
198
|
+
|
|
199
|
+
Returns:
|
|
200
|
+
SyncUserLookupService: A service instance for cross-company user lookup.
|
|
201
|
+
|
|
202
|
+
Raises:
|
|
203
|
+
RuntimeError: If no default client has been configured.
|
|
204
|
+
|
|
205
|
+
Example:
|
|
206
|
+
```python
|
|
207
|
+
lookup = sync_user_lookup_service()
|
|
208
|
+
results = await lookup.by_email("alice@example.com")
|
|
209
|
+
```
|
|
210
|
+
"""
|
|
211
|
+
from vclient._sync.services.user_lookup import SyncUserLookupService
|
|
212
|
+
|
|
213
|
+
return SyncUserLookupService(sync_default_client())
|
|
214
|
+
|
|
215
|
+
|
|
192
216
|
def sync_users_service(company_id: str | None = None) -> "SyncUsersService":
|
|
193
217
|
"""Create a SyncUsersService scoped to a specific company using the default client.
|
|
194
218
|
|
|
@@ -16,6 +16,7 @@ from .dictionary import SyncDictionaryService
|
|
|
16
16
|
from .global_admin import SyncGlobalAdminService
|
|
17
17
|
from .options import SyncOptionsService
|
|
18
18
|
from .system import SyncSystemService
|
|
19
|
+
from .user_lookup import SyncUserLookupService
|
|
19
20
|
from .users import SyncUsersService
|
|
20
21
|
|
|
21
22
|
__all__ = [
|
|
@@ -34,5 +35,6 @@ __all__ = [
|
|
|
34
35
|
"SyncGlobalAdminService",
|
|
35
36
|
"SyncOptionsService",
|
|
36
37
|
"SyncSystemService",
|
|
38
|
+
"SyncUserLookupService",
|
|
37
39
|
"SyncUsersService",
|
|
38
40
|
]
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# AUTO-GENERATED — do not edit. Run 'uv run duty generate_sync' to regenerate.
|
|
2
|
+
"""Service for cross-company user lookup."""
|
|
3
|
+
|
|
4
|
+
from vclient._sync.services.base import SyncBaseService
|
|
5
|
+
from vclient.endpoints import Endpoints
|
|
6
|
+
from vclient.models import UserLookupResult
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class SyncUserLookupService(SyncBaseService):
|
|
10
|
+
"""Service for looking up users across companies.
|
|
11
|
+
|
|
12
|
+
Discover which companies a person has a user record in by searching
|
|
13
|
+
via email, Discord ID, Google ID, or GitHub ID.
|
|
14
|
+
|
|
15
|
+
Example:
|
|
16
|
+
>>> async with SyncVClient() as client:
|
|
17
|
+
... results = await client.user_lookup.by_email("alice@example.com")
|
|
18
|
+
... for r in results:
|
|
19
|
+
... print(f"{r.company_name}: {r.role}")
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
def by_email(self, email: str) -> list[UserLookupResult]:
|
|
23
|
+
"""Look up a user by email address.
|
|
24
|
+
|
|
25
|
+
Args:
|
|
26
|
+
email: Exact email address to search for.
|
|
27
|
+
|
|
28
|
+
Returns:
|
|
29
|
+
List of companies where a matching user was found. Empty list if no matches.
|
|
30
|
+
"""
|
|
31
|
+
response = self._get(Endpoints.USERS_LOOKUP, params={"email": email})
|
|
32
|
+
return [UserLookupResult.model_validate(item) for item in response.json()]
|
|
33
|
+
|
|
34
|
+
def by_discord_id(self, discord_id: str) -> list[UserLookupResult]:
|
|
35
|
+
"""Look up a user by Discord profile ID.
|
|
36
|
+
|
|
37
|
+
Args:
|
|
38
|
+
discord_id: Discord profile ID to search for.
|
|
39
|
+
|
|
40
|
+
Returns:
|
|
41
|
+
List of companies where a matching user was found. Empty list if no matches.
|
|
42
|
+
"""
|
|
43
|
+
response = self._get(Endpoints.USERS_LOOKUP, params={"discord_id": discord_id})
|
|
44
|
+
return [UserLookupResult.model_validate(item) for item in response.json()]
|
|
45
|
+
|
|
46
|
+
def by_google_id(self, google_id: str) -> list[UserLookupResult]:
|
|
47
|
+
"""Look up a user by Google profile ID.
|
|
48
|
+
|
|
49
|
+
Args:
|
|
50
|
+
google_id: Google profile ID to search for.
|
|
51
|
+
|
|
52
|
+
Returns:
|
|
53
|
+
List of companies where a matching user was found. Empty list if no matches.
|
|
54
|
+
"""
|
|
55
|
+
response = self._get(Endpoints.USERS_LOOKUP, params={"google_id": google_id})
|
|
56
|
+
return [UserLookupResult.model_validate(item) for item in response.json()]
|
|
57
|
+
|
|
58
|
+
def by_github_id(self, github_id: str) -> list[UserLookupResult]:
|
|
59
|
+
"""Look up a user by GitHub profile ID.
|
|
60
|
+
|
|
61
|
+
Args:
|
|
62
|
+
github_id: GitHub profile ID to search for.
|
|
63
|
+
|
|
64
|
+
Returns:
|
|
65
|
+
List of companies where a matching user was found. Empty list if no matches.
|
|
66
|
+
"""
|
|
67
|
+
response = self._get(Endpoints.USERS_LOOKUP, params={"github_id": github_id})
|
|
68
|
+
return [UserLookupResult.model_validate(item) for item in response.json()]
|
|
@@ -36,6 +36,7 @@ if TYPE_CHECKING:
|
|
|
36
36
|
GlobalAdminService,
|
|
37
37
|
OptionsService,
|
|
38
38
|
SystemService,
|
|
39
|
+
UserLookupService,
|
|
39
40
|
UsersService,
|
|
40
41
|
)
|
|
41
42
|
|
|
@@ -150,6 +151,7 @@ class VClient:
|
|
|
150
151
|
self._developer: DeveloperService | None = None
|
|
151
152
|
self._global_admin: GlobalAdminService | None = None
|
|
152
153
|
self._system: SystemService | None = None
|
|
154
|
+
self._user_lookup: UserLookupService | None = None
|
|
153
155
|
|
|
154
156
|
if set_as_default:
|
|
155
157
|
from vclient.registry import configure_default_client
|
|
@@ -290,6 +292,19 @@ class VClient:
|
|
|
290
292
|
self._system = SystemService(self)
|
|
291
293
|
return self._system
|
|
292
294
|
|
|
295
|
+
@property
|
|
296
|
+
def user_lookup(self) -> "UserLookupService":
|
|
297
|
+
"""Access the User Lookup service for cross-company user discovery.
|
|
298
|
+
|
|
299
|
+
Returns:
|
|
300
|
+
The UserLookupService instance for user lookup operations.
|
|
301
|
+
"""
|
|
302
|
+
if self._user_lookup is None:
|
|
303
|
+
from vclient.services.user_lookup import UserLookupService
|
|
304
|
+
|
|
305
|
+
self._user_lookup = UserLookupService(self)
|
|
306
|
+
return self._user_lookup
|
|
307
|
+
|
|
293
308
|
def users(self, company_id: str | None = None) -> "UsersService":
|
|
294
309
|
"""Get a UsersService scoped to a specific company.
|
|
295
310
|
|
|
@@ -19,6 +19,9 @@ class Endpoints:
|
|
|
19
19
|
# System endpoints
|
|
20
20
|
HEALTH = f"{_BASE}/health"
|
|
21
21
|
|
|
22
|
+
# User lookup (cross-company, not scoped)
|
|
23
|
+
USERS_LOOKUP = f"{_BASE}/users/lookup"
|
|
24
|
+
|
|
22
25
|
# Global Admin endpoints
|
|
23
26
|
ADMIN_DEVELOPERS = f"{_BASE}/admin/developers"
|
|
24
27
|
ADMIN_DEVELOPER = f"{_BASE}/admin/developers/{{developer_id}}"
|
{valentina_python_client-1.20.1 → valentina_python_client-1.21.0}/src/vclient/models/__init__.py
RENAMED
|
@@ -115,6 +115,9 @@ from .shared import (
|
|
|
115
115
|
Trait,
|
|
116
116
|
)
|
|
117
117
|
from .system import SystemHealth
|
|
118
|
+
from .user_lookup import (
|
|
119
|
+
UserLookupResult,
|
|
120
|
+
)
|
|
118
121
|
from .users import (
|
|
119
122
|
CampaignExperience,
|
|
120
123
|
DiscordProfile,
|
|
@@ -221,6 +224,7 @@ __all__ = [
|
|
|
221
224
|
"UserCreate",
|
|
222
225
|
"UserDenyDTO",
|
|
223
226
|
"UserDetail",
|
|
227
|
+
"UserLookupResult",
|
|
224
228
|
"UserMergeDTO",
|
|
225
229
|
"UserRegisterDTO",
|
|
226
230
|
"UserUpdate",
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"""Pydantic models for User Lookup API responses."""
|
|
2
|
+
|
|
3
|
+
from pydantic import BaseModel
|
|
4
|
+
|
|
5
|
+
from vclient.constants import UserRole
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class UserLookupResult(BaseModel):
|
|
9
|
+
"""A single result from a cross-company user lookup.
|
|
10
|
+
|
|
11
|
+
Each result represents a company where the looked-up person has a user record.
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
company_id: str
|
|
15
|
+
company_name: str
|
|
16
|
+
user_id: str
|
|
17
|
+
role: UserRole
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
__all__ = [
|
|
21
|
+
"UserLookupResult",
|
|
22
|
+
]
|
|
@@ -37,6 +37,7 @@ if TYPE_CHECKING:
|
|
|
37
37
|
GlobalAdminService,
|
|
38
38
|
OptionsService,
|
|
39
39
|
SystemService,
|
|
40
|
+
UserLookupService,
|
|
40
41
|
UsersService,
|
|
41
42
|
)
|
|
42
43
|
|
|
@@ -189,6 +190,29 @@ def system_service() -> "SystemService":
|
|
|
189
190
|
return SystemService(default_client())
|
|
190
191
|
|
|
191
192
|
|
|
193
|
+
def user_lookup_service() -> "UserLookupService":
|
|
194
|
+
"""Create a UserLookupService using the default client.
|
|
195
|
+
|
|
196
|
+
Discover which companies a person has a user record in by searching
|
|
197
|
+
via email, Discord ID, Google ID, or GitHub ID.
|
|
198
|
+
|
|
199
|
+
Returns:
|
|
200
|
+
UserLookupService: A service instance for cross-company user lookup.
|
|
201
|
+
|
|
202
|
+
Raises:
|
|
203
|
+
RuntimeError: If no default client has been configured.
|
|
204
|
+
|
|
205
|
+
Example:
|
|
206
|
+
```python
|
|
207
|
+
lookup = user_lookup_service()
|
|
208
|
+
results = await lookup.by_email("alice@example.com")
|
|
209
|
+
```
|
|
210
|
+
"""
|
|
211
|
+
from vclient.services.user_lookup import UserLookupService
|
|
212
|
+
|
|
213
|
+
return UserLookupService(default_client())
|
|
214
|
+
|
|
215
|
+
|
|
192
216
|
def users_service(company_id: str | None = None) -> "UsersService":
|
|
193
217
|
"""Create a UsersService scoped to a specific company using the default client.
|
|
194
218
|
|
{valentina_python_client-1.20.1 → valentina_python_client-1.21.0}/src/vclient/services/__init__.py
RENAMED
|
@@ -15,6 +15,7 @@ from .dictionary import DictionaryService
|
|
|
15
15
|
from .global_admin import GlobalAdminService
|
|
16
16
|
from .options import OptionsService
|
|
17
17
|
from .system import SystemService
|
|
18
|
+
from .user_lookup import UserLookupService
|
|
18
19
|
from .users import UsersService
|
|
19
20
|
|
|
20
21
|
__all__ = [
|
|
@@ -33,5 +34,6 @@ __all__ = [
|
|
|
33
34
|
"GlobalAdminService",
|
|
34
35
|
"OptionsService",
|
|
35
36
|
"SystemService",
|
|
37
|
+
"UserLookupService",
|
|
36
38
|
"UsersService",
|
|
37
39
|
]
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"""Service for cross-company user lookup."""
|
|
2
|
+
|
|
3
|
+
from vclient.endpoints import Endpoints
|
|
4
|
+
from vclient.models import UserLookupResult
|
|
5
|
+
from vclient.services.base import BaseService
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class UserLookupService(BaseService):
|
|
9
|
+
"""Service for looking up users across companies.
|
|
10
|
+
|
|
11
|
+
Discover which companies a person has a user record in by searching
|
|
12
|
+
via email, Discord ID, Google ID, or GitHub ID.
|
|
13
|
+
|
|
14
|
+
Example:
|
|
15
|
+
>>> async with VClient() as client:
|
|
16
|
+
... results = await client.user_lookup.by_email("alice@example.com")
|
|
17
|
+
... for r in results:
|
|
18
|
+
... print(f"{r.company_name}: {r.role}")
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
async def by_email(self, email: str) -> list[UserLookupResult]:
|
|
22
|
+
"""Look up a user by email address.
|
|
23
|
+
|
|
24
|
+
Args:
|
|
25
|
+
email: Exact email address to search for.
|
|
26
|
+
|
|
27
|
+
Returns:
|
|
28
|
+
List of companies where a matching user was found. Empty list if no matches.
|
|
29
|
+
"""
|
|
30
|
+
response = await self._get(Endpoints.USERS_LOOKUP, params={"email": email})
|
|
31
|
+
return [UserLookupResult.model_validate(item) for item in response.json()]
|
|
32
|
+
|
|
33
|
+
async def by_discord_id(self, discord_id: str) -> list[UserLookupResult]:
|
|
34
|
+
"""Look up a user by Discord profile ID.
|
|
35
|
+
|
|
36
|
+
Args:
|
|
37
|
+
discord_id: Discord profile ID to search for.
|
|
38
|
+
|
|
39
|
+
Returns:
|
|
40
|
+
List of companies where a matching user was found. Empty list if no matches.
|
|
41
|
+
"""
|
|
42
|
+
response = await self._get(Endpoints.USERS_LOOKUP, params={"discord_id": discord_id})
|
|
43
|
+
return [UserLookupResult.model_validate(item) for item in response.json()]
|
|
44
|
+
|
|
45
|
+
async def by_google_id(self, google_id: str) -> list[UserLookupResult]:
|
|
46
|
+
"""Look up a user by Google profile ID.
|
|
47
|
+
|
|
48
|
+
Args:
|
|
49
|
+
google_id: Google profile ID to search for.
|
|
50
|
+
|
|
51
|
+
Returns:
|
|
52
|
+
List of companies where a matching user was found. Empty list if no matches.
|
|
53
|
+
"""
|
|
54
|
+
response = await self._get(Endpoints.USERS_LOOKUP, params={"google_id": google_id})
|
|
55
|
+
return [UserLookupResult.model_validate(item) for item in response.json()]
|
|
56
|
+
|
|
57
|
+
async def by_github_id(self, github_id: str) -> list[UserLookupResult]:
|
|
58
|
+
"""Look up a user by GitHub profile ID.
|
|
59
|
+
|
|
60
|
+
Args:
|
|
61
|
+
github_id: GitHub profile ID to search for.
|
|
62
|
+
|
|
63
|
+
Returns:
|
|
64
|
+
List of companies where a matching user was found. Empty list if no matches.
|
|
65
|
+
"""
|
|
66
|
+
response = await self._get(Endpoints.USERS_LOOKUP, params={"github_id": github_id})
|
|
67
|
+
return [UserLookupResult.model_validate(item) for item in response.json()]
|
{valentina_python_client-1.20.1 → valentina_python_client-1.21.0}/src/vclient/testing/__init__.py
RENAMED
|
@@ -57,6 +57,7 @@ from vclient.testing._factories import (
|
|
|
57
57
|
TraitSubcategoryFactory,
|
|
58
58
|
UserDetailFactory,
|
|
59
59
|
UserFactory,
|
|
60
|
+
UserLookupResultFactory,
|
|
60
61
|
VampireClanFactory,
|
|
61
62
|
WerewolfAuspiceFactory,
|
|
62
63
|
WerewolfTribeFactory,
|
|
@@ -110,6 +111,7 @@ __all__ = [
|
|
|
110
111
|
"TraitSubcategoryFactory",
|
|
111
112
|
"UserDetailFactory",
|
|
112
113
|
"UserFactory",
|
|
114
|
+
"UserLookupResultFactory",
|
|
113
115
|
"VampireClanFactory",
|
|
114
116
|
"WerewolfAuspiceFactory",
|
|
115
117
|
"WerewolfTribeFactory",
|
{valentina_python_client-1.20.1 → valentina_python_client-1.21.0}/src/vclient/testing/_factories.py
RENAMED
|
@@ -43,6 +43,7 @@ from vclient.models import (
|
|
|
43
43
|
TraitSubcategory,
|
|
44
44
|
User,
|
|
45
45
|
UserDetail,
|
|
46
|
+
UserLookupResult,
|
|
46
47
|
VampireClan,
|
|
47
48
|
WerewolfAuspice,
|
|
48
49
|
WerewolfTribe,
|
|
@@ -259,6 +260,12 @@ class UserFactory(ModelFactory[User]):
|
|
|
259
260
|
role = "PLAYER"
|
|
260
261
|
|
|
261
262
|
|
|
263
|
+
class UserLookupResultFactory(ModelFactory[UserLookupResult]):
|
|
264
|
+
__model__ = UserLookupResult
|
|
265
|
+
__use_defaults__ = True
|
|
266
|
+
role = "PLAYER"
|
|
267
|
+
|
|
268
|
+
|
|
262
269
|
class UserDetailFactory(ModelFactory[UserDetail]):
|
|
263
270
|
__model__ = UserDetail
|
|
264
271
|
__use_defaults__ = True
|
|
@@ -323,6 +330,7 @@ __all__ = [
|
|
|
323
330
|
"TraitSubcategoryFactory",
|
|
324
331
|
"UserDetailFactory",
|
|
325
332
|
"UserFactory",
|
|
333
|
+
"UserLookupResultFactory",
|
|
326
334
|
"VampireClanFactory",
|
|
327
335
|
"WerewolfAuspiceFactory",
|
|
328
336
|
"WerewolfTribeFactory",
|
{valentina_python_client-1.20.1 → valentina_python_client-1.21.0}/src/vclient/testing/_router.py
RENAMED
|
@@ -48,6 +48,7 @@ from vclient.models import (
|
|
|
48
48
|
TraitSubcategory,
|
|
49
49
|
User,
|
|
50
50
|
UserDetail,
|
|
51
|
+
UserLookupResult,
|
|
51
52
|
VampireClan,
|
|
52
53
|
WerewolfAuspice,
|
|
53
54
|
WerewolfTribe,
|
|
@@ -91,6 +92,7 @@ from vclient.testing._factories import (
|
|
|
91
92
|
TraitSubcategoryFactory,
|
|
92
93
|
UserDetailFactory,
|
|
93
94
|
UserFactory,
|
|
95
|
+
UserLookupResultFactory,
|
|
94
96
|
VampireClanFactory,
|
|
95
97
|
WerewolfAuspiceFactory,
|
|
96
98
|
WerewolfTribeFactory,
|
|
@@ -133,6 +135,7 @@ _FACTORY_MAP: dict[type, type[ModelFactory]] = {
|
|
|
133
135
|
TraitCategory: TraitCategoryFactory,
|
|
134
136
|
TraitSubcategory: TraitSubcategoryFactory,
|
|
135
137
|
User: UserFactory,
|
|
138
|
+
UserLookupResult: UserLookupResultFactory,
|
|
136
139
|
UserDetail: UserDetailFactory,
|
|
137
140
|
VampireClan: VampireClanFactory,
|
|
138
141
|
WerewolfAuspice: WerewolfAuspiceFactory,
|
{valentina_python_client-1.20.1 → valentina_python_client-1.21.0}/src/vclient/testing/_routes.py
RENAMED
|
@@ -40,6 +40,7 @@ from vclient.models import (
|
|
|
40
40
|
TraitSubcategory,
|
|
41
41
|
User,
|
|
42
42
|
UserDetail,
|
|
43
|
+
UserLookupResult,
|
|
43
44
|
VampireClan,
|
|
44
45
|
WerewolfAuspice,
|
|
45
46
|
WerewolfTribe,
|
|
@@ -131,6 +132,8 @@ class Routes:
|
|
|
131
132
|
USERS_REGISTER = RouteSpec("POST", Endpoints.USER_REGISTER, SINGLE, User)
|
|
132
133
|
USERS_MERGE = RouteSpec("POST", Endpoints.USER_MERGE, SINGLE, User)
|
|
133
134
|
USERS_STATISTICS = RouteSpec("GET", Endpoints.USER_STATISTICS, SINGLE, RollStatistics)
|
|
135
|
+
# User lookup (cross-company)
|
|
136
|
+
USERS_LOOKUP = RouteSpec("GET", Endpoints.USERS_LOOKUP, LIST, UserLookupResult)
|
|
134
137
|
|
|
135
138
|
# User assets
|
|
136
139
|
USERS_ASSETS_LIST = RouteSpec("GET", Endpoints.USER_ASSETS, PAGINATED, Asset)
|
|
File without changes
|
|
File without changes
|
{valentina_python_client-1.20.1 → valentina_python_client-1.21.0}/src/vclient/_sync/services/base.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{valentina_python_client-1.20.1 → valentina_python_client-1.21.0}/src/vclient/models/books.py
RENAMED
|
File without changes
|
{valentina_python_client-1.20.1 → valentina_python_client-1.21.0}/src/vclient/models/campaigns.py
RENAMED
|
File without changes
|
{valentina_python_client-1.20.1 → valentina_python_client-1.21.0}/src/vclient/models/chapters.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{valentina_python_client-1.20.1 → valentina_python_client-1.21.0}/src/vclient/models/characters.py
RENAMED
|
File without changes
|
{valentina_python_client-1.20.1 → valentina_python_client-1.21.0}/src/vclient/models/companies.py
RENAMED
|
File without changes
|
{valentina_python_client-1.20.1 → valentina_python_client-1.21.0}/src/vclient/models/developers.py
RENAMED
|
File without changes
|
{valentina_python_client-1.20.1 → valentina_python_client-1.21.0}/src/vclient/models/diceroll.py
RENAMED
|
File without changes
|
{valentina_python_client-1.20.1 → valentina_python_client-1.21.0}/src/vclient/models/dictionary.py
RENAMED
|
File without changes
|
{valentina_python_client-1.20.1 → valentina_python_client-1.21.0}/src/vclient/models/full_sheet.py
RENAMED
|
File without changes
|
{valentina_python_client-1.20.1 → valentina_python_client-1.21.0}/src/vclient/models/global_admin.py
RENAMED
|
File without changes
|
{valentina_python_client-1.20.1 → valentina_python_client-1.21.0}/src/vclient/models/pagination.py
RENAMED
|
File without changes
|
{valentina_python_client-1.20.1 → valentina_python_client-1.21.0}/src/vclient/models/shared.py
RENAMED
|
File without changes
|
{valentina_python_client-1.20.1 → valentina_python_client-1.21.0}/src/vclient/models/system.py
RENAMED
|
File without changes
|
{valentina_python_client-1.20.1 → valentina_python_client-1.21.0}/src/vclient/models/users.py
RENAMED
|
File without changes
|
|
File without changes
|
{valentina_python_client-1.20.1 → valentina_python_client-1.21.0}/src/vclient/services/base.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{valentina_python_client-1.20.1 → valentina_python_client-1.21.0}/src/vclient/services/campaigns.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{valentina_python_client-1.20.1 → valentina_python_client-1.21.0}/src/vclient/services/characters.py
RENAMED
|
File without changes
|
{valentina_python_client-1.20.1 → valentina_python_client-1.21.0}/src/vclient/services/companies.py
RENAMED
|
File without changes
|
{valentina_python_client-1.20.1 → valentina_python_client-1.21.0}/src/vclient/services/developers.py
RENAMED
|
File without changes
|
{valentina_python_client-1.20.1 → valentina_python_client-1.21.0}/src/vclient/services/dicerolls.py
RENAMED
|
File without changes
|
{valentina_python_client-1.20.1 → valentina_python_client-1.21.0}/src/vclient/services/dictionary.py
RENAMED
|
File without changes
|
|
File without changes
|
{valentina_python_client-1.20.1 → valentina_python_client-1.21.0}/src/vclient/services/options.py
RENAMED
|
File without changes
|
{valentina_python_client-1.20.1 → valentina_python_client-1.21.0}/src/vclient/services/system.py
RENAMED
|
File without changes
|
{valentina_python_client-1.20.1 → valentina_python_client-1.21.0}/src/vclient/services/users.py
RENAMED
|
File without changes
|
{valentina_python_client-1.20.1 → valentina_python_client-1.21.0}/src/vclient/testing/_client.py
RENAMED
|
File without changes
|
{valentina_python_client-1.20.1 → valentina_python_client-1.21.0}/src/vclient/validate_constants.py
RENAMED
|
File without changes
|