chunkr-ai 0.1.0a2__tar.gz → 0.1.0a4__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 (95) hide show
  1. {chunkr_ai-0.1.0a2 → chunkr_ai-0.1.0a4}/.gitignore +2 -0
  2. chunkr_ai-0.1.0a4/.release-please-manifest.json +3 -0
  3. {chunkr_ai-0.1.0a2 → chunkr_ai-0.1.0a4}/CHANGELOG.md +33 -0
  4. {chunkr_ai-0.1.0a2 → chunkr_ai-0.1.0a4}/PKG-INFO +38 -20
  5. {chunkr_ai-0.1.0a2 → chunkr_ai-0.1.0a4}/README.md +37 -19
  6. chunkr_ai-0.1.0a4/api.md +50 -0
  7. {chunkr_ai-0.1.0a2 → chunkr_ai-0.1.0a4}/pyproject.toml +1 -1
  8. {chunkr_ai-0.1.0a2 → chunkr_ai-0.1.0a4}/src/chunkr_ai/__init__.py +3 -0
  9. {chunkr_ai-0.1.0a2 → chunkr_ai-0.1.0a4}/src/chunkr_ai/_client.py +18 -10
  10. {chunkr_ai-0.1.0a2 → chunkr_ai-0.1.0a4}/src/chunkr_ai/_files.py +1 -1
  11. {chunkr_ai-0.1.0a2 → chunkr_ai-0.1.0a4}/src/chunkr_ai/_version.py +1 -1
  12. chunkr_ai-0.1.0a4/src/chunkr_ai/lib/tasks_poll.py +122 -0
  13. {chunkr_ai-0.1.0a2 → chunkr_ai-0.1.0a4}/src/chunkr_ai/pagination.py +61 -1
  14. chunkr_ai-0.1.0a4/src/chunkr_ai/resources/__init__.py +47 -0
  15. chunkr_ai-0.1.0a4/src/chunkr_ai/resources/files.py +712 -0
  16. {chunkr_ai-0.1.0a2/src/chunkr_ai/resources/task → chunkr_ai-0.1.0a4/src/chunkr_ai/resources/tasks}/__init__.py +14 -14
  17. {chunkr_ai-0.1.0a2/src/chunkr_ai/resources/task → chunkr_ai-0.1.0a4/src/chunkr_ai/resources/tasks}/parse.py +48 -52
  18. chunkr_ai-0.1.0a2/src/chunkr_ai/resources/task/task.py → chunkr_ai-0.1.0a4/src/chunkr_ai/resources/tasks/tasks.py +58 -126
  19. chunkr_ai-0.1.0a4/src/chunkr_ai/types/__init__.py +15 -0
  20. chunkr_ai-0.1.0a4/src/chunkr_ai/types/delete.py +10 -0
  21. chunkr_ai-0.1.0a4/src/chunkr_ai/types/file.py +30 -0
  22. chunkr_ai-0.1.0a4/src/chunkr_ai/types/file_create_params.py +17 -0
  23. chunkr_ai-0.1.0a4/src/chunkr_ai/types/file_list_params.py +28 -0
  24. chunkr_ai-0.1.0a4/src/chunkr_ai/types/file_url.py +15 -0
  25. chunkr_ai-0.1.0a4/src/chunkr_ai/types/file_url_params.py +15 -0
  26. chunkr_ai-0.1.0a4/src/chunkr_ai/types/files_list_response.py +20 -0
  27. {chunkr_ai-0.1.0a2/src/chunkr_ai/types/task → chunkr_ai-0.1.0a4/src/chunkr_ai/types}/task.py +55 -23
  28. {chunkr_ai-0.1.0a2/src/chunkr_ai/types/task → chunkr_ai-0.1.0a4/src/chunkr_ai/types/tasks}/__init__.py +0 -1
  29. {chunkr_ai-0.1.0a2/src/chunkr_ai/types/task → chunkr_ai-0.1.0a4/src/chunkr_ai/types/tasks}/parse_create_params.py +61 -23
  30. {chunkr_ai-0.1.0a2/src/chunkr_ai/types/task → chunkr_ai-0.1.0a4/src/chunkr_ai/types/tasks}/parse_update_params.py +54 -22
  31. {chunkr_ai-0.1.0a2/tests/api_resources/task → chunkr_ai-0.1.0a4/tests/api_resources/tasks}/test_parse.py +19 -37
  32. chunkr_ai-0.1.0a4/tests/api_resources/test_files.py +488 -0
  33. {chunkr_ai-0.1.0a2 → chunkr_ai-0.1.0a4}/tests/api_resources/test_health.py +0 -6
  34. chunkr_ai-0.1.0a2/tests/api_resources/test_task.py → chunkr_ai-0.1.0a4/tests/api_resources/test_tasks.py +37 -71
  35. {chunkr_ai-0.1.0a2 → chunkr_ai-0.1.0a4}/tests/test_client.py +20 -20
  36. chunkr_ai-0.1.0a4/tests/test_tasks_poll.py +62 -0
  37. chunkr_ai-0.1.0a2/.release-please-manifest.json +0 -3
  38. chunkr_ai-0.1.0a2/api.md +0 -33
  39. chunkr_ai-0.1.0a2/src/chunkr_ai/resources/__init__.py +0 -33
  40. chunkr_ai-0.1.0a2/src/chunkr_ai/types/__init__.py +0 -8
  41. {chunkr_ai-0.1.0a2 → chunkr_ai-0.1.0a4}/CONTRIBUTING.md +0 -0
  42. {chunkr_ai-0.1.0a2 → chunkr_ai-0.1.0a4}/LICENSE +0 -0
  43. {chunkr_ai-0.1.0a2 → chunkr_ai-0.1.0a4}/SECURITY.md +0 -0
  44. {chunkr_ai-0.1.0a2 → chunkr_ai-0.1.0a4}/bin/check-release-environment +0 -0
  45. {chunkr_ai-0.1.0a2 → chunkr_ai-0.1.0a4}/bin/publish-pypi +0 -0
  46. {chunkr_ai-0.1.0a2 → chunkr_ai-0.1.0a4}/examples/.keep +0 -0
  47. {chunkr_ai-0.1.0a2 → chunkr_ai-0.1.0a4}/mypy.ini +0 -0
  48. {chunkr_ai-0.1.0a2 → chunkr_ai-0.1.0a4}/noxfile.py +0 -0
  49. {chunkr_ai-0.1.0a2 → chunkr_ai-0.1.0a4}/release-please-config.json +0 -0
  50. {chunkr_ai-0.1.0a2 → chunkr_ai-0.1.0a4}/requirements-dev.lock +0 -0
  51. {chunkr_ai-0.1.0a2 → chunkr_ai-0.1.0a4}/requirements.lock +0 -0
  52. {chunkr_ai-0.1.0a2 → chunkr_ai-0.1.0a4}/src/chunkr/lib/.keep +0 -0
  53. {chunkr_ai-0.1.0a2 → chunkr_ai-0.1.0a4}/src/chunkr_ai/_base_client.py +0 -0
  54. {chunkr_ai-0.1.0a2 → chunkr_ai-0.1.0a4}/src/chunkr_ai/_compat.py +0 -0
  55. {chunkr_ai-0.1.0a2 → chunkr_ai-0.1.0a4}/src/chunkr_ai/_constants.py +0 -0
  56. {chunkr_ai-0.1.0a2 → chunkr_ai-0.1.0a4}/src/chunkr_ai/_exceptions.py +0 -0
  57. {chunkr_ai-0.1.0a2 → chunkr_ai-0.1.0a4}/src/chunkr_ai/_models.py +0 -0
  58. {chunkr_ai-0.1.0a2 → chunkr_ai-0.1.0a4}/src/chunkr_ai/_qs.py +0 -0
  59. {chunkr_ai-0.1.0a2 → chunkr_ai-0.1.0a4}/src/chunkr_ai/_resource.py +0 -0
  60. {chunkr_ai-0.1.0a2 → chunkr_ai-0.1.0a4}/src/chunkr_ai/_response.py +0 -0
  61. {chunkr_ai-0.1.0a2 → chunkr_ai-0.1.0a4}/src/chunkr_ai/_streaming.py +0 -0
  62. {chunkr_ai-0.1.0a2 → chunkr_ai-0.1.0a4}/src/chunkr_ai/_types.py +0 -0
  63. {chunkr_ai-0.1.0a2 → chunkr_ai-0.1.0a4}/src/chunkr_ai/_utils/__init__.py +0 -0
  64. {chunkr_ai-0.1.0a2 → chunkr_ai-0.1.0a4}/src/chunkr_ai/_utils/_logs.py +0 -0
  65. {chunkr_ai-0.1.0a2 → chunkr_ai-0.1.0a4}/src/chunkr_ai/_utils/_proxy.py +0 -0
  66. {chunkr_ai-0.1.0a2 → chunkr_ai-0.1.0a4}/src/chunkr_ai/_utils/_reflection.py +0 -0
  67. {chunkr_ai-0.1.0a2 → chunkr_ai-0.1.0a4}/src/chunkr_ai/_utils/_resources_proxy.py +0 -0
  68. {chunkr_ai-0.1.0a2 → chunkr_ai-0.1.0a4}/src/chunkr_ai/_utils/_streams.py +0 -0
  69. {chunkr_ai-0.1.0a2 → chunkr_ai-0.1.0a4}/src/chunkr_ai/_utils/_sync.py +0 -0
  70. {chunkr_ai-0.1.0a2 → chunkr_ai-0.1.0a4}/src/chunkr_ai/_utils/_transform.py +0 -0
  71. {chunkr_ai-0.1.0a2 → chunkr_ai-0.1.0a4}/src/chunkr_ai/_utils/_typing.py +0 -0
  72. {chunkr_ai-0.1.0a2 → chunkr_ai-0.1.0a4}/src/chunkr_ai/_utils/_utils.py +0 -0
  73. {chunkr_ai-0.1.0a2 → chunkr_ai-0.1.0a4}/src/chunkr_ai/lib/.keep +0 -0
  74. {chunkr_ai-0.1.0a2 → chunkr_ai-0.1.0a4}/src/chunkr_ai/py.typed +0 -0
  75. {chunkr_ai-0.1.0a2 → chunkr_ai-0.1.0a4}/src/chunkr_ai/resources/health.py +0 -0
  76. {chunkr_ai-0.1.0a2 → chunkr_ai-0.1.0a4}/src/chunkr_ai/types/health_check_response.py +0 -0
  77. {chunkr_ai-0.1.0a2 → chunkr_ai-0.1.0a4}/src/chunkr_ai/types/task_get_params.py +0 -0
  78. {chunkr_ai-0.1.0a2 → chunkr_ai-0.1.0a4}/src/chunkr_ai/types/task_list_params.py +0 -0
  79. {chunkr_ai-0.1.0a2 → chunkr_ai-0.1.0a4}/tests/__init__.py +0 -0
  80. {chunkr_ai-0.1.0a2 → chunkr_ai-0.1.0a4}/tests/api_resources/__init__.py +0 -0
  81. {chunkr_ai-0.1.0a2/tests/api_resources/task → chunkr_ai-0.1.0a4/tests/api_resources/tasks}/__init__.py +0 -0
  82. {chunkr_ai-0.1.0a2 → chunkr_ai-0.1.0a4}/tests/conftest.py +0 -0
  83. {chunkr_ai-0.1.0a2 → chunkr_ai-0.1.0a4}/tests/sample_file.txt +0 -0
  84. {chunkr_ai-0.1.0a2 → chunkr_ai-0.1.0a4}/tests/test_deepcopy.py +0 -0
  85. {chunkr_ai-0.1.0a2 → chunkr_ai-0.1.0a4}/tests/test_extract_files.py +0 -0
  86. {chunkr_ai-0.1.0a2 → chunkr_ai-0.1.0a4}/tests/test_files.py +0 -0
  87. {chunkr_ai-0.1.0a2 → chunkr_ai-0.1.0a4}/tests/test_models.py +0 -0
  88. {chunkr_ai-0.1.0a2 → chunkr_ai-0.1.0a4}/tests/test_qs.py +0 -0
  89. {chunkr_ai-0.1.0a2 → chunkr_ai-0.1.0a4}/tests/test_required_args.py +0 -0
  90. {chunkr_ai-0.1.0a2 → chunkr_ai-0.1.0a4}/tests/test_response.py +0 -0
  91. {chunkr_ai-0.1.0a2 → chunkr_ai-0.1.0a4}/tests/test_streaming.py +0 -0
  92. {chunkr_ai-0.1.0a2 → chunkr_ai-0.1.0a4}/tests/test_transform.py +0 -0
  93. {chunkr_ai-0.1.0a2 → chunkr_ai-0.1.0a4}/tests/test_utils/test_proxy.py +0 -0
  94. {chunkr_ai-0.1.0a2 → chunkr_ai-0.1.0a4}/tests/test_utils/test_typing.py +0 -0
  95. {chunkr_ai-0.1.0a2 → chunkr_ai-0.1.0a4}/tests/utils.py +0 -0
@@ -13,3 +13,5 @@ dist
13
13
  .envrc
14
14
  codegen.log
15
15
  Brewfile.lock.json
16
+
17
+ .lh
@@ -0,0 +1,3 @@
1
+ {
2
+ ".": "0.1.0-alpha.4"
3
+ }
@@ -1,5 +1,38 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.1.0-alpha.4 (2025-08-09)
4
+
5
+ Full Changelog: [v0.1.0-alpha.3...v0.1.0-alpha.4](https://github.com/lumina-ai-inc/chunkr-python/compare/v0.1.0-alpha.3...v0.1.0-alpha.4)
6
+
7
+ ### Features
8
+
9
+ * **api:** added poll() and apoll() methods to Task ([#16](https://github.com/lumina-ai-inc/chunkr-python/issues/16)) ([da329dd](https://github.com/lumina-ai-inc/chunkr-python/commit/da329dda8ac0818e2b770e156b6b69456a5cfc72))
10
+ * **api:** manual updates ([a704c5d](https://github.com/lumina-ai-inc/chunkr-python/commit/a704c5deed4c91af239afb58fce99091f8784210))
11
+
12
+ ## 0.1.0-alpha.3 (2025-08-09)
13
+
14
+ Full Changelog: [v0.1.0-alpha.2...v0.1.0-alpha.3](https://github.com/lumina-ai-inc/chunkr-python/compare/v0.1.0-alpha.2...v0.1.0-alpha.3)
15
+
16
+ ### Features
17
+
18
+ * **api:** api update ([a00a95e](https://github.com/lumina-ai-inc/chunkr-python/commit/a00a95ec22d7141e9139dcdeac65f882e9be0d39))
19
+ * **api:** api update ([145a438](https://github.com/lumina-ai-inc/chunkr-python/commit/145a43891e138f9b986815b105ce65ea2ebaaf17))
20
+ * **api:** api update ([79170d4](https://github.com/lumina-ai-inc/chunkr-python/commit/79170d4b086300e3beb6cb536c574ba889164ee2))
21
+ * **api:** api update ([29fe5ea](https://github.com/lumina-ai-inc/chunkr-python/commit/29fe5ea3cc4de3c097ea446927bc499848cd5a2d))
22
+ * **api:** manual updates ([171e2f9](https://github.com/lumina-ai-inc/chunkr-python/commit/171e2f9046863086957002cb2eb77e726b2cac6e))
23
+ * **api:** manual updates ([62d6d6e](https://github.com/lumina-ai-inc/chunkr-python/commit/62d6d6e39eb6b5a5dde6c2e2e9f5caa4a01c2828))
24
+ * **api:** manual updates ([16190d7](https://github.com/lumina-ai-inc/chunkr-python/commit/16190d7c726aad97a749e3c606fa412f4f5fd191))
25
+ * **api:** manual updates ([5d73fd1](https://github.com/lumina-ai-inc/chunkr-python/commit/5d73fd1fd0368c56777a69992c302d5ee088a8f1))
26
+ * **api:** manual updates ([9269fd1](https://github.com/lumina-ai-inc/chunkr-python/commit/9269fd1f81567aa69a17a4d4b01adad8d2866e3b))
27
+ * **api:** manual updates ([ac4cd88](https://github.com/lumina-ai-inc/chunkr-python/commit/ac4cd883378d3f4fb89df50fc4eac8d94655648d))
28
+ * **api:** manual updates ([f29e11a](https://github.com/lumina-ai-inc/chunkr-python/commit/f29e11ad5014311faba9162e70a6aae40003c994))
29
+
30
+
31
+ ### Chores
32
+
33
+ * **internal:** update comment in script ([f44c608](https://github.com/lumina-ai-inc/chunkr-python/commit/f44c60889e1b26b85c142aa318a6f7801ae87241))
34
+ * update @stainless-api/prism-cli to v5.15.0 ([c0aab83](https://github.com/lumina-ai-inc/chunkr-python/commit/c0aab83a4ea61ea57f0424b05f19bbf46efb6ca0))
35
+
3
36
  ## 0.1.0-alpha.2 (2025-08-06)
4
37
 
5
38
  Full Changelog: [v0.1.0-alpha.1...v0.1.0-alpha.2](https://github.com/lumina-ai-inc/chunkr-python/compare/v0.1.0-alpha.1...v0.1.0-alpha.2)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: chunkr-ai
3
- Version: 0.1.0a2
3
+ Version: 0.1.0a4
4
4
  Summary: The official Python library for the chunkr API
5
5
  Project-URL: Homepage, https://github.com/lumina-ai-inc/chunkr-python
6
6
  Project-URL: Repository, https://github.com/lumina-ai-inc/chunkr-python
@@ -70,7 +70,7 @@ client = Chunkr(
70
70
  api_key=os.environ.get("CHUNKR_API_KEY"), # This is the default and can be omitted
71
71
  )
72
72
 
73
- task = client.task.parse.create(
73
+ task = client.tasks.parse.create(
74
74
  file="string",
75
75
  )
76
76
  print(task.task_id)
@@ -96,7 +96,7 @@ client = AsyncChunkr(
96
96
 
97
97
 
98
98
  async def main() -> None:
99
- task = await client.task.parse.create(
99
+ task = await client.tasks.parse.create(
100
100
  file="string",
101
101
  )
102
102
  print(task.task_id)
@@ -131,7 +131,7 @@ async def main() -> None:
131
131
  api_key="My API Key",
132
132
  http_client=DefaultAioHttpClient(),
133
133
  ) as client:
134
- task = await client.task.parse.create(
134
+ task = await client.tasks.parse.create(
135
135
  file="string",
136
136
  )
137
137
  print(task.task_id)
@@ -162,7 +162,7 @@ client = Chunkr()
162
162
 
163
163
  all_tasks = []
164
164
  # Automatically fetches more pages as needed.
165
- for task in client.task.list(
165
+ for task in client.tasks.list(
166
166
  limit=100,
167
167
  ):
168
168
  # Do something with task here
@@ -182,7 +182,7 @@ client = AsyncChunkr()
182
182
  async def main() -> None:
183
183
  all_tasks = []
184
184
  # Iterate through items across all pages, issuing requests as needed.
185
- async for task in client.task.list(
185
+ async for task in client.tasks.list(
186
186
  limit=100,
187
187
  ):
188
188
  all_tasks.append(task)
@@ -195,7 +195,7 @@ asyncio.run(main())
195
195
  Alternatively, you can use the `.has_next_page()`, `.next_page_info()`, or `.get_next_page()` methods for more granular control working with pages:
196
196
 
197
197
  ```python
198
- first_page = await client.task.list(
198
+ first_page = await client.tasks.list(
199
199
  limit=100,
200
200
  )
201
201
  if first_page.has_next_page():
@@ -209,7 +209,7 @@ if first_page.has_next_page():
209
209
  Or just work directly with the returned data:
210
210
 
211
211
  ```python
212
- first_page = await client.task.list(
212
+ first_page = await client.tasks.list(
213
213
  limit=100,
214
214
  )
215
215
 
@@ -229,13 +229,31 @@ from chunkr_ai import Chunkr
229
229
 
230
230
  client = Chunkr()
231
231
 
232
- task = client.task.parse.create(
232
+ task = client.tasks.parse.create(
233
233
  file="file",
234
234
  chunk_processing={},
235
235
  )
236
236
  print(task.chunk_processing)
237
237
  ```
238
238
 
239
+ ## File uploads
240
+
241
+ Request parameters that correspond to file uploads can be passed as `bytes`, or a [`PathLike`](https://docs.python.org/3/library/os.html#os.PathLike) instance or a tuple of `(filename, contents, media type)`.
242
+
243
+ ```python
244
+ from pathlib import Path
245
+ from chunkr_ai import Chunkr
246
+
247
+ client = Chunkr()
248
+
249
+ client.files.create(
250
+ file=Path("/path/to/file"),
251
+ file_metadata="file_metadata",
252
+ )
253
+ ```
254
+
255
+ The async client uses the exact same interface. If you pass a [`PathLike`](https://docs.python.org/3/library/os.html#os.PathLike) instance, the file contents will be read asynchronously automatically.
256
+
239
257
  ## Handling errors
240
258
 
241
259
  When the library is unable to connect to the API (for example, due to network connection problems or a timeout), a subclass of `chunkr_ai.APIConnectionError` is raised.
@@ -252,8 +270,8 @@ from chunkr_ai import Chunkr
252
270
  client = Chunkr()
253
271
 
254
272
  try:
255
- client.task.parse.create(
256
- file="base64 or url",
273
+ client.tasks.parse.create(
274
+ file="string",
257
275
  )
258
276
  except chunkr_ai.APIConnectionError as e:
259
277
  print("The server could not be reached")
@@ -297,8 +315,8 @@ client = Chunkr(
297
315
  )
298
316
 
299
317
  # Or, configure per-request:
300
- client.with_options(max_retries=5).task.parse.create(
301
- file="base64 or url",
318
+ client.with_options(max_retries=5).tasks.parse.create(
319
+ file="string",
302
320
  )
303
321
  ```
304
322
 
@@ -322,8 +340,8 @@ client = Chunkr(
322
340
  )
323
341
 
324
342
  # Override per-request:
325
- client.with_options(timeout=5.0).task.parse.create(
326
- file="base64 or url",
343
+ client.with_options(timeout=5.0).tasks.parse.create(
344
+ file="string",
327
345
  )
328
346
  ```
329
347
 
@@ -365,12 +383,12 @@ The "raw" Response object can be accessed by prefixing `.with_raw_response.` to
365
383
  from chunkr_ai import Chunkr
366
384
 
367
385
  client = Chunkr()
368
- response = client.task.parse.with_raw_response.create(
369
- file="base64 or url",
386
+ response = client.tasks.parse.with_raw_response.create(
387
+ file="string",
370
388
  )
371
389
  print(response.headers.get('X-My-Header'))
372
390
 
373
- parse = response.parse() # get the object that `task.parse.create()` would have returned
391
+ parse = response.parse() # get the object that `tasks.parse.create()` would have returned
374
392
  print(parse.task_id)
375
393
  ```
376
394
 
@@ -385,8 +403,8 @@ The above interface eagerly reads the full response body when you make the reque
385
403
  To stream the response body, use `.with_streaming_response` instead, which requires a context manager and only reads the response body once you call `.read()`, `.text()`, `.json()`, `.iter_bytes()`, `.iter_text()`, `.iter_lines()` or `.parse()`. In the async client, these are async methods.
386
404
 
387
405
  ```python
388
- with client.task.parse.with_streaming_response.create(
389
- file="base64 or url",
406
+ with client.tasks.parse.with_streaming_response.create(
407
+ file="string",
390
408
  ) as response:
391
409
  print(response.headers.get("X-My-Header"))
392
410
 
@@ -35,7 +35,7 @@ client = Chunkr(
35
35
  api_key=os.environ.get("CHUNKR_API_KEY"), # This is the default and can be omitted
36
36
  )
37
37
 
38
- task = client.task.parse.create(
38
+ task = client.tasks.parse.create(
39
39
  file="string",
40
40
  )
41
41
  print(task.task_id)
@@ -61,7 +61,7 @@ client = AsyncChunkr(
61
61
 
62
62
 
63
63
  async def main() -> None:
64
- task = await client.task.parse.create(
64
+ task = await client.tasks.parse.create(
65
65
  file="string",
66
66
  )
67
67
  print(task.task_id)
@@ -96,7 +96,7 @@ async def main() -> None:
96
96
  api_key="My API Key",
97
97
  http_client=DefaultAioHttpClient(),
98
98
  ) as client:
99
- task = await client.task.parse.create(
99
+ task = await client.tasks.parse.create(
100
100
  file="string",
101
101
  )
102
102
  print(task.task_id)
@@ -127,7 +127,7 @@ client = Chunkr()
127
127
 
128
128
  all_tasks = []
129
129
  # Automatically fetches more pages as needed.
130
- for task in client.task.list(
130
+ for task in client.tasks.list(
131
131
  limit=100,
132
132
  ):
133
133
  # Do something with task here
@@ -147,7 +147,7 @@ client = AsyncChunkr()
147
147
  async def main() -> None:
148
148
  all_tasks = []
149
149
  # Iterate through items across all pages, issuing requests as needed.
150
- async for task in client.task.list(
150
+ async for task in client.tasks.list(
151
151
  limit=100,
152
152
  ):
153
153
  all_tasks.append(task)
@@ -160,7 +160,7 @@ asyncio.run(main())
160
160
  Alternatively, you can use the `.has_next_page()`, `.next_page_info()`, or `.get_next_page()` methods for more granular control working with pages:
161
161
 
162
162
  ```python
163
- first_page = await client.task.list(
163
+ first_page = await client.tasks.list(
164
164
  limit=100,
165
165
  )
166
166
  if first_page.has_next_page():
@@ -174,7 +174,7 @@ if first_page.has_next_page():
174
174
  Or just work directly with the returned data:
175
175
 
176
176
  ```python
177
- first_page = await client.task.list(
177
+ first_page = await client.tasks.list(
178
178
  limit=100,
179
179
  )
180
180
 
@@ -194,13 +194,31 @@ from chunkr_ai import Chunkr
194
194
 
195
195
  client = Chunkr()
196
196
 
197
- task = client.task.parse.create(
197
+ task = client.tasks.parse.create(
198
198
  file="file",
199
199
  chunk_processing={},
200
200
  )
201
201
  print(task.chunk_processing)
202
202
  ```
203
203
 
204
+ ## File uploads
205
+
206
+ Request parameters that correspond to file uploads can be passed as `bytes`, or a [`PathLike`](https://docs.python.org/3/library/os.html#os.PathLike) instance or a tuple of `(filename, contents, media type)`.
207
+
208
+ ```python
209
+ from pathlib import Path
210
+ from chunkr_ai import Chunkr
211
+
212
+ client = Chunkr()
213
+
214
+ client.files.create(
215
+ file=Path("/path/to/file"),
216
+ file_metadata="file_metadata",
217
+ )
218
+ ```
219
+
220
+ The async client uses the exact same interface. If you pass a [`PathLike`](https://docs.python.org/3/library/os.html#os.PathLike) instance, the file contents will be read asynchronously automatically.
221
+
204
222
  ## Handling errors
205
223
 
206
224
  When the library is unable to connect to the API (for example, due to network connection problems or a timeout), a subclass of `chunkr_ai.APIConnectionError` is raised.
@@ -217,8 +235,8 @@ from chunkr_ai import Chunkr
217
235
  client = Chunkr()
218
236
 
219
237
  try:
220
- client.task.parse.create(
221
- file="base64 or url",
238
+ client.tasks.parse.create(
239
+ file="string",
222
240
  )
223
241
  except chunkr_ai.APIConnectionError as e:
224
242
  print("The server could not be reached")
@@ -262,8 +280,8 @@ client = Chunkr(
262
280
  )
263
281
 
264
282
  # Or, configure per-request:
265
- client.with_options(max_retries=5).task.parse.create(
266
- file="base64 or url",
283
+ client.with_options(max_retries=5).tasks.parse.create(
284
+ file="string",
267
285
  )
268
286
  ```
269
287
 
@@ -287,8 +305,8 @@ client = Chunkr(
287
305
  )
288
306
 
289
307
  # Override per-request:
290
- client.with_options(timeout=5.0).task.parse.create(
291
- file="base64 or url",
308
+ client.with_options(timeout=5.0).tasks.parse.create(
309
+ file="string",
292
310
  )
293
311
  ```
294
312
 
@@ -330,12 +348,12 @@ The "raw" Response object can be accessed by prefixing `.with_raw_response.` to
330
348
  from chunkr_ai import Chunkr
331
349
 
332
350
  client = Chunkr()
333
- response = client.task.parse.with_raw_response.create(
334
- file="base64 or url",
351
+ response = client.tasks.parse.with_raw_response.create(
352
+ file="string",
335
353
  )
336
354
  print(response.headers.get('X-My-Header'))
337
355
 
338
- parse = response.parse() # get the object that `task.parse.create()` would have returned
356
+ parse = response.parse() # get the object that `tasks.parse.create()` would have returned
339
357
  print(parse.task_id)
340
358
  ```
341
359
 
@@ -350,8 +368,8 @@ The above interface eagerly reads the full response body when you make the reque
350
368
  To stream the response body, use `.with_streaming_response` instead, which requires a context manager and only reads the response body once you call `.read()`, `.text()`, `.json()`, `.iter_bytes()`, `.iter_text()`, `.iter_lines()` or `.parse()`. In the async client, these are async methods.
351
369
 
352
370
  ```python
353
- with client.task.parse.with_streaming_response.create(
354
- file="base64 or url",
371
+ with client.tasks.parse.with_streaming_response.create(
372
+ file="string",
355
373
  ) as response:
356
374
  print(response.headers.get("X-My-Header"))
357
375
 
@@ -0,0 +1,50 @@
1
+ # Tasks
2
+
3
+ Types:
4
+
5
+ ```python
6
+ from chunkr_ai.types import Task
7
+ ```
8
+
9
+ Methods:
10
+
11
+ - <code title="get /tasks">client.tasks.<a href="./src/chunkr_ai/resources/tasks/tasks.py">list</a>(\*\*<a href="src/chunkr_ai/types/task_list_params.py">params</a>) -> <a href="./src/chunkr_ai/types/task.py">SyncTasksPage[Task]</a></code>
12
+ - <code title="delete /tasks/{task_id}">client.tasks.<a href="./src/chunkr_ai/resources/tasks/tasks.py">delete</a>(task_id) -> None</code>
13
+ - <code title="get /tasks/{task_id}/cancel">client.tasks.<a href="./src/chunkr_ai/resources/tasks/tasks.py">cancel</a>(task_id) -> None</code>
14
+ - <code title="get /tasks/{task_id}">client.tasks.<a href="./src/chunkr_ai/resources/tasks/tasks.py">get</a>(task_id, \*\*<a href="src/chunkr_ai/types/task_get_params.py">params</a>) -> <a href="./src/chunkr_ai/types/task.py">Task</a></code>
15
+
16
+ ## Parse
17
+
18
+ Methods:
19
+
20
+ - <code title="post /tasks/parse">client.tasks.parse.<a href="./src/chunkr_ai/resources/tasks/parse.py">create</a>(\*\*<a href="src/chunkr_ai/types/tasks/parse_create_params.py">params</a>) -> <a href="./src/chunkr_ai/types/task.py">Task</a></code>
21
+ - <code title="patch /tasks/parse/{task_id}">client.tasks.parse.<a href="./src/chunkr_ai/resources/tasks/parse.py">update</a>(task_id, \*\*<a href="src/chunkr_ai/types/tasks/parse_update_params.py">params</a>) -> <a href="./src/chunkr_ai/types/task.py">Task</a></code>
22
+
23
+ # Files
24
+
25
+ Types:
26
+
27
+ ```python
28
+ from chunkr_ai.types import Delete, File, FilesListResponse, FileURL
29
+ ```
30
+
31
+ Methods:
32
+
33
+ - <code title="post /files">client.files.<a href="./src/chunkr_ai/resources/files.py">create</a>(\*\*<a href="src/chunkr_ai/types/file_create_params.py">params</a>) -> <a href="./src/chunkr_ai/types/file.py">File</a></code>
34
+ - <code title="get /files">client.files.<a href="./src/chunkr_ai/resources/files.py">list</a>(\*\*<a href="src/chunkr_ai/types/file_list_params.py">params</a>) -> <a href="./src/chunkr_ai/types/file.py">SyncFilesPage[File]</a></code>
35
+ - <code title="delete /files/{file_id}">client.files.<a href="./src/chunkr_ai/resources/files.py">delete</a>(file_id) -> <a href="./src/chunkr_ai/types/delete.py">Delete</a></code>
36
+ - <code title="get /files/{file_id}/content">client.files.<a href="./src/chunkr_ai/resources/files.py">content</a>(file_id) -> None</code>
37
+ - <code title="get /files/{file_id}">client.files.<a href="./src/chunkr_ai/resources/files.py">get</a>(file_id) -> <a href="./src/chunkr_ai/types/file.py">File</a></code>
38
+ - <code title="get /files/{file_id}/url">client.files.<a href="./src/chunkr_ai/resources/files.py">url</a>(file_id, \*\*<a href="src/chunkr_ai/types/file_url_params.py">params</a>) -> <a href="./src/chunkr_ai/types/file_url.py">FileURL</a></code>
39
+
40
+ # Health
41
+
42
+ Types:
43
+
44
+ ```python
45
+ from chunkr_ai.types import HealthCheckResponse
46
+ ```
47
+
48
+ Methods:
49
+
50
+ - <code title="get /health">client.health.<a href="./src/chunkr_ai/resources/health.py">check</a>() -> str</code>
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "chunkr-ai"
3
- version = "0.1.0-alpha.2"
3
+ version = "0.1.0-alpha.4"
4
4
  description = "The official Python library for the chunkr API"
5
5
  dynamic = ["readme"]
6
6
  license = "Apache-2.0"
@@ -72,6 +72,9 @@ __all__ = [
72
72
  ]
73
73
 
74
74
  if not _t.TYPE_CHECKING:
75
+ # Load custom helpers that monkey-patch generated types.
76
+ # This keeps custom code separate from generated files, per Stainless guidance.
77
+ from .lib import tasks_poll as _tasks_poll # noqa: F401
75
78
  from ._utils._resources_proxy import resources as resources
76
79
 
77
80
  _setup_logging()
@@ -21,7 +21,7 @@ from ._types import (
21
21
  )
22
22
  from ._utils import is_given, get_async_library
23
23
  from ._version import __version__
24
- from .resources import health
24
+ from .resources import files, health
25
25
  from ._streaming import Stream as Stream, AsyncStream as AsyncStream
26
26
  from ._exceptions import ChunkrError, APIStatusError
27
27
  from ._base_client import (
@@ -29,13 +29,14 @@ from ._base_client import (
29
29
  SyncAPIClient,
30
30
  AsyncAPIClient,
31
31
  )
32
- from .resources.task import task
32
+ from .resources.tasks import tasks
33
33
 
34
34
  __all__ = ["Timeout", "Transport", "ProxiesTypes", "RequestOptions", "Chunkr", "AsyncChunkr", "Client", "AsyncClient"]
35
35
 
36
36
 
37
37
  class Chunkr(SyncAPIClient):
38
- task: task.TaskResource
38
+ tasks: tasks.TasksResource
39
+ files: files.FilesResource
39
40
  health: health.HealthResource
40
41
  with_raw_response: ChunkrWithRawResponse
41
42
  with_streaming_response: ChunkrWithStreamedResponse
@@ -94,7 +95,8 @@ class Chunkr(SyncAPIClient):
94
95
  _strict_response_validation=_strict_response_validation,
95
96
  )
96
97
 
97
- self.task = task.TaskResource(self)
98
+ self.tasks = tasks.TasksResource(self)
99
+ self.files = files.FilesResource(self)
98
100
  self.health = health.HealthResource(self)
99
101
  self.with_raw_response = ChunkrWithRawResponse(self)
100
102
  self.with_streaming_response = ChunkrWithStreamedResponse(self)
@@ -205,7 +207,8 @@ class Chunkr(SyncAPIClient):
205
207
 
206
208
 
207
209
  class AsyncChunkr(AsyncAPIClient):
208
- task: task.AsyncTaskResource
210
+ tasks: tasks.AsyncTasksResource
211
+ files: files.AsyncFilesResource
209
212
  health: health.AsyncHealthResource
210
213
  with_raw_response: AsyncChunkrWithRawResponse
211
214
  with_streaming_response: AsyncChunkrWithStreamedResponse
@@ -264,7 +267,8 @@ class AsyncChunkr(AsyncAPIClient):
264
267
  _strict_response_validation=_strict_response_validation,
265
268
  )
266
269
 
267
- self.task = task.AsyncTaskResource(self)
270
+ self.tasks = tasks.AsyncTasksResource(self)
271
+ self.files = files.AsyncFilesResource(self)
268
272
  self.health = health.AsyncHealthResource(self)
269
273
  self.with_raw_response = AsyncChunkrWithRawResponse(self)
270
274
  self.with_streaming_response = AsyncChunkrWithStreamedResponse(self)
@@ -376,25 +380,29 @@ class AsyncChunkr(AsyncAPIClient):
376
380
 
377
381
  class ChunkrWithRawResponse:
378
382
  def __init__(self, client: Chunkr) -> None:
379
- self.task = task.TaskResourceWithRawResponse(client.task)
383
+ self.tasks = tasks.TasksResourceWithRawResponse(client.tasks)
384
+ self.files = files.FilesResourceWithRawResponse(client.files)
380
385
  self.health = health.HealthResourceWithRawResponse(client.health)
381
386
 
382
387
 
383
388
  class AsyncChunkrWithRawResponse:
384
389
  def __init__(self, client: AsyncChunkr) -> None:
385
- self.task = task.AsyncTaskResourceWithRawResponse(client.task)
390
+ self.tasks = tasks.AsyncTasksResourceWithRawResponse(client.tasks)
391
+ self.files = files.AsyncFilesResourceWithRawResponse(client.files)
386
392
  self.health = health.AsyncHealthResourceWithRawResponse(client.health)
387
393
 
388
394
 
389
395
  class ChunkrWithStreamedResponse:
390
396
  def __init__(self, client: Chunkr) -> None:
391
- self.task = task.TaskResourceWithStreamingResponse(client.task)
397
+ self.tasks = tasks.TasksResourceWithStreamingResponse(client.tasks)
398
+ self.files = files.FilesResourceWithStreamingResponse(client.files)
392
399
  self.health = health.HealthResourceWithStreamingResponse(client.health)
393
400
 
394
401
 
395
402
  class AsyncChunkrWithStreamedResponse:
396
403
  def __init__(self, client: AsyncChunkr) -> None:
397
- self.task = task.AsyncTaskResourceWithStreamingResponse(client.task)
404
+ self.tasks = tasks.AsyncTasksResourceWithStreamingResponse(client.tasks)
405
+ self.files = files.AsyncFilesResourceWithStreamingResponse(client.files)
398
406
  self.health = health.AsyncHealthResourceWithStreamingResponse(client.health)
399
407
 
400
408
 
@@ -34,7 +34,7 @@ def assert_is_file_content(obj: object, *, key: str | None = None) -> None:
34
34
  if not is_file_content(obj):
35
35
  prefix = f"Expected entry at `{key}`" if key is not None else f"Expected file input `{obj!r}`"
36
36
  raise RuntimeError(
37
- f"{prefix} to be bytes, an io.IOBase instance, PathLike or a tuple but received {type(obj)} instead."
37
+ f"{prefix} to be bytes, an io.IOBase instance, PathLike or a tuple but received {type(obj)} instead. See https://github.com/lumina-ai-inc/chunkr-python/tree/main#file-uploads"
38
38
  ) from None
39
39
 
40
40
 
@@ -1,4 +1,4 @@
1
1
  # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
2
2
 
3
3
  __title__ = "chunkr_ai"
4
- __version__ = "0.1.0-alpha.2" # x-release-please-version
4
+ __version__ = "0.1.0-alpha.4" # x-release-please-version
@@ -0,0 +1,122 @@
1
+ from __future__ import annotations
2
+
3
+ """
4
+ Custom helpers for task polling.
5
+
6
+ This module adds `Task.poll()` and `Task.apoll()` methods at runtime to the
7
+ generated `Task` model, without modifying generated code directly.
8
+
9
+ Usage:
10
+ task = client.tasks.get(task_id)
11
+ task = task.poll(client) # blocks until terminal state
12
+
13
+ # async
14
+ task = await async_client.tasks.get(task_id)
15
+ task = await task.apoll(async_client)
16
+ """
17
+
18
+ import time
19
+ import asyncio
20
+ from typing import Protocol, cast
21
+
22
+ from .._types import NOT_GIVEN, NotGiven
23
+ from .._client import Chunkr, AsyncChunkr
24
+ from ..types.task import Task as _Task
25
+ from .._exceptions import ChunkrError
26
+
27
+ TERMINAL_STATUSES = {"Succeeded", "Failed", "Cancelled"}
28
+
29
+
30
+ def _task_poll(
31
+ self: _Task,
32
+ client: Chunkr,
33
+ *,
34
+ interval: float = 0.5,
35
+ timeout: float = 600.0,
36
+ include_chunks: bool | NotGiven = NOT_GIVEN,
37
+ base64_urls: bool | NotGiven = NOT_GIVEN,
38
+ ) -> _Task:
39
+ """Poll the task until it reaches a terminal status.
40
+
41
+ Args:
42
+ client: Synchronous Chunkr client instance.
43
+ interval: Seconds to sleep between polls.
44
+ timeout: Maximum total seconds to wait before raising an error.
45
+ include_chunks: Whether to include chunks in the output response for each poll.
46
+ base64_urls: Whether to return base64 encoded URLs.
47
+ """
48
+ start_time = time.monotonic()
49
+ current: _Task = self
50
+
51
+ class _TasksGetProtocol(Protocol):
52
+ def get(
53
+ self,
54
+ task_id: str,
55
+ *,
56
+ base64_urls: bool | NotGiven = NOT_GIVEN,
57
+ include_chunks: bool | NotGiven = NOT_GIVEN,
58
+ ) -> _Task: ...
59
+
60
+ resource = cast(_TasksGetProtocol, client.tasks)
61
+
62
+ while current.status not in TERMINAL_STATUSES:
63
+ if time.monotonic() - start_time > timeout:
64
+ raise ChunkrError("Task polling timed out.")
65
+
66
+ if interval > 0:
67
+ time.sleep(interval)
68
+
69
+ current = resource.get(
70
+ current.task_id,
71
+ include_chunks=include_chunks,
72
+ base64_urls=base64_urls,
73
+ )
74
+
75
+ return current
76
+
77
+
78
+ async def _task_apoll(
79
+ self: _Task,
80
+ client: AsyncChunkr,
81
+ *,
82
+ interval: float = 0.5,
83
+ timeout: float = 600.0,
84
+ include_chunks: bool | NotGiven = NOT_GIVEN,
85
+ base64_urls: bool | NotGiven = NOT_GIVEN,
86
+ ) -> _Task:
87
+ """Async poll the task until it reaches a terminal status."""
88
+ start_time = time.monotonic()
89
+ current: _Task = self
90
+
91
+ class _AsyncTasksGetProtocol(Protocol):
92
+ async def get(
93
+ self,
94
+ task_id: str,
95
+ *,
96
+ base64_urls: bool | NotGiven = NOT_GIVEN,
97
+ include_chunks: bool | NotGiven = NOT_GIVEN,
98
+ ) -> _Task: ...
99
+
100
+ aresource = cast(_AsyncTasksGetProtocol, client.tasks)
101
+
102
+ while current.status not in TERMINAL_STATUSES:
103
+ if time.monotonic() - start_time > timeout:
104
+ raise ChunkrError("Task polling timed out.")
105
+
106
+ if interval > 0:
107
+ await asyncio.sleep(interval)
108
+
109
+ current = await aresource.get(
110
+ current.task_id,
111
+ include_chunks=include_chunks,
112
+ base64_urls=base64_urls,
113
+ )
114
+
115
+ return current
116
+
117
+
118
+ # Attach methods to the generated Task model
119
+ _Task.poll = _task_poll # type: ignore[attr-defined]
120
+ _Task.apoll = _task_apoll # type: ignore[attr-defined]
121
+
122
+