valentina-python-client 3.0.0__tar.gz → 3.2.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.
Files changed (84) hide show
  1. {valentina_python_client-3.0.0 → valentina_python_client-3.2.0}/PKG-INFO +3 -3
  2. {valentina_python_client-3.0.0 → valentina_python_client-3.2.0}/pyproject.toml +11 -11
  3. {valentina_python_client-3.0.0 → valentina_python_client-3.2.0}/src/vclient/__init__.py +1 -1
  4. {valentina_python_client-3.0.0 → valentina_python_client-3.2.0}/src/vclient/_sync/services/campaign_book_chapters.py +2 -2
  5. {valentina_python_client-3.0.0 → valentina_python_client-3.2.0}/src/vclient/_sync/services/character_traits.py +7 -3
  6. {valentina_python_client-3.0.0 → valentina_python_client-3.2.0}/src/vclient/models/__init__.py +0 -2
  7. {valentina_python_client-3.0.0 → valentina_python_client-3.2.0}/src/vclient/models/books.py +4 -0
  8. {valentina_python_client-3.0.0 → valentina_python_client-3.2.0}/src/vclient/models/chapters.py +11 -0
  9. {valentina_python_client-3.0.0 → valentina_python_client-3.2.0}/src/vclient/models/character_trait.py +5 -4
  10. {valentina_python_client-3.0.0 → valentina_python_client-3.2.0}/src/vclient/models/characters.py +4 -0
  11. {valentina_python_client-3.0.0 → valentina_python_client-3.2.0}/src/vclient/models/users.py +4 -28
  12. {valentina_python_client-3.0.0 → valentina_python_client-3.2.0}/src/vclient/services/campaign_book_chapters.py +2 -2
  13. {valentina_python_client-3.0.0 → valentina_python_client-3.2.0}/src/vclient/services/character_traits.py +7 -3
  14. {valentina_python_client-3.0.0 → valentina_python_client-3.2.0}/LICENSE +0 -0
  15. {valentina_python_client-3.0.0 → valentina_python_client-3.2.0}/README.md +0 -0
  16. {valentina_python_client-3.0.0 → valentina_python_client-3.2.0}/src/vclient/_codegen.py +0 -0
  17. {valentina_python_client-3.0.0 → valentina_python_client-3.2.0}/src/vclient/_sync/__init__.py +0 -0
  18. {valentina_python_client-3.0.0 → valentina_python_client-3.2.0}/src/vclient/_sync/client.py +0 -0
  19. {valentina_python_client-3.0.0 → valentina_python_client-3.2.0}/src/vclient/_sync/registry.py +0 -0
  20. {valentina_python_client-3.0.0 → valentina_python_client-3.2.0}/src/vclient/_sync/services/__init__.py +0 -0
  21. {valentina_python_client-3.0.0 → valentina_python_client-3.2.0}/src/vclient/_sync/services/_audit_params.py +0 -0
  22. {valentina_python_client-3.0.0 → valentina_python_client-3.2.0}/src/vclient/_sync/services/base.py +0 -0
  23. {valentina_python_client-3.0.0 → valentina_python_client-3.2.0}/src/vclient/_sync/services/campaign_books.py +0 -0
  24. {valentina_python_client-3.0.0 → valentina_python_client-3.2.0}/src/vclient/_sync/services/campaigns.py +0 -0
  25. {valentina_python_client-3.0.0 → valentina_python_client-3.2.0}/src/vclient/_sync/services/character_autogen.py +0 -0
  26. {valentina_python_client-3.0.0 → valentina_python_client-3.2.0}/src/vclient/_sync/services/character_blueprint.py +0 -0
  27. {valentina_python_client-3.0.0 → valentina_python_client-3.2.0}/src/vclient/_sync/services/characters.py +0 -0
  28. {valentina_python_client-3.0.0 → valentina_python_client-3.2.0}/src/vclient/_sync/services/companies.py +0 -0
  29. {valentina_python_client-3.0.0 → valentina_python_client-3.2.0}/src/vclient/_sync/services/developers.py +0 -0
  30. {valentina_python_client-3.0.0 → valentina_python_client-3.2.0}/src/vclient/_sync/services/dicerolls.py +0 -0
  31. {valentina_python_client-3.0.0 → valentina_python_client-3.2.0}/src/vclient/_sync/services/dictionary.py +0 -0
  32. {valentina_python_client-3.0.0 → valentina_python_client-3.2.0}/src/vclient/_sync/services/global_admin.py +0 -0
  33. {valentina_python_client-3.0.0 → valentina_python_client-3.2.0}/src/vclient/_sync/services/identity.py +0 -0
  34. {valentina_python_client-3.0.0 → valentina_python_client-3.2.0}/src/vclient/_sync/services/options.py +0 -0
  35. {valentina_python_client-3.0.0 → valentina_python_client-3.2.0}/src/vclient/_sync/services/system.py +0 -0
  36. {valentina_python_client-3.0.0 → valentina_python_client-3.2.0}/src/vclient/_sync/services/user_lookup.py +0 -0
  37. {valentina_python_client-3.0.0 → valentina_python_client-3.2.0}/src/vclient/_sync/services/users.py +0 -0
  38. {valentina_python_client-3.0.0 → valentina_python_client-3.2.0}/src/vclient/_sync/testing/__init__.py +0 -0
  39. {valentina_python_client-3.0.0 → valentina_python_client-3.2.0}/src/vclient/_sync/testing/_client.py +0 -0
  40. {valentina_python_client-3.0.0 → valentina_python_client-3.2.0}/src/vclient/client.py +0 -0
  41. {valentina_python_client-3.0.0 → valentina_python_client-3.2.0}/src/vclient/config.py +0 -0
  42. {valentina_python_client-3.0.0 → valentina_python_client-3.2.0}/src/vclient/constants.py +0 -0
  43. {valentina_python_client-3.0.0 → valentina_python_client-3.2.0}/src/vclient/endpoints.py +0 -0
  44. {valentina_python_client-3.0.0 → valentina_python_client-3.2.0}/src/vclient/exceptions.py +0 -0
  45. {valentina_python_client-3.0.0 → valentina_python_client-3.2.0}/src/vclient/models/audit_logs.py +0 -0
  46. {valentina_python_client-3.0.0 → valentina_python_client-3.2.0}/src/vclient/models/campaigns.py +0 -0
  47. {valentina_python_client-3.0.0 → valentina_python_client-3.2.0}/src/vclient/models/character_autogen.py +0 -0
  48. {valentina_python_client-3.0.0 → valentina_python_client-3.2.0}/src/vclient/models/character_blueprint.py +0 -0
  49. {valentina_python_client-3.0.0 → valentina_python_client-3.2.0}/src/vclient/models/companies.py +0 -0
  50. {valentina_python_client-3.0.0 → valentina_python_client-3.2.0}/src/vclient/models/developers.py +0 -0
  51. {valentina_python_client-3.0.0 → valentina_python_client-3.2.0}/src/vclient/models/diceroll.py +0 -0
  52. {valentina_python_client-3.0.0 → valentina_python_client-3.2.0}/src/vclient/models/dictionary.py +0 -0
  53. {valentina_python_client-3.0.0 → valentina_python_client-3.2.0}/src/vclient/models/full_sheet.py +0 -0
  54. {valentina_python_client-3.0.0 → valentina_python_client-3.2.0}/src/vclient/models/global_admin.py +0 -0
  55. {valentina_python_client-3.0.0 → valentina_python_client-3.2.0}/src/vclient/models/pagination.py +0 -0
  56. {valentina_python_client-3.0.0 → valentina_python_client-3.2.0}/src/vclient/models/shared.py +0 -0
  57. {valentina_python_client-3.0.0 → valentina_python_client-3.2.0}/src/vclient/models/system.py +0 -0
  58. {valentina_python_client-3.0.0 → valentina_python_client-3.2.0}/src/vclient/models/user_lookup.py +0 -0
  59. {valentina_python_client-3.0.0 → valentina_python_client-3.2.0}/src/vclient/py.typed +0 -0
  60. {valentina_python_client-3.0.0 → valentina_python_client-3.2.0}/src/vclient/registry.py +0 -0
  61. {valentina_python_client-3.0.0 → valentina_python_client-3.2.0}/src/vclient/services/__init__.py +0 -0
  62. {valentina_python_client-3.0.0 → valentina_python_client-3.2.0}/src/vclient/services/_audit_params.py +0 -0
  63. {valentina_python_client-3.0.0 → valentina_python_client-3.2.0}/src/vclient/services/base.py +0 -0
  64. {valentina_python_client-3.0.0 → valentina_python_client-3.2.0}/src/vclient/services/campaign_books.py +0 -0
  65. {valentina_python_client-3.0.0 → valentina_python_client-3.2.0}/src/vclient/services/campaigns.py +0 -0
  66. {valentina_python_client-3.0.0 → valentina_python_client-3.2.0}/src/vclient/services/character_autogen.py +0 -0
  67. {valentina_python_client-3.0.0 → valentina_python_client-3.2.0}/src/vclient/services/character_blueprint.py +0 -0
  68. {valentina_python_client-3.0.0 → valentina_python_client-3.2.0}/src/vclient/services/characters.py +0 -0
  69. {valentina_python_client-3.0.0 → valentina_python_client-3.2.0}/src/vclient/services/companies.py +0 -0
  70. {valentina_python_client-3.0.0 → valentina_python_client-3.2.0}/src/vclient/services/developers.py +0 -0
  71. {valentina_python_client-3.0.0 → valentina_python_client-3.2.0}/src/vclient/services/dicerolls.py +0 -0
  72. {valentina_python_client-3.0.0 → valentina_python_client-3.2.0}/src/vclient/services/dictionary.py +0 -0
  73. {valentina_python_client-3.0.0 → valentina_python_client-3.2.0}/src/vclient/services/global_admin.py +0 -0
  74. {valentina_python_client-3.0.0 → valentina_python_client-3.2.0}/src/vclient/services/identity.py +0 -0
  75. {valentina_python_client-3.0.0 → valentina_python_client-3.2.0}/src/vclient/services/options.py +0 -0
  76. {valentina_python_client-3.0.0 → valentina_python_client-3.2.0}/src/vclient/services/system.py +0 -0
  77. {valentina_python_client-3.0.0 → valentina_python_client-3.2.0}/src/vclient/services/user_lookup.py +0 -0
  78. {valentina_python_client-3.0.0 → valentina_python_client-3.2.0}/src/vclient/services/users.py +0 -0
  79. {valentina_python_client-3.0.0 → valentina_python_client-3.2.0}/src/vclient/testing/__init__.py +0 -0
  80. {valentina_python_client-3.0.0 → valentina_python_client-3.2.0}/src/vclient/testing/_client.py +0 -0
  81. {valentina_python_client-3.0.0 → valentina_python_client-3.2.0}/src/vclient/testing/_factories.py +0 -0
  82. {valentina_python_client-3.0.0 → valentina_python_client-3.2.0}/src/vclient/testing/_router.py +0 -0
  83. {valentina_python_client-3.0.0 → valentina_python_client-3.2.0}/src/vclient/testing/_routes.py +0 -0
  84. {valentina_python_client-3.0.0 → valentina_python_client-3.2.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: 3.0.0
3
+ Version: 3.2.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>
@@ -15,8 +15,8 @@ License: MIT License
15
15
  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
16
16
  Classifier: Programming Language :: Python :: 3.13
17
17
  Classifier: Programming Language :: Python :: 3.14
18
- Requires-Dist: anyio>=4.13.0,<5.0.0
19
- Requires-Dist: httpx2>=2.4.0
18
+ Requires-Dist: anyio>=4.14.1,<5.0.0
19
+ Requires-Dist: httpx2>=2.5.0
20
20
  Requires-Dist: loguru>=0.7.3
21
21
  Requires-Dist: polyfactory>=3.3.0,<4.0.0
22
22
  Requires-Dist: pydantic[email]>=2.13.4,<3.0.0
@@ -5,8 +5,8 @@
5
5
  "Programming Language :: Python :: 3.14",
6
6
  ]
7
7
  dependencies = [
8
- "anyio>=4.13.0, <5.0.0",
9
- "httpx2>=2.4.0",
8
+ "anyio>=4.14.1,<5.0.0",
9
+ "httpx2>=2.5.0",
10
10
  "loguru>=0.7.3",
11
11
  "polyfactory>=3.3.0, <4.0.0",
12
12
  "pydantic[email]>=2.13.4, <3.0.0",
@@ -16,7 +16,7 @@
16
16
  name = "valentina-python-client"
17
17
  readme = "README.md"
18
18
  requires-python = ">=3.13"
19
- version = "3.0.0"
19
+ version = "3.2.0"
20
20
 
21
21
  [project.optional-dependencies]
22
22
  testing = ["polyfactory>=3.3.0"]
@@ -34,11 +34,11 @@
34
34
 
35
35
  [dependency-groups]
36
36
  dev = [
37
- "commitizen>=4.16.3",
38
- "coverage>=7.14.1",
37
+ "commitizen>=4.16.4",
38
+ "coverage>=7.15.0",
39
39
  "duty>=1.9.0",
40
40
  "httpx>=0.28.1",
41
- "prek>=0.4.4",
41
+ "prek>=0.4.8",
42
42
  "pytest-anyio>=0.0.0",
43
43
  "pytest-clarity>=1.0.1",
44
44
  "pytest-cov>=7.1.0",
@@ -48,16 +48,16 @@
48
48
  "pytest-repeat>=0.9.4",
49
49
  "pytest-sugar>=1.1.1",
50
50
  "pytest-xdist>=3.8.0",
51
- "pytest>=9.1.0",
51
+ "pytest>=9.1.1",
52
52
  "respx>=0.23.1",
53
- "ruff>=0.15.17",
53
+ "ruff>=0.15.20",
54
54
  "shellcheck-py>=0.11.0.1",
55
- "ty>=0.0.49",
56
- "typos>=1.47.2",
55
+ "ty>=0.0.56",
56
+ "typos>=1.48.0",
57
57
  "vulture>=2.16",
58
58
  "yamllint>=1.38.0",
59
59
  ]
60
- docs = ["zensical>=0.0.45"]
60
+ docs = ["zensical>=0.0.47"]
61
61
 
62
62
  [tool.commitizen]
63
63
  bump_message = "bump(release): v$current_version → v$new_version"
@@ -116,4 +116,4 @@ __all__ = (
116
116
  "users_service",
117
117
  )
118
118
 
119
- __version__ = "3.0.0"
119
+ __version__ = "3.2.0"
@@ -114,7 +114,7 @@ class SyncChaptersService(SyncBaseService):
114
114
  Args:
115
115
  request: A ChapterCreate model, OR pass fields as keyword arguments.
116
116
  **kwargs: Fields for ChapterCreate if request is not provided.
117
- Accepts: name (str, required), description (str | None).
117
+ Accepts: name (str, required), description (str | None), character_ids (list[str] | None).
118
118
  """
119
119
  body = request if request is not None else ChapterCreate(**kwargs)
120
120
  response = self._post(
@@ -132,7 +132,7 @@ class SyncChaptersService(SyncBaseService):
132
132
  chapter_id: The ID of the chapter to update.
133
133
  request: A ChapterUpdate model, OR pass fields as keyword arguments.
134
134
  **kwargs: Fields for ChapterUpdate if request is not provided.
135
- Accepts: name (str | None), description (str | None).
135
+ Accepts: name (str | None), description (str | None), character_ids (list[str] | None).
136
136
  """
137
137
  body = request if request is not None else ChapterUpdate(**kwargs)
138
138
  response = self._patch(
@@ -211,15 +211,19 @@ class SyncCharacterTraitsService(SyncBaseService):
211
211
  return BulkAssignTraitResponse.model_validate(response.json())
212
212
 
213
213
  def create(self, request: TraitCreate | None = None, **kwargs) -> CharacterTrait:
214
- """Create a new character trait.
214
+ """Create a new custom character trait.
215
+
216
+ The trait is always created at a value of ``1``; the supplied ``currency`` pays
217
+ for that first dot. ``NPC`` and ``STORYTELLER`` characters accept only
218
+ ``"NO_COST"``.
215
219
 
216
220
  Args:
217
221
  request: A TraitCreate model, OR pass fields as keyword arguments.
218
222
  **kwargs: Fields for TraitCreate if request is not provided.
219
- Required: name (str), category_id (str).
223
+ Required: name (str), category_id (str), currency (TraitModifyCurrency).
220
224
  Optional: description (str | None), max_value (int), min_value (int),
221
225
  show_when_zero (bool), initial_cost (int | None),
222
- upgrade_cost (int | None), value (int | None).
226
+ upgrade_cost (int | None).
223
227
  """
224
228
  body = request if request is not None else self._validate_request(TraitCreate, **kwargs)
225
229
  response = self._post(
@@ -134,7 +134,6 @@ from .users import (
134
134
  AppleProfile,
135
135
  CampaignExperience,
136
136
  DiscordProfile,
137
- DiscordProfileUpdate,
138
137
  GitHubProfile,
139
138
  GoogleProfile,
140
139
  IdentityResolution,
@@ -207,7 +206,6 @@ __all__ = [
207
206
  "DictionaryTermCreate",
208
207
  "DictionaryTermUpdate",
209
208
  "DiscordProfile",
210
- "DiscordProfileUpdate",
211
209
  "FullSheetTraitCategory",
212
210
  "FullSheetTraitSection",
213
211
  "FullSheetTraitSubcategory",
@@ -20,6 +20,10 @@ class CampaignBook(BaseModel):
20
20
  name: str = Field(..., description="Book name (3-50 characters).")
21
21
  description: str | None = Field(default=None, description="Book description.")
22
22
  asset_ids: list[str] = Field(default_factory=list, description="List of associated asset IDs.")
23
+ character_ids: list[str] = Field(
24
+ default_factory=list,
25
+ description="Read-only union of character IDs across the book's chapters.",
26
+ )
23
27
  number: int = Field(..., description="Book number within the campaign.")
24
28
  campaign_id: str = Field(..., description="ID of the parent campaign.")
25
29
  num_chapters: int = Field(default=0, description="Number of active chapters in the book.")
@@ -21,6 +21,9 @@ class CampaignChapter(BaseModel):
21
21
  name: str = Field(..., description="Chapter name (3-50 characters).")
22
22
  description: str | None = Field(default=None, description="Chapter description.")
23
23
  asset_ids: list[str] = Field(default_factory=list, description="List of associated asset IDs.")
24
+ character_ids: list[str] = Field(
25
+ default_factory=list, description="List of associated character IDs."
26
+ )
24
27
  number: int = Field(..., description="Chapter number within the book.")
25
28
  book_id: str = Field(..., description="ID of the parent book.")
26
29
  num_notes: int = Field(default=0, description="Number of active notes on the chapter.")
@@ -48,6 +51,10 @@ class ChapterCreate(BaseModel):
48
51
 
49
52
  name: str = Field(..., description="Chapter name (3-50 characters).")
50
53
  description: str | None = Field(default=None, description="Chapter description.")
54
+ character_ids: list[str] | None = Field(
55
+ default=None,
56
+ description="Character IDs to associate. Each must be an active character in the same campaign.",
57
+ )
51
58
 
52
59
 
53
60
  class ChapterUpdate(BaseModel):
@@ -55,6 +62,10 @@ class ChapterUpdate(BaseModel):
55
62
 
56
63
  name: str | None = Field(default=None, description="Chapter name (3-50 characters).")
57
64
  description: str | None = Field(default=None, description="Chapter description.")
65
+ character_ids: list[str] | None = Field(
66
+ default=None,
67
+ description="Replacement character ID list. Omit to leave unchanged; send [] to clear.",
68
+ )
58
69
 
59
70
 
60
71
  class _ChapterRenumber(BaseModel):
@@ -34,21 +34,22 @@ class CharacterTraitAdd(BaseModel):
34
34
 
35
35
 
36
36
  class TraitCreate(BaseModel):
37
- """Request model for creating a character trait.
37
+ """Request model for creating a custom character trait.
38
38
 
39
- Used to construct the JSON payload for character trait creation.
39
+ Used to construct the JSON payload for character trait creation. The trait is
40
+ always created at a value of ``1``; the supplied ``currency`` pays for that first dot.
40
41
  """
41
42
 
42
43
  name: str
44
+ category_id: str
45
+ currency: TraitModifyCurrency
43
46
  description: str | None = None
44
47
  max_value: Annotated[int, Field(ge=0, le=100, default=5)] = 5
45
48
  min_value: Annotated[int, Field(ge=0, le=100, default=0)] = 0
46
49
  show_when_zero: bool | None = True
47
- category_id: str
48
50
  initial_cost: int | None = None
49
51
  upgrade_cost: int | None = None
50
52
  count_based_cost_multiplier: int | None = None
51
- value: int | None = None
52
53
 
53
54
 
54
55
  class _TraitModify(BaseModel):
@@ -204,6 +204,10 @@ class Character(BaseModel):
204
204
  character_trait_ids: list[str] = Field(
205
205
  default_factory=list, description="List of character trait IDs."
206
206
  )
207
+ chapter_ids: list[str] = Field(
208
+ default_factory=list,
209
+ description="Read-only IDs of non-archived chapters this character is associated with.",
210
+ )
207
211
  specialties: list[CharacterSpecialty] = Field(
208
212
  default_factory=list, description="List of character specialties."
209
213
  )
@@ -168,22 +168,6 @@ class IdentityResolution(BaseModel):
168
168
  # -----------------------------------------------------------------------------
169
169
 
170
170
 
171
- class DiscordProfileUpdate(BaseModel):
172
- """Request body for creating or updating a user's Discord profile.
173
-
174
- Contains Discord account details for integration with Discord bots.
175
- All fields are optional as not all users have Discord linked.
176
- """
177
-
178
- id: str | None = None
179
- username: str | None = None
180
- global_name: str | None = None
181
- avatar_id: str | None = None
182
- discriminator: str | None = None
183
- email: str | None = None
184
- verified: bool | None = None
185
-
186
-
187
171
  class UserMergeDTO(BaseModel):
188
172
  """Merge an UNAPPROVED user into an existing primary user."""
189
173
 
@@ -244,15 +228,11 @@ class AdminUserCreate(UserCreate):
244
228
  the target company. The server rejects ``UNAPPROVED``/``DEACTIVATED`` roles
245
229
  on create, so no client-side role restriction is applied here.
246
230
 
247
- Unlike the tenant-scoped surface, the global-admin endpoints still accept
248
- provider profile writes, so the four profile fields are declared here.
231
+ Provider-identity profiles cannot be written here; associate a verified
232
+ provider identity through the ``identify`` or link endpoints instead.
249
233
  """
250
234
 
251
235
  company_id: str
252
- discord_profile: DiscordProfileUpdate | None = None
253
- google_profile: GoogleProfile | None = None
254
- github_profile: GitHubProfile | None = None
255
- apple_profile: AppleProfile | None = None
256
236
 
257
237
 
258
238
  class AdminUserUpdate(UserUpdate):
@@ -261,15 +241,11 @@ class AdminUserUpdate(UserUpdate):
261
241
  Extends the tenant-scoped ``UserUpdate`` with ``is_archived``. Set it to
262
242
  ``False`` to restore a soft-deleted user.
263
243
 
264
- Unlike the tenant-scoped surface, the global-admin endpoints still accept
265
- provider profile writes, so the four profile fields are declared here.
244
+ Provider-identity profiles cannot be written here; associate a verified
245
+ provider identity through the ``identify`` or link endpoints instead.
266
246
  """
267
247
 
268
248
  is_archived: bool | None = None
269
- discord_profile: DiscordProfileUpdate | None = None
270
- google_profile: GoogleProfile | None = None
271
- github_profile: GitHubProfile | None = None
272
- apple_profile: AppleProfile | None = None
273
249
 
274
250
 
275
251
  class UserApproveDTO(BaseModel):
@@ -132,7 +132,7 @@ class ChaptersService(BaseService):
132
132
  Args:
133
133
  request: A ChapterCreate model, OR pass fields as keyword arguments.
134
134
  **kwargs: Fields for ChapterCreate if request is not provided.
135
- Accepts: name (str, required), description (str | None).
135
+ Accepts: name (str, required), description (str | None), character_ids (list[str] | None).
136
136
  """
137
137
  body = request if request is not None else ChapterCreate(**kwargs)
138
138
  response = await self._post(
@@ -153,7 +153,7 @@ class ChaptersService(BaseService):
153
153
  chapter_id: The ID of the chapter to update.
154
154
  request: A ChapterUpdate model, OR pass fields as keyword arguments.
155
155
  **kwargs: Fields for ChapterUpdate if request is not provided.
156
- Accepts: name (str | None), description (str | None).
156
+ Accepts: name (str | None), description (str | None), character_ids (list[str] | None).
157
157
  """
158
158
  body = request if request is not None else ChapterUpdate(**kwargs)
159
159
  response = await self._patch(
@@ -243,15 +243,19 @@ class CharacterTraitsService(BaseService):
243
243
  request: TraitCreate | None = None,
244
244
  **kwargs,
245
245
  ) -> CharacterTrait:
246
- """Create a new character trait.
246
+ """Create a new custom character trait.
247
+
248
+ The trait is always created at a value of ``1``; the supplied ``currency`` pays
249
+ for that first dot. ``NPC`` and ``STORYTELLER`` characters accept only
250
+ ``"NO_COST"``.
247
251
 
248
252
  Args:
249
253
  request: A TraitCreate model, OR pass fields as keyword arguments.
250
254
  **kwargs: Fields for TraitCreate if request is not provided.
251
- Required: name (str), category_id (str).
255
+ Required: name (str), category_id (str), currency (TraitModifyCurrency).
252
256
  Optional: description (str | None), max_value (int), min_value (int),
253
257
  show_when_zero (bool), initial_cost (int | None),
254
- upgrade_cost (int | None), value (int | None).
258
+ upgrade_cost (int | None).
255
259
  """
256
260
  body = request if request is not None else self._validate_request(TraitCreate, **kwargs)
257
261
  response = await self._post(