planvortex 0.8.0__tar.gz → 0.10.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 (109) hide show
  1. {planvortex-0.8.0 → planvortex-0.10.0}/CHANGELOG.md +91 -0
  2. {planvortex-0.8.0 → planvortex-0.10.0}/PKG-INFO +5 -5
  3. {planvortex-0.8.0 → planvortex-0.10.0}/README.md +4 -4
  4. {planvortex-0.8.0 → planvortex-0.10.0}/openapi/planvortex.openapi.json +1094 -103
  5. {planvortex-0.8.0 → planvortex-0.10.0}/pyproject.toml +1 -1
  6. {planvortex-0.8.0 → planvortex-0.10.0}/src/planvortex/__init__.py +1 -1
  7. {planvortex-0.8.0 → planvortex-0.10.0}/src/planvortex/_core/errors.py +18 -11
  8. {planvortex-0.8.0 → planvortex-0.10.0}/src/planvortex/_generated/models.py +413 -21
  9. {planvortex-0.8.0 → planvortex-0.10.0}/src/planvortex/_shapes.py +21 -5
  10. {planvortex-0.8.0 → planvortex-0.10.0}/src/planvortex/_version.py +1 -1
  11. {planvortex-0.8.0 → planvortex-0.10.0}/src/planvortex/resources/accounts.py +60 -1
  12. {planvortex-0.8.0 → planvortex-0.10.0}/src/planvortex/resources/ai_plans.py +88 -5
  13. {planvortex-0.8.0 → planvortex-0.10.0}/src/planvortex/resources/apps.py +15 -0
  14. {planvortex-0.8.0 → planvortex-0.10.0}/src/planvortex/resources/publications.py +22 -0
  15. {planvortex-0.8.0 → planvortex-0.10.0}/src/planvortex/resources_sync/accounts.py +60 -1
  16. {planvortex-0.8.0 → planvortex-0.10.0}/src/planvortex/resources_sync/ai_plans.py +88 -5
  17. {planvortex-0.8.0 → planvortex-0.10.0}/src/planvortex/resources_sync/apps.py +13 -0
  18. {planvortex-0.8.0 → planvortex-0.10.0}/src/planvortex/resources_sync/publications.py +22 -0
  19. {planvortex-0.8.0 → planvortex-0.10.0}/src/planvortex/types.py +118 -12
  20. {planvortex-0.8.0 → planvortex-0.10.0}/tests/test_accounts.py +24 -1
  21. {planvortex-0.8.0 → planvortex-0.10.0}/tests/test_ai_plans.py +93 -0
  22. {planvortex-0.8.0 → planvortex-0.10.0}/tests/test_apps.py +8 -0
  23. {planvortex-0.8.0 → planvortex-0.10.0}/tests/test_core.py +28 -0
  24. {planvortex-0.8.0 → planvortex-0.10.0}/tests/test_route_coverage.py +7 -4
  25. {planvortex-0.8.0 → planvortex-0.10.0}/tests/test_types.py +14 -0
  26. {planvortex-0.8.0 → planvortex-0.10.0}/.gitignore +0 -0
  27. {planvortex-0.8.0 → planvortex-0.10.0}/LICENSE +0 -0
  28. {planvortex-0.8.0 → planvortex-0.10.0}/scripts/build_docs.py +0 -0
  29. {planvortex-0.8.0 → planvortex-0.10.0}/scripts/check_packaging.py +0 -0
  30. {planvortex-0.8.0 → planvortex-0.10.0}/scripts/generate_models.py +0 -0
  31. {planvortex-0.8.0 → planvortex-0.10.0}/scripts/generate_sync.py +0 -0
  32. {planvortex-0.8.0 → planvortex-0.10.0}/scripts/route_coverage.py +0 -0
  33. {planvortex-0.8.0 → planvortex-0.10.0}/src/planvortex/_client.py +0 -0
  34. {planvortex-0.8.0 → planvortex-0.10.0}/src/planvortex/_client_sync.py +0 -0
  35. {planvortex-0.8.0 → planvortex-0.10.0}/src/planvortex/_core/__init__.py +0 -0
  36. {planvortex-0.8.0 → planvortex-0.10.0}/src/planvortex/_core/auth.py +0 -0
  37. {planvortex-0.8.0 → planvortex-0.10.0}/src/planvortex/_core/auth_sync.py +0 -0
  38. {planvortex-0.8.0 → planvortex-0.10.0}/src/planvortex/_core/files.py +0 -0
  39. {planvortex-0.8.0 → planvortex-0.10.0}/src/planvortex/_core/http.py +0 -0
  40. {planvortex-0.8.0 → planvortex-0.10.0}/src/planvortex/_core/http_sync.py +0 -0
  41. {planvortex-0.8.0 → planvortex-0.10.0}/src/planvortex/_core/pagination.py +0 -0
  42. {planvortex-0.8.0 → planvortex-0.10.0}/src/planvortex/_core/query.py +0 -0
  43. {planvortex-0.8.0 → planvortex-0.10.0}/src/planvortex/_core/transport.py +0 -0
  44. {planvortex-0.8.0 → planvortex-0.10.0}/src/planvortex/_generated/__init__.py +0 -0
  45. {planvortex-0.8.0 → planvortex-0.10.0}/src/planvortex/py.typed +0 -0
  46. {planvortex-0.8.0 → planvortex-0.10.0}/src/planvortex/resources/__init__.py +0 -0
  47. {planvortex-0.8.0 → planvortex-0.10.0}/src/planvortex/resources/base.py +0 -0
  48. {planvortex-0.8.0 → planvortex-0.10.0}/src/planvortex/resources/catalog.py +0 -0
  49. {planvortex-0.8.0 → planvortex-0.10.0}/src/planvortex/resources/clients.py +0 -0
  50. {planvortex-0.8.0 → planvortex-0.10.0}/src/planvortex/resources/comments.py +0 -0
  51. {planvortex-0.8.0 → planvortex-0.10.0}/src/planvortex/resources/contacts.py +0 -0
  52. {planvortex-0.8.0 → planvortex-0.10.0}/src/planvortex/resources/dashboard.py +0 -0
  53. {planvortex-0.8.0 → planvortex-0.10.0}/src/planvortex/resources/integrations.py +0 -0
  54. {planvortex-0.8.0 → planvortex-0.10.0}/src/planvortex/resources/messages.py +0 -0
  55. {planvortex-0.8.0 → planvortex-0.10.0}/src/planvortex/resources/organizations.py +0 -0
  56. {planvortex-0.8.0 → planvortex-0.10.0}/src/planvortex/resources/products.py +0 -0
  57. {planvortex-0.8.0 → planvortex-0.10.0}/src/planvortex/resources/uploads.py +0 -0
  58. {planvortex-0.8.0 → planvortex-0.10.0}/src/planvortex/resources_sync/__init__.py +0 -0
  59. {planvortex-0.8.0 → planvortex-0.10.0}/src/planvortex/resources_sync/base.py +0 -0
  60. {planvortex-0.8.0 → planvortex-0.10.0}/src/planvortex/resources_sync/catalog.py +0 -0
  61. {planvortex-0.8.0 → planvortex-0.10.0}/src/planvortex/resources_sync/clients.py +0 -0
  62. {planvortex-0.8.0 → planvortex-0.10.0}/src/planvortex/resources_sync/comments.py +0 -0
  63. {planvortex-0.8.0 → planvortex-0.10.0}/src/planvortex/resources_sync/contacts.py +0 -0
  64. {planvortex-0.8.0 → planvortex-0.10.0}/src/planvortex/resources_sync/dashboard.py +0 -0
  65. {planvortex-0.8.0 → planvortex-0.10.0}/src/planvortex/resources_sync/integrations.py +0 -0
  66. {planvortex-0.8.0 → planvortex-0.10.0}/src/planvortex/resources_sync/messages.py +0 -0
  67. {planvortex-0.8.0 → planvortex-0.10.0}/src/planvortex/resources_sync/organizations.py +0 -0
  68. {planvortex-0.8.0 → planvortex-0.10.0}/src/planvortex/resources_sync/products.py +0 -0
  69. {planvortex-0.8.0 → planvortex-0.10.0}/src/planvortex/resources_sync/uploads.py +0 -0
  70. {planvortex-0.8.0 → planvortex-0.10.0}/src/planvortex/webhooks.py +0 -0
  71. {planvortex-0.8.0 → planvortex-0.10.0}/tests/__init__.py +0 -0
  72. {planvortex-0.8.0 → planvortex-0.10.0}/tests/conftest.py +0 -0
  73. {planvortex-0.8.0 → planvortex-0.10.0}/tests/contrato.py +0 -0
  74. {planvortex-0.8.0 → planvortex-0.10.0}/tests/live/__init__.py +0 -0
  75. {planvortex-0.8.0 → planvortex-0.10.0}/tests/live/conftest.py +0 -0
  76. {planvortex-0.8.0 → planvortex-0.10.0}/tests/live/test_auth.py +0 -0
  77. {planvortex-0.8.0 → planvortex-0.10.0}/tests/live/test_catalog.py +0 -0
  78. {planvortex-0.8.0 → planvortex-0.10.0}/tests/live/test_connect_flow.py +0 -0
  79. {planvortex-0.8.0 → planvortex-0.10.0}/tests/live/test_errors.py +0 -0
  80. {planvortex-0.8.0 → planvortex-0.10.0}/tests/live/test_publish.py +0 -0
  81. {planvortex-0.8.0 → planvortex-0.10.0}/tests/live/test_read.py +0 -0
  82. {planvortex-0.8.0 → planvortex-0.10.0}/tests/test_catalog.py +0 -0
  83. {planvortex-0.8.0 → planvortex-0.10.0}/tests/test_client.py +0 -0
  84. {planvortex-0.8.0 → planvortex-0.10.0}/tests/test_clients.py +0 -0
  85. {planvortex-0.8.0 → planvortex-0.10.0}/tests/test_comments.py +0 -0
  86. {planvortex-0.8.0 → planvortex-0.10.0}/tests/test_contacts.py +0 -0
  87. {planvortex-0.8.0 → planvortex-0.10.0}/tests/test_dashboard.py +0 -0
  88. {planvortex-0.8.0 → planvortex-0.10.0}/tests/test_example_comments.py +0 -0
  89. {planvortex-0.8.0 → planvortex-0.10.0}/tests/test_example_connect.py +0 -0
  90. {planvortex-0.8.0 → planvortex-0.10.0}/tests/test_example_publish.py +0 -0
  91. {planvortex-0.8.0 → planvortex-0.10.0}/tests/test_example_schedule.py +0 -0
  92. {planvortex-0.8.0 → planvortex-0.10.0}/tests/test_example_webhooks.py +0 -0
  93. {planvortex-0.8.0 → planvortex-0.10.0}/tests/test_files.py +0 -0
  94. {planvortex-0.8.0 → planvortex-0.10.0}/tests/test_generate_models.py +0 -0
  95. {planvortex-0.8.0 → planvortex-0.10.0}/tests/test_generate_sync.py +0 -0
  96. {planvortex-0.8.0 → planvortex-0.10.0}/tests/test_integrations.py +0 -0
  97. {planvortex-0.8.0 → planvortex-0.10.0}/tests/test_messages.py +0 -0
  98. {planvortex-0.8.0 → planvortex-0.10.0}/tests/test_models.py +0 -0
  99. {planvortex-0.8.0 → planvortex-0.10.0}/tests/test_openapi_freshness.py +0 -0
  100. {planvortex-0.8.0 → planvortex-0.10.0}/tests/test_organizations.py +0 -0
  101. {planvortex-0.8.0 → planvortex-0.10.0}/tests/test_packaging.py +0 -0
  102. {planvortex-0.8.0 → planvortex-0.10.0}/tests/test_pagination.py +0 -0
  103. {planvortex-0.8.0 → planvortex-0.10.0}/tests/test_products.py +0 -0
  104. {planvortex-0.8.0 → planvortex-0.10.0}/tests/test_publications.py +0 -0
  105. {planvortex-0.8.0 → planvortex-0.10.0}/tests/test_query_parity.py +0 -0
  106. {planvortex-0.8.0 → planvortex-0.10.0}/tests/test_readme.py +0 -0
  107. {planvortex-0.8.0 → planvortex-0.10.0}/tests/test_shapes_parity.py +0 -0
  108. {planvortex-0.8.0 → planvortex-0.10.0}/tests/test_uploads.py +0 -0
  109. {planvortex-0.8.0 → planvortex-0.10.0}/tests/test_webhooks.py +0 -0
@@ -4,6 +4,97 @@ All notable changes to this package are documented here. The format follows
4
4
  [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to
5
5
  [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
6
 
7
+ ## [0.10.0] - 2026-09-24
8
+
9
+ Pinterest, the fourteenth network, reaches the package — and it is the first one where choosing
10
+ the account does not choose where the publication comes out. **A pin goes to a board**, and that is
11
+ a field no other network has. Nothing was removed and no signature moved: upgrading from `0.9.0`
12
+ needs no changes, and `MIGRATION.md` gains no entry. The new fields are optional for the other
13
+ thirteen networks.
14
+
15
+ **`PublishableNetwork` is a closed `Literal` written by hand, and it went red on regeneration** —
16
+ which is how it is meant to find out. Pinterest is also the first network that enters
17
+ `PUBLISHABLE_NETWORKS` and **not** `COMMENT_NETWORKS`, so it is the first real proof that the two
18
+ lists are independent.
19
+
20
+ ### Added
21
+
22
+ - **`pv.accounts.destinations(id_organization, id_account)`** and
23
+ **`pv.accounts.destination(id_organization, id_account, id_destination)`**, over
24
+ `GET /organizations/{id}/accounts/{id}/destinations[/{id}]`: an account's Pinterest boards, and
25
+ one board with its sections. Every other network answers 992 — the account itself is where its
26
+ publications go. Both take `refresh=True` to skip the server's short cache, for a board created
27
+ a moment ago; not on every call, because all of PlanVortex's Pinterest traffic leaves through one
28
+ application. Also on the synchronous client.
29
+ - **`"pinterest"` in `PublishableNetwork` and `PUBLISHABLE_NETWORKS`**, and **`destination` and
30
+ `link` on `PublicationInput`.** On Pinterest the board is **required**, and leaving it out does
31
+ not raise: the publication is created in `withErrors` with code 987 and is never attempted.
32
+ `destination["id"]` is **always a string** — Pinterest's ids are long integers. `link` is where
33
+ the pin takes whoever clicks it: it goes in its own field, not inside `text`. On every other
34
+ network both fields are deleted on save. Ask `destinations` and `link` in
35
+ `catalog.social_capabilities()` rather than keeping a list of which network has which.
36
+ - **`destinations` on `AiPlanCreateRequest` and `AiPlan`, and `options["link"]`.** A plan with a
37
+ Pinterest account needs that account's board, one entry per account; without it
38
+ `ai_plans.create` raises **2118**, listing every account that fails. A plan that would leave pins
39
+ without an image is refused with **2119** before a single credit is spent, and an image that
40
+ fails halfway through the generation shows up as a **922** in `warnings`, with the publication
41
+ that was left without it.
42
+ - Types `Destination`, `PublicationDestination` and `AiPlanDestination`.
43
+
44
+ ### Fixed
45
+
46
+ - **Pinterest's error codes (987-996) arrived outside every family**, the third time a network's
47
+ codes were born above the ceiling of the publications range (after 978 and 980). They are now
48
+ `PublicationError`. The one that matters most is **991**: Pinterest throttling the application,
49
+ sent as HTTP 429 with `Retry-After` — the answer is to wait, and `error.retry_after` says how long.
50
+ - **547, 548 and 716 were unclassified too.** 547 (a client app's identifier cannot change) and
51
+ 548 (rotating the secret failed, the method that came with `0.9.0`) are now `AuthError`, and 716
52
+ (another process is renewing the Bluesky session; retry) is `AccountError`.
53
+ - A test now checks that **every** error code named in the specification's error tables falls into
54
+ some family, so the next network cannot repeat this without the build going red.
55
+ - The prose that counts networks said "nine of the eleven" and "eleven and not twelve" in places;
56
+ it now says fourteen, thirteen of which publish.
57
+
58
+ ## [0.9.0] - 2026-09-17
59
+
60
+ **Which AI plan worked?** The server can now answer it, and so can this package:
61
+ `ai_plans.results()` returns what every plan achieved with what it published, the aggregate per
62
+ template and the total.
63
+
64
+ Nothing was removed and no signature moved: upgrading from `0.8.0` needs no changes, and
65
+ `MIGRATION.md` gains no entry.
66
+
67
+ ### Added
68
+
69
+ - **`pv.ai_plans.results(id_client, id_organization, ...)`**, over
70
+ `GET /clients/{id}/organizations/{id}/ai_plans/results`, in both clients. Four things about it
71
+ are not obvious, and all four are in its docstring:
72
+ - **The range filters on the plan's week** (`week_start`), not on when it was created. A plan
73
+ created today for next week has published nothing yet.
74
+ - **The ranking is interactions per _measured_ publication**, not the total — the total rewards
75
+ the plan with seven accounts even when each post does half as well — and only plans with
76
+ `ranked: True` (at least three measured publications, or all of them) compete in it.
77
+ - **`social_network` recomputes every plan with only its publications on those networks**,
78
+ which is what makes plans on different networks comparable. With that filter
79
+ `credits_per_engagement` is absent: the cost belongs to the whole plan.
80
+ - **It is not a `Page`.** Besides the page it carries `totals` and `by_template`, which do not
81
+ depend on the page, so it comes back whole.
82
+ - **Being first is not being good.** Every plan, group and the dashboard block carry
83
+ `engagement_vs_average`: the plan's interactions per post over what your usual posts get on the
84
+ same networks (`expected_engagement_per_publication`), where **1 is your average**. The ranking
85
+ still orders by interactions per post, so the first plan can be below 1.
86
+ - Types `AiPlanResult`, `AiPlanResults`, `AiPlanResultsGroup`, `AiPlanResultsTemplateGroup` and
87
+ the closed `AiPlanResultsSort`.
88
+ - **`Dashboard["ai_plan_results"]`** and its `available_blocks["ai_plan_results"]`: the three best
89
+ plans of the range, for the home screen. It needs both `ai_plans:read` and
90
+ `publication_stats:read`, and unlike `ai_plans.results()` it covers the organization **and its
91
+ children**, so each row carries its `id_organization`.
92
+ - **`pv.apps.rotate_secret(id_client, id_app)`**, over `POST /clients/{id}/apps/{id}/secret`. The
93
+ route reached the specification before this package, and regenerating the models is what turned
94
+ `tests/test_route_coverage.py` red — which is the test doing its job. **The previous secret stops
95
+ working the moment it answers, and the webhook signature changes with it.** Like `secret()`, it
96
+ needs a user token.
97
+
7
98
  ## [0.8.0] - 2026-09-13
8
99
 
9
100
  Slack, the thirteenth network, reaches the package — and here it arrives the way it should: **three
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: planvortex
3
- Version: 0.8.0
3
+ Version: 0.10.0
4
4
  Summary: Official Python client for the PlanVortex API
5
5
  Project-URL: Homepage, https://planvortex.com/en/developers
6
6
  Project-URL: Documentation, https://taliasoftworks.github.io/PlanVortexPython/
@@ -242,11 +242,11 @@ memorising numbers:
242
242
 
243
243
  | Codes | Family | Exception |
244
244
  |---|---|---|
245
- | 500-546 | `auth` | `AuthError` |
245
+ | 500-548 | `auth` | `AuthError` |
246
246
  | 601-612 | `user` | `UserError` |
247
- | 700-715 | `account` | `AccountError` |
247
+ | 700-716 | `account` | `AccountError` |
248
248
  | 800-810 | `file` | `FileError` |
249
- | 900-986 | `publication` | `PublicationError` |
249
+ | 900-996 | `publication` | `PublicationError` |
250
250
  | 1000-1003 | `general` | `PlanVortexError` |
251
251
  | 1100-1111 | `organization` | `OrganizationError` |
252
252
  | 1200-1207 | `role` | `PlanVortexError` |
@@ -348,7 +348,7 @@ you missed.
348
348
  · `pv.comments` · `pv.messages` · `pv.contacts` · `pv.products` · `pv.integrations` · `pv.ai_plans`
349
349
  · `pv.dashboard` · `pv.apps`
350
350
 
351
- That is **113 of the 113 operations** the specification documents — everything except the 19 routes
351
+ That is **117 of the 117 operations** the specification documents — everything except the 19 routes
352
352
  of roles and invitations, which are out of scope. A script walks the OpenAPI bundle on every test
353
353
  run and fails if a route is left without a method, so the sentence above stays true.
354
354
 
@@ -212,11 +212,11 @@ memorising numbers:
212
212
 
213
213
  | Codes | Family | Exception |
214
214
  |---|---|---|
215
- | 500-546 | `auth` | `AuthError` |
215
+ | 500-548 | `auth` | `AuthError` |
216
216
  | 601-612 | `user` | `UserError` |
217
- | 700-715 | `account` | `AccountError` |
217
+ | 700-716 | `account` | `AccountError` |
218
218
  | 800-810 | `file` | `FileError` |
219
- | 900-986 | `publication` | `PublicationError` |
219
+ | 900-996 | `publication` | `PublicationError` |
220
220
  | 1000-1003 | `general` | `PlanVortexError` |
221
221
  | 1100-1111 | `organization` | `OrganizationError` |
222
222
  | 1200-1207 | `role` | `PlanVortexError` |
@@ -318,7 +318,7 @@ you missed.
318
318
  · `pv.comments` · `pv.messages` · `pv.contacts` · `pv.products` · `pv.integrations` · `pv.ai_plans`
319
319
  · `pv.dashboard` · `pv.apps`
320
320
 
321
- That is **113 of the 113 operations** the specification documents — everything except the 19 routes
321
+ That is **117 of the 117 operations** the specification documents — everything except the 19 routes
322
322
  of roles and invitations, which are out of scope. A script walks the OpenAPI bundle on every test
323
323
  run and fails if a route is left without a method, so the sentence above stays true.
324
324