chunkr-ai 0.1.0a3__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 (92) hide show
  1. {chunkr_ai-0.1.0a3 → 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.0a3 → chunkr_ai-0.1.0a4}/CHANGELOG.md +9 -0
  4. {chunkr_ai-0.1.0a3 → chunkr_ai-0.1.0a4}/PKG-INFO +1 -1
  5. {chunkr_ai-0.1.0a3 → chunkr_ai-0.1.0a4}/api.md +1 -1
  6. {chunkr_ai-0.1.0a3 → chunkr_ai-0.1.0a4}/pyproject.toml +1 -1
  7. {chunkr_ai-0.1.0a3 → chunkr_ai-0.1.0a4}/src/chunkr_ai/__init__.py +3 -0
  8. {chunkr_ai-0.1.0a3 → chunkr_ai-0.1.0a4}/src/chunkr_ai/_version.py +1 -1
  9. chunkr_ai-0.1.0a4/src/chunkr_ai/lib/tasks_poll.py +122 -0
  10. {chunkr_ai-0.1.0a3 → chunkr_ai-0.1.0a4}/src/chunkr_ai/types/__init__.py +1 -1
  11. chunkr_ai-0.1.0a3/src/chunkr_ai/types/files_page_response.py → chunkr_ai-0.1.0a4/src/chunkr_ai/types/files_list_response.py +2 -2
  12. chunkr_ai-0.1.0a4/tests/test_tasks_poll.py +62 -0
  13. chunkr_ai-0.1.0a3/.release-please-manifest.json +0 -3
  14. {chunkr_ai-0.1.0a3 → chunkr_ai-0.1.0a4}/CONTRIBUTING.md +0 -0
  15. {chunkr_ai-0.1.0a3 → chunkr_ai-0.1.0a4}/LICENSE +0 -0
  16. {chunkr_ai-0.1.0a3 → chunkr_ai-0.1.0a4}/README.md +0 -0
  17. {chunkr_ai-0.1.0a3 → chunkr_ai-0.1.0a4}/SECURITY.md +0 -0
  18. {chunkr_ai-0.1.0a3 → chunkr_ai-0.1.0a4}/bin/check-release-environment +0 -0
  19. {chunkr_ai-0.1.0a3 → chunkr_ai-0.1.0a4}/bin/publish-pypi +0 -0
  20. {chunkr_ai-0.1.0a3 → chunkr_ai-0.1.0a4}/examples/.keep +0 -0
  21. {chunkr_ai-0.1.0a3 → chunkr_ai-0.1.0a4}/mypy.ini +0 -0
  22. {chunkr_ai-0.1.0a3 → chunkr_ai-0.1.0a4}/noxfile.py +0 -0
  23. {chunkr_ai-0.1.0a3 → chunkr_ai-0.1.0a4}/release-please-config.json +0 -0
  24. {chunkr_ai-0.1.0a3 → chunkr_ai-0.1.0a4}/requirements-dev.lock +0 -0
  25. {chunkr_ai-0.1.0a3 → chunkr_ai-0.1.0a4}/requirements.lock +0 -0
  26. {chunkr_ai-0.1.0a3 → chunkr_ai-0.1.0a4}/src/chunkr/lib/.keep +0 -0
  27. {chunkr_ai-0.1.0a3 → chunkr_ai-0.1.0a4}/src/chunkr_ai/_base_client.py +0 -0
  28. {chunkr_ai-0.1.0a3 → chunkr_ai-0.1.0a4}/src/chunkr_ai/_client.py +0 -0
  29. {chunkr_ai-0.1.0a3 → chunkr_ai-0.1.0a4}/src/chunkr_ai/_compat.py +0 -0
  30. {chunkr_ai-0.1.0a3 → chunkr_ai-0.1.0a4}/src/chunkr_ai/_constants.py +0 -0
  31. {chunkr_ai-0.1.0a3 → chunkr_ai-0.1.0a4}/src/chunkr_ai/_exceptions.py +0 -0
  32. {chunkr_ai-0.1.0a3 → chunkr_ai-0.1.0a4}/src/chunkr_ai/_files.py +0 -0
  33. {chunkr_ai-0.1.0a3 → chunkr_ai-0.1.0a4}/src/chunkr_ai/_models.py +0 -0
  34. {chunkr_ai-0.1.0a3 → chunkr_ai-0.1.0a4}/src/chunkr_ai/_qs.py +0 -0
  35. {chunkr_ai-0.1.0a3 → chunkr_ai-0.1.0a4}/src/chunkr_ai/_resource.py +0 -0
  36. {chunkr_ai-0.1.0a3 → chunkr_ai-0.1.0a4}/src/chunkr_ai/_response.py +0 -0
  37. {chunkr_ai-0.1.0a3 → chunkr_ai-0.1.0a4}/src/chunkr_ai/_streaming.py +0 -0
  38. {chunkr_ai-0.1.0a3 → chunkr_ai-0.1.0a4}/src/chunkr_ai/_types.py +0 -0
  39. {chunkr_ai-0.1.0a3 → chunkr_ai-0.1.0a4}/src/chunkr_ai/_utils/__init__.py +0 -0
  40. {chunkr_ai-0.1.0a3 → chunkr_ai-0.1.0a4}/src/chunkr_ai/_utils/_logs.py +0 -0
  41. {chunkr_ai-0.1.0a3 → chunkr_ai-0.1.0a4}/src/chunkr_ai/_utils/_proxy.py +0 -0
  42. {chunkr_ai-0.1.0a3 → chunkr_ai-0.1.0a4}/src/chunkr_ai/_utils/_reflection.py +0 -0
  43. {chunkr_ai-0.1.0a3 → chunkr_ai-0.1.0a4}/src/chunkr_ai/_utils/_resources_proxy.py +0 -0
  44. {chunkr_ai-0.1.0a3 → chunkr_ai-0.1.0a4}/src/chunkr_ai/_utils/_streams.py +0 -0
  45. {chunkr_ai-0.1.0a3 → chunkr_ai-0.1.0a4}/src/chunkr_ai/_utils/_sync.py +0 -0
  46. {chunkr_ai-0.1.0a3 → chunkr_ai-0.1.0a4}/src/chunkr_ai/_utils/_transform.py +0 -0
  47. {chunkr_ai-0.1.0a3 → chunkr_ai-0.1.0a4}/src/chunkr_ai/_utils/_typing.py +0 -0
  48. {chunkr_ai-0.1.0a3 → chunkr_ai-0.1.0a4}/src/chunkr_ai/_utils/_utils.py +0 -0
  49. {chunkr_ai-0.1.0a3 → chunkr_ai-0.1.0a4}/src/chunkr_ai/lib/.keep +0 -0
  50. {chunkr_ai-0.1.0a3 → chunkr_ai-0.1.0a4}/src/chunkr_ai/pagination.py +0 -0
  51. {chunkr_ai-0.1.0a3 → chunkr_ai-0.1.0a4}/src/chunkr_ai/py.typed +0 -0
  52. {chunkr_ai-0.1.0a3 → chunkr_ai-0.1.0a4}/src/chunkr_ai/resources/__init__.py +0 -0
  53. {chunkr_ai-0.1.0a3 → chunkr_ai-0.1.0a4}/src/chunkr_ai/resources/files.py +0 -0
  54. {chunkr_ai-0.1.0a3 → chunkr_ai-0.1.0a4}/src/chunkr_ai/resources/health.py +0 -0
  55. {chunkr_ai-0.1.0a3 → chunkr_ai-0.1.0a4}/src/chunkr_ai/resources/tasks/__init__.py +0 -0
  56. {chunkr_ai-0.1.0a3 → chunkr_ai-0.1.0a4}/src/chunkr_ai/resources/tasks/parse.py +0 -0
  57. {chunkr_ai-0.1.0a3 → chunkr_ai-0.1.0a4}/src/chunkr_ai/resources/tasks/tasks.py +0 -0
  58. {chunkr_ai-0.1.0a3 → chunkr_ai-0.1.0a4}/src/chunkr_ai/types/delete.py +0 -0
  59. {chunkr_ai-0.1.0a3 → chunkr_ai-0.1.0a4}/src/chunkr_ai/types/file.py +0 -0
  60. {chunkr_ai-0.1.0a3 → chunkr_ai-0.1.0a4}/src/chunkr_ai/types/file_create_params.py +0 -0
  61. {chunkr_ai-0.1.0a3 → chunkr_ai-0.1.0a4}/src/chunkr_ai/types/file_list_params.py +0 -0
  62. {chunkr_ai-0.1.0a3 → chunkr_ai-0.1.0a4}/src/chunkr_ai/types/file_url.py +0 -0
  63. {chunkr_ai-0.1.0a3 → chunkr_ai-0.1.0a4}/src/chunkr_ai/types/file_url_params.py +0 -0
  64. {chunkr_ai-0.1.0a3 → chunkr_ai-0.1.0a4}/src/chunkr_ai/types/health_check_response.py +0 -0
  65. {chunkr_ai-0.1.0a3 → chunkr_ai-0.1.0a4}/src/chunkr_ai/types/task.py +0 -0
  66. {chunkr_ai-0.1.0a3 → chunkr_ai-0.1.0a4}/src/chunkr_ai/types/task_get_params.py +0 -0
  67. {chunkr_ai-0.1.0a3 → chunkr_ai-0.1.0a4}/src/chunkr_ai/types/task_list_params.py +0 -0
  68. {chunkr_ai-0.1.0a3 → chunkr_ai-0.1.0a4}/src/chunkr_ai/types/tasks/__init__.py +0 -0
  69. {chunkr_ai-0.1.0a3 → chunkr_ai-0.1.0a4}/src/chunkr_ai/types/tasks/parse_create_params.py +0 -0
  70. {chunkr_ai-0.1.0a3 → chunkr_ai-0.1.0a4}/src/chunkr_ai/types/tasks/parse_update_params.py +0 -0
  71. {chunkr_ai-0.1.0a3 → chunkr_ai-0.1.0a4}/tests/__init__.py +0 -0
  72. {chunkr_ai-0.1.0a3 → chunkr_ai-0.1.0a4}/tests/api_resources/__init__.py +0 -0
  73. {chunkr_ai-0.1.0a3 → chunkr_ai-0.1.0a4}/tests/api_resources/tasks/__init__.py +0 -0
  74. {chunkr_ai-0.1.0a3 → chunkr_ai-0.1.0a4}/tests/api_resources/tasks/test_parse.py +0 -0
  75. {chunkr_ai-0.1.0a3 → chunkr_ai-0.1.0a4}/tests/api_resources/test_files.py +0 -0
  76. {chunkr_ai-0.1.0a3 → chunkr_ai-0.1.0a4}/tests/api_resources/test_health.py +0 -0
  77. {chunkr_ai-0.1.0a3 → chunkr_ai-0.1.0a4}/tests/api_resources/test_tasks.py +0 -0
  78. {chunkr_ai-0.1.0a3 → chunkr_ai-0.1.0a4}/tests/conftest.py +0 -0
  79. {chunkr_ai-0.1.0a3 → chunkr_ai-0.1.0a4}/tests/sample_file.txt +0 -0
  80. {chunkr_ai-0.1.0a3 → chunkr_ai-0.1.0a4}/tests/test_client.py +0 -0
  81. {chunkr_ai-0.1.0a3 → chunkr_ai-0.1.0a4}/tests/test_deepcopy.py +0 -0
  82. {chunkr_ai-0.1.0a3 → chunkr_ai-0.1.0a4}/tests/test_extract_files.py +0 -0
  83. {chunkr_ai-0.1.0a3 → chunkr_ai-0.1.0a4}/tests/test_files.py +0 -0
  84. {chunkr_ai-0.1.0a3 → chunkr_ai-0.1.0a4}/tests/test_models.py +0 -0
  85. {chunkr_ai-0.1.0a3 → chunkr_ai-0.1.0a4}/tests/test_qs.py +0 -0
  86. {chunkr_ai-0.1.0a3 → chunkr_ai-0.1.0a4}/tests/test_required_args.py +0 -0
  87. {chunkr_ai-0.1.0a3 → chunkr_ai-0.1.0a4}/tests/test_response.py +0 -0
  88. {chunkr_ai-0.1.0a3 → chunkr_ai-0.1.0a4}/tests/test_streaming.py +0 -0
  89. {chunkr_ai-0.1.0a3 → chunkr_ai-0.1.0a4}/tests/test_transform.py +0 -0
  90. {chunkr_ai-0.1.0a3 → chunkr_ai-0.1.0a4}/tests/test_utils/test_proxy.py +0 -0
  91. {chunkr_ai-0.1.0a3 → chunkr_ai-0.1.0a4}/tests/test_utils/test_typing.py +0 -0
  92. {chunkr_ai-0.1.0a3 → 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,14 @@
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
+
3
12
  ## 0.1.0-alpha.3 (2025-08-09)
4
13
 
5
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)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: chunkr-ai
3
- Version: 0.1.0a3
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
@@ -25,7 +25,7 @@ Methods:
25
25
  Types:
26
26
 
27
27
  ```python
28
- from chunkr_ai.types import Delete, File, FilesPageResponse, FileURL
28
+ from chunkr_ai.types import Delete, File, FilesListResponse, FileURL
29
29
  ```
30
30
 
31
31
  Methods:
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "chunkr-ai"
3
- version = "0.1.0-alpha.3"
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()
@@ -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.3" # 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
+
@@ -11,5 +11,5 @@ from .task_get_params import TaskGetParams as TaskGetParams
11
11
  from .file_list_params import FileListParams as FileListParams
12
12
  from .task_list_params import TaskListParams as TaskListParams
13
13
  from .file_create_params import FileCreateParams as FileCreateParams
14
- from .files_page_response import FilesPageResponse as FilesPageResponse
14
+ from .files_list_response import FilesListResponse as FilesListResponse
15
15
  from .health_check_response import HealthCheckResponse as HealthCheckResponse
@@ -6,10 +6,10 @@ from datetime import datetime
6
6
  from .file import File
7
7
  from .._models import BaseModel
8
8
 
9
- __all__ = ["FilesPageResponse"]
9
+ __all__ = ["FilesListResponse"]
10
10
 
11
11
 
12
- class FilesPageResponse(BaseModel):
12
+ class FilesListResponse(BaseModel):
13
13
  files: List[File]
14
14
  """List of files"""
15
15
 
@@ -0,0 +1,62 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import Any, List, cast
4
+ from datetime import datetime, timezone
5
+
6
+ from chunkr_ai import Chunkr, AsyncChunkr
7
+ from chunkr_ai.types.task import Task
8
+
9
+
10
+ def _mk_task(status: str) -> Task:
11
+ return Task.construct(
12
+ configuration={
13
+ "chunk_processing": {},
14
+ "error_handling": "Fail",
15
+ "llm_processing": {},
16
+ "ocr_strategy": "All",
17
+ "segment_processing": {},
18
+ "segmentation_strategy": "Page",
19
+ },
20
+ created_at=datetime.now(timezone.utc),
21
+ message="",
22
+ status=status,
23
+ task_id="task_123",
24
+ )
25
+
26
+
27
+ class _TasksStub:
28
+ def __init__(self, responses: List[Task]) -> None:
29
+ self._responses = responses
30
+
31
+ def get(self, task_id: str, *, base64_urls: Any = None, include_chunks: Any = None) -> Task: # noqa: ARG002
32
+ return self._responses.pop(0)
33
+
34
+
35
+ class _AsyncTasksStub:
36
+ def __init__(self, responses: List[Task]) -> None:
37
+ self._responses = responses
38
+
39
+ async def get(self, task_id: str, *, base64_urls: Any = None, include_chunks: Any = None) -> Task: # noqa: ARG002
40
+ return self._responses.pop(0)
41
+
42
+
43
+ def test_poll_reaches_terminal_state() -> None:
44
+ client = Chunkr(base_url="http://127.0.0.1:4010", api_key="key", _strict_response_validation=True)
45
+
46
+ initial = _mk_task("Starting")
47
+ client.tasks = _TasksStub([_mk_task("Processing"), _mk_task("Succeeded")]) # type: ignore[assignment]
48
+
49
+ # avoid static type errors for monkey-patched method
50
+ final = cast(Any, initial).poll(client, interval=0.0, timeout=2.0)
51
+ assert final.status == "Succeeded"
52
+
53
+ async def test_apoll_reaches_terminal_state() -> None:
54
+ client = AsyncChunkr(base_url="http://127.0.0.1:4010", api_key="key", _strict_response_validation=True)
55
+
56
+ initial = _mk_task("Starting")
57
+ client.tasks = _AsyncTasksStub([_mk_task("Processing"), _mk_task("Succeeded")]) # type: ignore[assignment]
58
+
59
+ final = await cast(Any, initial).apoll(client, interval=0.0, timeout=2.0)
60
+ assert final.status == "Succeeded"
61
+
62
+
@@ -1,3 +0,0 @@
1
- {
2
- ".": "0.1.0-alpha.3"
3
- }
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes