planvortex 0.7.0__tar.gz → 0.9.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.7.0 → planvortex-0.9.0}/CHANGELOG.md +81 -0
  2. {planvortex-0.7.0 → planvortex-0.9.0}/PKG-INFO +3 -3
  3. {planvortex-0.7.0 → planvortex-0.9.0}/README.md +2 -2
  4. {planvortex-0.7.0 → planvortex-0.9.0}/openapi/planvortex.openapi.json +3198 -142
  5. {planvortex-0.7.0 → planvortex-0.9.0}/pyproject.toml +1 -1
  6. {planvortex-0.7.0 → planvortex-0.9.0}/src/planvortex/__init__.py +1 -1
  7. {planvortex-0.7.0 → planvortex-0.9.0}/src/planvortex/_core/errors.py +6 -4
  8. {planvortex-0.7.0 → planvortex-0.9.0}/src/planvortex/_generated/models.py +245 -12
  9. {planvortex-0.7.0 → planvortex-0.9.0}/src/planvortex/_shapes.py +4 -3
  10. {planvortex-0.7.0 → planvortex-0.9.0}/src/planvortex/_version.py +1 -1
  11. {planvortex-0.7.0 → planvortex-0.9.0}/src/planvortex/resources/accounts.py +7 -0
  12. {planvortex-0.7.0 → planvortex-0.9.0}/src/planvortex/resources/ai_plans.py +61 -2
  13. {planvortex-0.7.0 → planvortex-0.9.0}/src/planvortex/resources/apps.py +15 -0
  14. {planvortex-0.7.0 → planvortex-0.9.0}/src/planvortex/resources_sync/accounts.py +7 -0
  15. {planvortex-0.7.0 → planvortex-0.9.0}/src/planvortex/resources_sync/ai_plans.py +61 -2
  16. {planvortex-0.7.0 → planvortex-0.9.0}/src/planvortex/resources_sync/apps.py +13 -0
  17. {planvortex-0.7.0 → planvortex-0.9.0}/src/planvortex/types.py +59 -6
  18. {planvortex-0.7.0 → planvortex-0.9.0}/tests/test_ai_plans.py +93 -0
  19. {planvortex-0.7.0 → planvortex-0.9.0}/tests/test_apps.py +8 -0
  20. {planvortex-0.7.0 → planvortex-0.9.0}/tests/test_core.py +8 -4
  21. {planvortex-0.7.0 → planvortex-0.9.0}/tests/test_route_coverage.py +6 -4
  22. {planvortex-0.7.0 → planvortex-0.9.0}/.gitignore +0 -0
  23. {planvortex-0.7.0 → planvortex-0.9.0}/LICENSE +0 -0
  24. {planvortex-0.7.0 → planvortex-0.9.0}/scripts/build_docs.py +0 -0
  25. {planvortex-0.7.0 → planvortex-0.9.0}/scripts/check_packaging.py +0 -0
  26. {planvortex-0.7.0 → planvortex-0.9.0}/scripts/generate_models.py +0 -0
  27. {planvortex-0.7.0 → planvortex-0.9.0}/scripts/generate_sync.py +0 -0
  28. {planvortex-0.7.0 → planvortex-0.9.0}/scripts/route_coverage.py +0 -0
  29. {planvortex-0.7.0 → planvortex-0.9.0}/src/planvortex/_client.py +0 -0
  30. {planvortex-0.7.0 → planvortex-0.9.0}/src/planvortex/_client_sync.py +0 -0
  31. {planvortex-0.7.0 → planvortex-0.9.0}/src/planvortex/_core/__init__.py +0 -0
  32. {planvortex-0.7.0 → planvortex-0.9.0}/src/planvortex/_core/auth.py +0 -0
  33. {planvortex-0.7.0 → planvortex-0.9.0}/src/planvortex/_core/auth_sync.py +0 -0
  34. {planvortex-0.7.0 → planvortex-0.9.0}/src/planvortex/_core/files.py +0 -0
  35. {planvortex-0.7.0 → planvortex-0.9.0}/src/planvortex/_core/http.py +0 -0
  36. {planvortex-0.7.0 → planvortex-0.9.0}/src/planvortex/_core/http_sync.py +0 -0
  37. {planvortex-0.7.0 → planvortex-0.9.0}/src/planvortex/_core/pagination.py +0 -0
  38. {planvortex-0.7.0 → planvortex-0.9.0}/src/planvortex/_core/query.py +0 -0
  39. {planvortex-0.7.0 → planvortex-0.9.0}/src/planvortex/_core/transport.py +0 -0
  40. {planvortex-0.7.0 → planvortex-0.9.0}/src/planvortex/_generated/__init__.py +0 -0
  41. {planvortex-0.7.0 → planvortex-0.9.0}/src/planvortex/py.typed +0 -0
  42. {planvortex-0.7.0 → planvortex-0.9.0}/src/planvortex/resources/__init__.py +0 -0
  43. {planvortex-0.7.0 → planvortex-0.9.0}/src/planvortex/resources/base.py +0 -0
  44. {planvortex-0.7.0 → planvortex-0.9.0}/src/planvortex/resources/catalog.py +0 -0
  45. {planvortex-0.7.0 → planvortex-0.9.0}/src/planvortex/resources/clients.py +0 -0
  46. {planvortex-0.7.0 → planvortex-0.9.0}/src/planvortex/resources/comments.py +0 -0
  47. {planvortex-0.7.0 → planvortex-0.9.0}/src/planvortex/resources/contacts.py +0 -0
  48. {planvortex-0.7.0 → planvortex-0.9.0}/src/planvortex/resources/dashboard.py +0 -0
  49. {planvortex-0.7.0 → planvortex-0.9.0}/src/planvortex/resources/integrations.py +0 -0
  50. {planvortex-0.7.0 → planvortex-0.9.0}/src/planvortex/resources/messages.py +0 -0
  51. {planvortex-0.7.0 → planvortex-0.9.0}/src/planvortex/resources/organizations.py +0 -0
  52. {planvortex-0.7.0 → planvortex-0.9.0}/src/planvortex/resources/products.py +0 -0
  53. {planvortex-0.7.0 → planvortex-0.9.0}/src/planvortex/resources/publications.py +0 -0
  54. {planvortex-0.7.0 → planvortex-0.9.0}/src/planvortex/resources/uploads.py +0 -0
  55. {planvortex-0.7.0 → planvortex-0.9.0}/src/planvortex/resources_sync/__init__.py +0 -0
  56. {planvortex-0.7.0 → planvortex-0.9.0}/src/planvortex/resources_sync/base.py +0 -0
  57. {planvortex-0.7.0 → planvortex-0.9.0}/src/planvortex/resources_sync/catalog.py +0 -0
  58. {planvortex-0.7.0 → planvortex-0.9.0}/src/planvortex/resources_sync/clients.py +0 -0
  59. {planvortex-0.7.0 → planvortex-0.9.0}/src/planvortex/resources_sync/comments.py +0 -0
  60. {planvortex-0.7.0 → planvortex-0.9.0}/src/planvortex/resources_sync/contacts.py +0 -0
  61. {planvortex-0.7.0 → planvortex-0.9.0}/src/planvortex/resources_sync/dashboard.py +0 -0
  62. {planvortex-0.7.0 → planvortex-0.9.0}/src/planvortex/resources_sync/integrations.py +0 -0
  63. {planvortex-0.7.0 → planvortex-0.9.0}/src/planvortex/resources_sync/messages.py +0 -0
  64. {planvortex-0.7.0 → planvortex-0.9.0}/src/planvortex/resources_sync/organizations.py +0 -0
  65. {planvortex-0.7.0 → planvortex-0.9.0}/src/planvortex/resources_sync/products.py +0 -0
  66. {planvortex-0.7.0 → planvortex-0.9.0}/src/planvortex/resources_sync/publications.py +0 -0
  67. {planvortex-0.7.0 → planvortex-0.9.0}/src/planvortex/resources_sync/uploads.py +0 -0
  68. {planvortex-0.7.0 → planvortex-0.9.0}/src/planvortex/webhooks.py +0 -0
  69. {planvortex-0.7.0 → planvortex-0.9.0}/tests/__init__.py +0 -0
  70. {planvortex-0.7.0 → planvortex-0.9.0}/tests/conftest.py +0 -0
  71. {planvortex-0.7.0 → planvortex-0.9.0}/tests/contrato.py +0 -0
  72. {planvortex-0.7.0 → planvortex-0.9.0}/tests/live/__init__.py +0 -0
  73. {planvortex-0.7.0 → planvortex-0.9.0}/tests/live/conftest.py +0 -0
  74. {planvortex-0.7.0 → planvortex-0.9.0}/tests/live/test_auth.py +0 -0
  75. {planvortex-0.7.0 → planvortex-0.9.0}/tests/live/test_catalog.py +0 -0
  76. {planvortex-0.7.0 → planvortex-0.9.0}/tests/live/test_connect_flow.py +0 -0
  77. {planvortex-0.7.0 → planvortex-0.9.0}/tests/live/test_errors.py +0 -0
  78. {planvortex-0.7.0 → planvortex-0.9.0}/tests/live/test_publish.py +0 -0
  79. {planvortex-0.7.0 → planvortex-0.9.0}/tests/live/test_read.py +0 -0
  80. {planvortex-0.7.0 → planvortex-0.9.0}/tests/test_accounts.py +0 -0
  81. {planvortex-0.7.0 → planvortex-0.9.0}/tests/test_catalog.py +0 -0
  82. {planvortex-0.7.0 → planvortex-0.9.0}/tests/test_client.py +0 -0
  83. {planvortex-0.7.0 → planvortex-0.9.0}/tests/test_clients.py +0 -0
  84. {planvortex-0.7.0 → planvortex-0.9.0}/tests/test_comments.py +0 -0
  85. {planvortex-0.7.0 → planvortex-0.9.0}/tests/test_contacts.py +0 -0
  86. {planvortex-0.7.0 → planvortex-0.9.0}/tests/test_dashboard.py +0 -0
  87. {planvortex-0.7.0 → planvortex-0.9.0}/tests/test_example_comments.py +0 -0
  88. {planvortex-0.7.0 → planvortex-0.9.0}/tests/test_example_connect.py +0 -0
  89. {planvortex-0.7.0 → planvortex-0.9.0}/tests/test_example_publish.py +0 -0
  90. {planvortex-0.7.0 → planvortex-0.9.0}/tests/test_example_schedule.py +0 -0
  91. {planvortex-0.7.0 → planvortex-0.9.0}/tests/test_example_webhooks.py +0 -0
  92. {planvortex-0.7.0 → planvortex-0.9.0}/tests/test_files.py +0 -0
  93. {planvortex-0.7.0 → planvortex-0.9.0}/tests/test_generate_models.py +0 -0
  94. {planvortex-0.7.0 → planvortex-0.9.0}/tests/test_generate_sync.py +0 -0
  95. {planvortex-0.7.0 → planvortex-0.9.0}/tests/test_integrations.py +0 -0
  96. {planvortex-0.7.0 → planvortex-0.9.0}/tests/test_messages.py +0 -0
  97. {planvortex-0.7.0 → planvortex-0.9.0}/tests/test_models.py +0 -0
  98. {planvortex-0.7.0 → planvortex-0.9.0}/tests/test_openapi_freshness.py +0 -0
  99. {planvortex-0.7.0 → planvortex-0.9.0}/tests/test_organizations.py +0 -0
  100. {planvortex-0.7.0 → planvortex-0.9.0}/tests/test_packaging.py +0 -0
  101. {planvortex-0.7.0 → planvortex-0.9.0}/tests/test_pagination.py +0 -0
  102. {planvortex-0.7.0 → planvortex-0.9.0}/tests/test_products.py +0 -0
  103. {planvortex-0.7.0 → planvortex-0.9.0}/tests/test_publications.py +0 -0
  104. {planvortex-0.7.0 → planvortex-0.9.0}/tests/test_query_parity.py +0 -0
  105. {planvortex-0.7.0 → planvortex-0.9.0}/tests/test_readme.py +0 -0
  106. {planvortex-0.7.0 → planvortex-0.9.0}/tests/test_shapes_parity.py +0 -0
  107. {planvortex-0.7.0 → planvortex-0.9.0}/tests/test_types.py +0 -0
  108. {planvortex-0.7.0 → planvortex-0.9.0}/tests/test_uploads.py +0 -0
  109. {planvortex-0.7.0 → planvortex-0.9.0}/tests/test_webhooks.py +0 -0
@@ -4,6 +4,87 @@ 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.9.0] - 2026-09-17
8
+
9
+ **Which AI plan worked?** The server can now answer it, and so can this package:
10
+ `ai_plans.results()` returns what every plan achieved with what it published, the aggregate per
11
+ template and the total.
12
+
13
+ Nothing was removed and no signature moved: upgrading from `0.8.0` needs no changes, and
14
+ `MIGRATION.md` gains no entry.
15
+
16
+ ### Added
17
+
18
+ - **`pv.ai_plans.results(id_client, id_organization, ...)`**, over
19
+ `GET /clients/{id}/organizations/{id}/ai_plans/results`, in both clients. Four things about it
20
+ are not obvious, and all four are in its docstring:
21
+ - **The range filters on the plan's week** (`week_start`), not on when it was created. A plan
22
+ created today for next week has published nothing yet.
23
+ - **The ranking is interactions per _measured_ publication**, not the total — the total rewards
24
+ the plan with seven accounts even when each post does half as well — and only plans with
25
+ `ranked: True` (at least three measured publications, or all of them) compete in it.
26
+ - **`social_network` recomputes every plan with only its publications on those networks**,
27
+ which is what makes plans on different networks comparable. With that filter
28
+ `credits_per_engagement` is absent: the cost belongs to the whole plan.
29
+ - **It is not a `Page`.** Besides the page it carries `totals` and `by_template`, which do not
30
+ depend on the page, so it comes back whole.
31
+ - **Being first is not being good.** Every plan, group and the dashboard block carry
32
+ `engagement_vs_average`: the plan's interactions per post over what your usual posts get on the
33
+ same networks (`expected_engagement_per_publication`), where **1 is your average**. The ranking
34
+ still orders by interactions per post, so the first plan can be below 1.
35
+ - Types `AiPlanResult`, `AiPlanResults`, `AiPlanResultsGroup`, `AiPlanResultsTemplateGroup` and
36
+ the closed `AiPlanResultsSort`.
37
+ - **`Dashboard["ai_plan_results"]`** and its `available_blocks["ai_plan_results"]`: the three best
38
+ plans of the range, for the home screen. It needs both `ai_plans:read` and
39
+ `publication_stats:read`, and unlike `ai_plans.results()` it covers the organization **and its
40
+ children**, so each row carries its `id_organization`.
41
+ - **`pv.apps.rotate_secret(id_client, id_app)`**, over `POST /clients/{id}/apps/{id}/secret`. The
42
+ route reached the specification before this package, and regenerating the models is what turned
43
+ `tests/test_route_coverage.py` red — which is the test doing its job. **The previous secret stops
44
+ working the moment it answers, and the webhook signature changes with it.** Like `secret()`, it
45
+ needs a user token.
46
+
47
+ ## [0.8.0] - 2026-09-13
48
+
49
+ Slack, the thirteenth network, reaches the package — and here it arrives the way it should: **three
50
+ tests went red the moment the models were regenerated**, because `PublishableNetwork` is a closed
51
+ `Literal` written by hand. The Node package did not break at all, and that is worse: its
52
+ `SocialNetwork` is an open enumeration, so a missing network there costs autocompletion and
53
+ documentation with nothing to signal it.
54
+
55
+ Nothing was removed and no signature moved: upgrading from `0.7.0` needs no changes, and
56
+ `MIGRATION.md` gains no entry.
57
+
58
+ ### Fixed
59
+
60
+ - **Slack's errors (980-986) were not `PublicationError`.** The publication family stopped at 979,
61
+ so every one of them fell outside the table and arrived as a plain `PlanVortexError` — including
62
+ **980, the commonest error on the whole network**: the PlanVortex app is not in the channel.
63
+ Code that catches `PublicationError` to tell a fixable publication failure from anything else was
64
+ told nothing. The range now reaches 986, both ends are pinned by a test, and the README's range
65
+ table — which a test compares against the package — says so too.
66
+
67
+ ### Added
68
+
69
+ - **`slack` in `PublishableNetwork`**, so it is in `PUBLISHABLE_NETWORKS` at runtime and
70
+ `is_publishable_network("slack")` answers `True`. It is deliberately **not** in `CommentNetwork`
71
+ nor in `ContactChannel`: Slack has neither a comment inbox nor direct messages, and putting it in
72
+ either would promise a screen that does not exist. `SocialNetwork` picked it up on its own — it
73
+ comes from the generated models.
74
+ - **A warning on `accounts.enable()`, because nothing else announces it.** On Slack that call is
75
+ also what puts the app inside the channel. On a **public** channel it joins by itself; on a
76
+ **private** one it cannot — Slack has no API for that — and somebody has to type
77
+ `/invite @PlanVortex` in the channel. The call succeeds either way and the account stays
78
+ connected: what fails is the first publication, with error 980. Say it before your user picks the
79
+ channel.
80
+
81
+ ### Changed
82
+
83
+ - The prose that counts networks, in the five places it had gone stale: the two union sizes
84
+ (`PublishableNetwork` is now **twelve of the thirteen**), the bridge in `is_publishable_network`,
85
+ `SOCIAL_NETWORKS` ("six to thirteen in two years"), `ContactChannel` — where `slack` joins
86
+ `telegram` as a network that is **not** a channel, for the same reason: a bot cannot start a
87
+ conversation with anybody — and the two examples, `connect.py` and `publish.py`.
7
88
  ## [0.7.0] - 2026-09-04
8
89
 
9
90
  **Users are unlimited on every plan**, so the quota that said otherwise is gone from the types —
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: planvortex
3
- Version: 0.7.0
3
+ Version: 0.9.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/
@@ -246,7 +246,7 @@ memorising numbers:
246
246
  | 601-612 | `user` | `UserError` |
247
247
  | 700-715 | `account` | `AccountError` |
248
248
  | 800-810 | `file` | `FileError` |
249
- | 900-979 | `publication` | `PublicationError` |
249
+ | 900-986 | `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
 
@@ -216,7 +216,7 @@ memorising numbers:
216
216
  | 601-612 | `user` | `UserError` |
217
217
  | 700-715 | `account` | `AccountError` |
218
218
  | 800-810 | `file` | `FileError` |
219
- | 900-979 | `publication` | `PublicationError` |
219
+ | 900-986 | `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