python-kanka 2.0.0__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,377 @@
1
+ Metadata-Version: 2.4
2
+ Name: python-kanka
3
+ Version: 2.0.0
4
+ Summary: A modern Python client for the Kanka API with full typing support
5
+ Home-page: https://github.com/ervwalter/python-kanka
6
+ Author: Erv Walter
7
+ Author-email: erv@ewal.net
8
+ License: MIT
9
+ Project-URL: Bug Reports, https://github.com/ervwalter/python-kanka/issues
10
+ Project-URL: Source, https://github.com/ervwalter/python-kanka
11
+ Project-URL: Documentation, https://github.com/ervwalter/python-kanka#readme
12
+ Project-URL: Kanka API, https://kanka.io/en-US/docs/1.0
13
+ Keywords: kanka api client worldbuilding rpg campaign tabletop ttrpg dnd pathfinder
14
+ Classifier: Development Status :: 4 - Beta
15
+ Classifier: Intended Audience :: Developers
16
+ Classifier: Topic :: Games/Entertainment :: Role-Playing
17
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
18
+ Classifier: License :: OSI Approved :: MIT License
19
+ Classifier: Programming Language :: Python :: 3
20
+ Classifier: Programming Language :: Python :: 3.9
21
+ Classifier: Programming Language :: Python :: 3.10
22
+ Classifier: Programming Language :: Python :: 3.11
23
+ Classifier: Programming Language :: Python :: 3.12
24
+ Classifier: Operating System :: OS Independent
25
+ Classifier: Typing :: Typed
26
+ Requires-Python: >=3.9
27
+ Description-Content-Type: text/markdown
28
+ License-File: LICENSE
29
+ Requires-Dist: requests==2.32.3
30
+ Requires-Dist: requests_toolbelt>=0.9.1
31
+ Requires-Dist: pydantic==2.11.5
32
+ Provides-Extra: dev
33
+ Requires-Dist: pytest>=7.0.0; extra == "dev"
34
+ Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
35
+ Requires-Dist: pytest-mock>=3.10.0; extra == "dev"
36
+ Requires-Dist: black>=23.0.0; extra == "dev"
37
+ Requires-Dist: isort>=5.12.0; extra == "dev"
38
+ Requires-Dist: ruff>=0.1.0; extra == "dev"
39
+ Requires-Dist: mypy>=1.0.0; extra == "dev"
40
+ Requires-Dist: pre-commit>=3.0.0; extra == "dev"
41
+ Dynamic: author
42
+ Dynamic: author-email
43
+ Dynamic: classifier
44
+ Dynamic: description
45
+ Dynamic: description-content-type
46
+ Dynamic: home-page
47
+ Dynamic: keywords
48
+ Dynamic: license
49
+ Dynamic: license-file
50
+ Dynamic: project-url
51
+ Dynamic: provides-extra
52
+ Dynamic: requires-dist
53
+ Dynamic: requires-python
54
+ Dynamic: summary
55
+
56
+ # python-kanka
57
+
58
+ A modern Python client for the [Kanka API](https://app.kanka.io/api-docs/1.0), the collaborative worldbuilding and campaign management platform.
59
+
60
+ *Originally inspired by/forked from [Kathrin Weihe's python-kanka](https://github.com/rbtnx/python-kanka). Thank you to Kathrin for the foundation and inspiration.*
61
+
62
+ ## Features
63
+
64
+ - **Entity Support**: Support for 12 core Kanka entity types:
65
+ - Characters, Locations, Organisations, Families
66
+ - Calendars, Events, Quests, Journals
67
+ - Notes, Tags, Races, Creatures
68
+ - **Type Safety**: Built with Pydantic v2 for data validation and type hints
69
+ - **Python 3.9+**: Full typing support for modern Python versions
70
+ - **Pythonic API**: Consistent interface patterns across all entity types
71
+ - **Error Handling**: Specific exception types for different API errors
72
+ - **Rate Limit Handling**: Automatic retry with exponential backoff
73
+ - **Entity Posts**: Support for entity posts/comments management
74
+ - **Filtering and Search**: Filter entities by various criteria and search across types
75
+ - **Pagination**: Built-in pagination support for large result sets
76
+
77
+ ## Installation
78
+
79
+ Install from PyPI:
80
+ ```bash
81
+ pip install python-kanka
82
+ ```
83
+
84
+ Or install from source:
85
+ ```bash
86
+ git clone https://github.com/ervwalter/python-kanka.git
87
+ cd python-kanka
88
+ pip install -e .
89
+ ```
90
+
91
+ ## Quick Start
92
+
93
+ ```python
94
+ from kanka import KankaClient
95
+
96
+ # Initialize the client
97
+ client = KankaClient(
98
+ token="your-api-token", # Get from https://app.kanka.io/settings/api
99
+ campaign_id=12345 # Your campaign ID
100
+ )
101
+
102
+ # Create a character
103
+ gandalf = client.characters.create(
104
+ name="Gandalf the Grey",
105
+ title="Wizard",
106
+ type="Istari",
107
+ age="2000+ years",
108
+ is_private=False
109
+ )
110
+
111
+ # Update the character
112
+ gandalf = client.characters.update(
113
+ gandalf,
114
+ name="Gandalf the White"
115
+ )
116
+
117
+ # Search across all entities
118
+ results = client.search("Dragon")
119
+ for result in results:
120
+ print(f"{result.name} ({result.type})")
121
+
122
+ # List characters with filters
123
+ wizards = client.characters.list(
124
+ type="Wizard",
125
+ is_private=False
126
+ )
127
+
128
+ # Delete when done
129
+ client.characters.delete(gandalf)
130
+ ```
131
+
132
+ ## Common Use Cases
133
+
134
+ ### Working with Entity Posts
135
+
136
+ ```python
137
+ # Get a character
138
+ character = client.characters.get(character_id)
139
+
140
+ # Create a new post/note (pass the entity object, not just ID)
141
+ post = client.characters.create_post(
142
+ character, # Pass the full entity object
143
+ name="Background",
144
+ entry="*Born in the ancient times...*",
145
+ is_private=False
146
+ )
147
+
148
+ # List all posts for an entity
149
+ posts = client.characters.list_posts(character)
150
+ for post in posts:
151
+ print(f"{post.name}: {post.entry[:50]}...")
152
+
153
+ # Update a post (name field is required even if not changing)
154
+ update = client.characters.update_post(
155
+ character,
156
+ post.id,
157
+ name=post.name, # Required by API
158
+ entry="Updated content..."
159
+ )
160
+ ```
161
+
162
+ ### Advanced Filtering
163
+
164
+ ```python
165
+ # Filter by multiple criteria
166
+ results = client.characters.list(
167
+ name="Gandalf", # Partial name match
168
+ type="Wizard", # Exact type match
169
+ is_private=False, # Only public entities
170
+ tags=[15, 23], # Has specific tags
171
+ page=1, # Pagination
172
+ limit=30 # Results per page
173
+ )
174
+
175
+ # Access the generic entities endpoint
176
+ entities = client.entities(
177
+ types=["character", "location"], # Multiple entity types
178
+ name="Dragon", # Name filter
179
+ tags=[15, 23], # Tag filter
180
+ is_private=False
181
+ )
182
+ ```
183
+
184
+ ### Working with Multiple Entity Types
185
+
186
+ All entity types follow the same pattern:
187
+
188
+ ```python
189
+ # Locations
190
+ rivendell = client.locations.create(
191
+ name="Rivendell",
192
+ type="City",
193
+ parent_location_id=middle_earth.id
194
+ )
195
+
196
+ # Organizations
197
+ council = client.organisations.create(
198
+ name="The White Council",
199
+ type="Council"
200
+ )
201
+
202
+ # Journals
203
+ journal = client.journals.create(
204
+ name="Campaign Log",
205
+ date="3019-03-25"
206
+ )
207
+
208
+ # Notes (for DM/private notes)
209
+ note = client.notes.create(
210
+ name="DM Notes",
211
+ entry="Remember: Gandalf knows about the ring",
212
+ is_private=True
213
+ )
214
+
215
+ # Tags
216
+ tag = client.tags.create(
217
+ name="Important NPC",
218
+ colour="#ff0000"
219
+ )
220
+ ```
221
+
222
+ ### Error Handling
223
+
224
+ ```python
225
+ from kanka.exceptions import (
226
+ NotFoundError,
227
+ ValidationError,
228
+ RateLimitError,
229
+ AuthenticationError
230
+ )
231
+
232
+ try:
233
+ character = client.characters.get(99999)
234
+ except NotFoundError:
235
+ print("Character not found")
236
+ except RateLimitError as e:
237
+ print(f"Rate limited. Retry after {e.retry_after} seconds")
238
+ except ValidationError as e:
239
+ print(f"Invalid data: {e.errors}")
240
+ except AuthenticationError:
241
+ print("Invalid API token")
242
+ ```
243
+
244
+ ## Rate Limiting
245
+
246
+ The client automatically handles API rate limits by retrying requests with exponential backoff:
247
+
248
+ ```python
249
+ # Default behavior - automatic retry on rate limits
250
+ client = KankaClient(token, campaign_id)
251
+
252
+ # Disable automatic retry
253
+ client = KankaClient(
254
+ token,
255
+ campaign_id,
256
+ enable_rate_limit_retry=False
257
+ )
258
+
259
+ # Customize retry behavior
260
+ client = KankaClient(
261
+ token,
262
+ campaign_id,
263
+ max_retries=5, # Try up to 5 times (default: 3)
264
+ retry_delay=2.0, # Initial delay in seconds (default: 1.0)
265
+ max_retry_delay=120.0 # Maximum delay between retries (default: 60.0)
266
+ )
267
+ ```
268
+
269
+ The client parses rate limit headers from the API to determine retry delays and respects the API's rate limits.
270
+
271
+ ## Migration Guide
272
+
273
+ ### Upgrading from v0.x to v2.0
274
+
275
+ The v2.0 release introduces a new API design with Pydantic models and type safety. Here's how to migrate:
276
+
277
+ #### Old API (v0.x)
278
+ ```python
279
+ # Old way - procedural API
280
+ import kanka
281
+ client = kanka.KankaClient(token)
282
+ campaign = client.campaign(campaign_id)
283
+ char = campaign.character(char_id)
284
+ char.name = "New Name"
285
+ char.update()
286
+ ```
287
+
288
+ #### New API (v2.0+)
289
+ ```python
290
+ # New way - object-oriented with managers
291
+ from kanka import KankaClient
292
+ client = KankaClient(token, campaign_id)
293
+ char = client.characters.get(char_id)
294
+ char = client.characters.update(char, name="New Name")
295
+ ```
296
+
297
+ ### Key Differences
298
+
299
+ 1. **Single Client**: No more separate campaign object - everything through `KankaClient`
300
+ 2. **Entity Managers**: Each entity type has a dedicated manager (`client.characters`, `client.locations`, etc.)
301
+ 3. **Immutable Models**: Models are Pydantic objects - use manager methods to update
302
+ 4. **Better Types**: Full typing support with IDE autocomplete
303
+ 5. **Consistent API**: All entities follow the same CRUD pattern
304
+
305
+ ## Development Setup
306
+
307
+ For development, install additional dependencies:
308
+
309
+ ```bash
310
+ # Clone the repository
311
+ git clone https://github.com/ervwalter/python-kanka.git
312
+ cd python-kanka
313
+
314
+ # Install dev dependencies
315
+ pip install -r dev-requirements.txt
316
+ pip install -e . # Install in editable mode
317
+ ```
318
+
319
+ ### Development Tools
320
+
321
+ This project uses several tools to maintain code quality:
322
+
323
+ - **black** - Code formatter
324
+ - **isort** - Import sorter
325
+ - **ruff** - Fast Python linter
326
+ - **pytest** - Testing framework
327
+ - **mypy** - Static type checker
328
+
329
+ Use the Makefile for common development tasks:
330
+
331
+ ```bash
332
+ make install # Install all dependencies
333
+ make format # Format code with black and isort
334
+ make lint # Run linting checks
335
+ make test # Run all tests
336
+ make coverage # Run tests with coverage report
337
+ make check # Run all checks (lint + test)
338
+ make clean # Clean up temporary files
339
+ ```
340
+
341
+ ### Pre-commit Hooks (Optional)
342
+
343
+ To automatically run formatting and linting before each commit:
344
+
345
+ ```bash
346
+ pre-commit install
347
+ ```
348
+
349
+ ## API Documentation
350
+
351
+ See the [API Reference](API_REFERENCE.md) for detailed documentation of all classes and methods.
352
+
353
+ ## Examples
354
+
355
+ Check out the [examples/](examples/) directory for more detailed examples:
356
+
357
+ - `quickstart.py` - Basic usage tutorial
358
+ - `crud_operations.py` - Full CRUD examples for all entity types
359
+ - `filtering.py` - Advanced filtering and search
360
+ - `posts.py` - Working with entity posts
361
+ - `error_handling.py` - Proper error handling patterns
362
+ - `migration.py` - Migrating from the old API
363
+
364
+ ## Contributing
365
+
366
+ Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.
367
+
368
+ ## License
369
+
370
+ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
371
+
372
+ ## Links
373
+
374
+ - [Kanka.io](https://kanka.io) - The Kanka platform
375
+ - [Kanka API Documentation](https://app.kanka.io/api-docs/1.0) - Official API docs
376
+ - [GitHub Repository](https://github.com/ervwalter/python-kanka) - Source code
377
+ - [Issue Tracker](https://github.com/ervwalter/python-kanka/issues) - Report bugs or request features
@@ -0,0 +1,16 @@
1
+ kanka/__init__.py,sha256=CRXZ6Ksdwjdnj0X9Mi0PfKjfuqkbuBubIgOFIi5VEiQ,1940
2
+ kanka/_version.py,sha256=qUKW4fU8V0MfR7QcDOqx466k09zsltHgH0ZEr4DbSK0,67
3
+ kanka/client.py,sha256=8RREBqRIKqrks6TW2yyWX2xYRhIzcw0a05Hg4OIGnVE,18511
4
+ kanka/exceptions.py,sha256=A4P7T7VO_Rp5IYldvFaecE3z4N7WYDgCDojYPu_yDzk,3871
5
+ kanka/managers.py,sha256=mqYs511xa94JnWHNU28pAR8CKkSSsBCXoFyEGPQHGwU,15772
6
+ kanka/py.typed,sha256=mZgbv7X8oKfyMzYIbodUlHrC15905jgP-ZbYviEIL18,86
7
+ kanka/types.py,sha256=ZcIZJZBkivmjoPlm2PXiAQQY_sZqdtZ-dSvF6jVfYIE,293
8
+ kanka/models/__init__.py,sha256=dpIL22R4olQuq26J8B1oB9tDcvmn6_7qdRvIhP1WZjs,1154
9
+ kanka/models/base.py,sha256=1KpfxXPil2z7BO9mFU5G8C1un_hYcqPETFfEWI_EZ7Q,2938
10
+ kanka/models/common.py,sha256=GgvcVrADDc9xcUM-nG2svKKK0pAyhdN0axnwmP7Xrec,4803
11
+ kanka/models/entities.py,sha256=iJCsmd0-QzST8lXFvy25EYEIysIbbrtkieAiocFI-eo,10532
12
+ python_kanka-2.0.0.dist-info/licenses/LICENSE,sha256=37op2CRJ_dU2qGU-iJjczcP-ljtJjpKAgBdKFaiF2GY,1067
13
+ python_kanka-2.0.0.dist-info/METADATA,sha256=JM6c11Uk18sYSbaL9tdqBjLNv4g4UaYTr_X24cNQUMU,10638
14
+ python_kanka-2.0.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
15
+ python_kanka-2.0.0.dist-info/top_level.txt,sha256=vSc0572bt8Jo1ie_cadWOh97JC-TNaYOvnsd80qMohs,6
16
+ python_kanka-2.0.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (80.9.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Erv Walter
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1 @@
1
+ kanka