qodev-apollo-api 0.3.1__tar.gz → 0.3.2__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 (26) hide show
  1. {qodev_apollo_api-0.3.1 → qodev_apollo_api-0.3.2}/CHANGELOG.md +6 -0
  2. {qodev_apollo_api-0.3.1 → qodev_apollo_api-0.3.2}/PKG-INFO +1 -1
  3. {qodev_apollo_api-0.3.1 → qodev_apollo_api-0.3.2}/pyproject.toml +1 -1
  4. {qodev_apollo_api-0.3.1 → qodev_apollo_api-0.3.2}/src/qodev_apollo_api/client.py +6 -1
  5. {qodev_apollo_api-0.3.1 → qodev_apollo_api-0.3.2}/tests/test_client.py +23 -0
  6. {qodev_apollo_api-0.3.1 → qodev_apollo_api-0.3.2}/tests/test_models.py +3 -0
  7. {qodev_apollo_api-0.3.1 → qodev_apollo_api-0.3.2}/uv.lock +1 -1
  8. {qodev_apollo_api-0.3.1 → qodev_apollo_api-0.3.2}/.github/workflows/ci.yml +0 -0
  9. {qodev_apollo_api-0.3.1 → qodev_apollo_api-0.3.2}/.github/workflows/publish.yml +0 -0
  10. {qodev_apollo_api-0.3.1 → qodev_apollo_api-0.3.2}/.gitignore +0 -0
  11. {qodev_apollo_api-0.3.1 → qodev_apollo_api-0.3.2}/.pre-commit-config.yaml +0 -0
  12. {qodev_apollo_api-0.3.1 → qodev_apollo_api-0.3.2}/CLAUDE.md +0 -0
  13. {qodev_apollo_api-0.3.1 → qodev_apollo_api-0.3.2}/LICENSE +0 -0
  14. {qodev_apollo_api-0.3.1 → qodev_apollo_api-0.3.2}/Makefile +0 -0
  15. {qodev_apollo_api-0.3.1 → qodev_apollo_api-0.3.2}/README.md +0 -0
  16. {qodev_apollo_api-0.3.1 → qodev_apollo_api-0.3.2}/src/qodev_apollo_api/__init__.py +0 -0
  17. {qodev_apollo_api-0.3.1 → qodev_apollo_api-0.3.2}/src/qodev_apollo_api/exceptions.py +0 -0
  18. {qodev_apollo_api-0.3.1 → qodev_apollo_api-0.3.2}/src/qodev_apollo_api/models.py +0 -0
  19. {qodev_apollo_api-0.3.1 → qodev_apollo_api-0.3.2}/src/qodev_apollo_api/py.typed +0 -0
  20. {qodev_apollo_api-0.3.1 → qodev_apollo_api-0.3.2}/src/qodev_apollo_api/utils.py +0 -0
  21. {qodev_apollo_api-0.3.1 → qodev_apollo_api-0.3.2}/tests/__init__.py +0 -0
  22. {qodev_apollo_api-0.3.1 → qodev_apollo_api-0.3.2}/tests/integration/__init__.py +0 -0
  23. {qodev_apollo_api-0.3.1 → qodev_apollo_api-0.3.2}/tests/integration/validate_all_models.py +0 -0
  24. {qodev_apollo_api-0.3.1 → qodev_apollo_api-0.3.2}/tests/integration/validate_email_task_flow.py +0 -0
  25. {qodev_apollo_api-0.3.1 → qodev_apollo_api-0.3.2}/tests/test_exceptions.py +0 -0
  26. {qodev_apollo_api-0.3.1 → qodev_apollo_api-0.3.2}/tests/test_utils.py +0 -0
@@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.3.2] - 2026-07-08
11
+
12
+ ### Fixed
13
+
14
+ - `search_tasks()` could raise `AttributeError` while *handling* an unparseable row: the skip path called `raw.get("id")` assuming `raw` was a dict, so a non-dict row (e.g. a stray `null`) turned the intended "skip one bad row" into a whole-page crash. The id lookup is now guarded (`isinstance(raw, dict)`), and iteration tolerates a null `tasks` value (`result.get("tasks") or []`).
15
+
10
16
  ## [0.3.1] - 2026-07-08
11
17
 
12
18
  ### Changed
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: qodev-apollo-api
3
- Version: 0.3.1
3
+ Version: 0.3.2
4
4
  Summary: Async Python client for Apollo.io CRM API
5
5
  Project-URL: Homepage, https://github.com/qodevai/apollo-api
6
6
  Project-URL: Repository, https://github.com/qodevai/apollo-api
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "qodev-apollo-api"
3
- version = "0.3.1"
3
+ version = "0.3.2"
4
4
  description = "Async Python client for Apollo.io CRM API"
5
5
  readme = "README.md"
6
6
  authors = [
@@ -759,7 +759,12 @@ class ApolloClient:
759
759
  result = await self._post("/tasks/search", data)
760
760
 
761
761
  tasks: list[Task] = []
762
- for raw in result.get("tasks", []):
762
+ for raw in result.get("tasks") or []:
763
+ if not isinstance(raw, dict):
764
+ # A non-dict row (e.g. a stray null) would make resolve_task raise
765
+ # AttributeError, not ValidationError — skip it before we get there.
766
+ logger.warning("Skipping non-dict task row: %r", raw)
767
+ continue
763
768
  try:
764
769
  tasks.append(resolve_task(raw))
765
770
  except ValidationError:
@@ -338,6 +338,29 @@ async def test_search_tasks_skips_unparseable_row(client: ApolloClient):
338
338
  assert [t.id for t in result.items] == ["t2"]
339
339
 
340
340
 
341
+ async def test_search_tasks_skips_non_dict_row(client: ApolloClient):
342
+ """A non-dict row (e.g. a stray null) is skipped without raising AttributeError."""
343
+ client._client.request.return_value = _make_response(
344
+ {
345
+ "tasks": [None, "oops", {"id": "t2", "type": "call"}],
346
+ "pagination": {"total_entries": 3},
347
+ }
348
+ )
349
+
350
+ result = await client.search_tasks()
351
+
352
+ assert [t.id for t in result.items] == ["t2"]
353
+
354
+
355
+ async def test_search_tasks_null_tasks_key(client: ApolloClient):
356
+ """A null `tasks` value doesn't crash iteration."""
357
+ client._client.request.return_value = _make_response({"tasks": None, "pagination": {}})
358
+
359
+ result = await client.search_tasks()
360
+
361
+ assert result.items == []
362
+
363
+
341
364
  async def test_search_tasks_with_sort(client: ApolloClient):
342
365
  """Test search_tasks with sort parameter generates multi_sort payload."""
343
366
  client._client.request.return_value = _make_response(
@@ -899,6 +899,9 @@ def test_resolve_task_preserves_unmodelled_status():
899
899
  assert result.status == "skipped"
900
900
  # comparison against the known-value enum still works via StrEnum equality
901
901
  assert result.status != TaskStatus.SCHEDULED
902
+ # ...and a modelled status still compares equal to its enum member
903
+ scheduled = resolve_task({"id": "2", "type": "linkedin_step_connect", "status": "scheduled"})
904
+ assert scheduled.status == TaskStatus.SCHEDULED
902
905
 
903
906
 
904
907
  def test_resolve_task_preserves_unmodelled_priority():
@@ -407,7 +407,7 @@ wheels = [
407
407
 
408
408
  [[package]]
409
409
  name = "qodev-apollo-api"
410
- version = "0.3.1"
410
+ version = "0.3.2"
411
411
  source = { editable = "." }
412
412
  dependencies = [
413
413
  { name = "httpx" },