planvortex 0.9.0__tar.gz → 0.11.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.9.0 → planvortex-0.11.0}/CHANGELOG.md +107 -0
  2. {planvortex-0.9.0 → planvortex-0.11.0}/PKG-INFO +4 -4
  3. {planvortex-0.9.0 → planvortex-0.11.0}/README.md +3 -3
  4. {planvortex-0.9.0 → planvortex-0.11.0}/openapi/planvortex.openapi.json +936 -149
  5. {planvortex-0.9.0 → planvortex-0.11.0}/pyproject.toml +1 -1
  6. {planvortex-0.9.0 → planvortex-0.11.0}/src/planvortex/__init__.py +1 -1
  7. {planvortex-0.9.0 → planvortex-0.11.0}/src/planvortex/_core/errors.py +18 -11
  8. {planvortex-0.9.0 → planvortex-0.11.0}/src/planvortex/_generated/models.py +369 -40
  9. {planvortex-0.9.0 → planvortex-0.11.0}/src/planvortex/_shapes.py +21 -5
  10. {planvortex-0.9.0 → planvortex-0.11.0}/src/planvortex/_version.py +1 -1
  11. {planvortex-0.9.0 → planvortex-0.11.0}/src/planvortex/resources/accounts.py +60 -1
  12. {planvortex-0.9.0 → planvortex-0.11.0}/src/planvortex/resources/ai_plans.py +27 -3
  13. {planvortex-0.9.0 → planvortex-0.11.0}/src/planvortex/resources/integrations.py +101 -16
  14. {planvortex-0.9.0 → planvortex-0.11.0}/src/planvortex/resources/publications.py +22 -0
  15. {planvortex-0.9.0 → planvortex-0.11.0}/src/planvortex/resources_sync/accounts.py +60 -1
  16. {planvortex-0.9.0 → planvortex-0.11.0}/src/planvortex/resources_sync/ai_plans.py +27 -3
  17. {planvortex-0.9.0 → planvortex-0.11.0}/src/planvortex/resources_sync/integrations.py +87 -7
  18. {planvortex-0.9.0 → planvortex-0.11.0}/src/planvortex/resources_sync/publications.py +22 -0
  19. {planvortex-0.9.0 → planvortex-0.11.0}/src/planvortex/types.py +153 -26
  20. {planvortex-0.9.0 → planvortex-0.11.0}/tests/test_accounts.py +24 -1
  21. {planvortex-0.9.0 → planvortex-0.11.0}/tests/test_core.py +28 -0
  22. {planvortex-0.9.0 → planvortex-0.11.0}/tests/test_integrations.py +95 -0
  23. {planvortex-0.9.0 → planvortex-0.11.0}/tests/test_route_coverage.py +5 -3
  24. {planvortex-0.9.0 → planvortex-0.11.0}/tests/test_types.py +14 -0
  25. {planvortex-0.9.0 → planvortex-0.11.0}/.gitignore +0 -0
  26. {planvortex-0.9.0 → planvortex-0.11.0}/LICENSE +0 -0
  27. {planvortex-0.9.0 → planvortex-0.11.0}/scripts/build_docs.py +0 -0
  28. {planvortex-0.9.0 → planvortex-0.11.0}/scripts/check_packaging.py +0 -0
  29. {planvortex-0.9.0 → planvortex-0.11.0}/scripts/generate_models.py +0 -0
  30. {planvortex-0.9.0 → planvortex-0.11.0}/scripts/generate_sync.py +0 -0
  31. {planvortex-0.9.0 → planvortex-0.11.0}/scripts/route_coverage.py +0 -0
  32. {planvortex-0.9.0 → planvortex-0.11.0}/src/planvortex/_client.py +0 -0
  33. {planvortex-0.9.0 → planvortex-0.11.0}/src/planvortex/_client_sync.py +0 -0
  34. {planvortex-0.9.0 → planvortex-0.11.0}/src/planvortex/_core/__init__.py +0 -0
  35. {planvortex-0.9.0 → planvortex-0.11.0}/src/planvortex/_core/auth.py +0 -0
  36. {planvortex-0.9.0 → planvortex-0.11.0}/src/planvortex/_core/auth_sync.py +0 -0
  37. {planvortex-0.9.0 → planvortex-0.11.0}/src/planvortex/_core/files.py +0 -0
  38. {planvortex-0.9.0 → planvortex-0.11.0}/src/planvortex/_core/http.py +0 -0
  39. {planvortex-0.9.0 → planvortex-0.11.0}/src/planvortex/_core/http_sync.py +0 -0
  40. {planvortex-0.9.0 → planvortex-0.11.0}/src/planvortex/_core/pagination.py +0 -0
  41. {planvortex-0.9.0 → planvortex-0.11.0}/src/planvortex/_core/query.py +0 -0
  42. {planvortex-0.9.0 → planvortex-0.11.0}/src/planvortex/_core/transport.py +0 -0
  43. {planvortex-0.9.0 → planvortex-0.11.0}/src/planvortex/_generated/__init__.py +0 -0
  44. {planvortex-0.9.0 → planvortex-0.11.0}/src/planvortex/py.typed +0 -0
  45. {planvortex-0.9.0 → planvortex-0.11.0}/src/planvortex/resources/__init__.py +0 -0
  46. {planvortex-0.9.0 → planvortex-0.11.0}/src/planvortex/resources/apps.py +0 -0
  47. {planvortex-0.9.0 → planvortex-0.11.0}/src/planvortex/resources/base.py +0 -0
  48. {planvortex-0.9.0 → planvortex-0.11.0}/src/planvortex/resources/catalog.py +0 -0
  49. {planvortex-0.9.0 → planvortex-0.11.0}/src/planvortex/resources/clients.py +0 -0
  50. {planvortex-0.9.0 → planvortex-0.11.0}/src/planvortex/resources/comments.py +0 -0
  51. {planvortex-0.9.0 → planvortex-0.11.0}/src/planvortex/resources/contacts.py +0 -0
  52. {planvortex-0.9.0 → planvortex-0.11.0}/src/planvortex/resources/dashboard.py +0 -0
  53. {planvortex-0.9.0 → planvortex-0.11.0}/src/planvortex/resources/messages.py +0 -0
  54. {planvortex-0.9.0 → planvortex-0.11.0}/src/planvortex/resources/organizations.py +0 -0
  55. {planvortex-0.9.0 → planvortex-0.11.0}/src/planvortex/resources/products.py +0 -0
  56. {planvortex-0.9.0 → planvortex-0.11.0}/src/planvortex/resources/uploads.py +0 -0
  57. {planvortex-0.9.0 → planvortex-0.11.0}/src/planvortex/resources_sync/__init__.py +0 -0
  58. {planvortex-0.9.0 → planvortex-0.11.0}/src/planvortex/resources_sync/apps.py +0 -0
  59. {planvortex-0.9.0 → planvortex-0.11.0}/src/planvortex/resources_sync/base.py +0 -0
  60. {planvortex-0.9.0 → planvortex-0.11.0}/src/planvortex/resources_sync/catalog.py +0 -0
  61. {planvortex-0.9.0 → planvortex-0.11.0}/src/planvortex/resources_sync/clients.py +0 -0
  62. {planvortex-0.9.0 → planvortex-0.11.0}/src/planvortex/resources_sync/comments.py +0 -0
  63. {planvortex-0.9.0 → planvortex-0.11.0}/src/planvortex/resources_sync/contacts.py +0 -0
  64. {planvortex-0.9.0 → planvortex-0.11.0}/src/planvortex/resources_sync/dashboard.py +0 -0
  65. {planvortex-0.9.0 → planvortex-0.11.0}/src/planvortex/resources_sync/messages.py +0 -0
  66. {planvortex-0.9.0 → planvortex-0.11.0}/src/planvortex/resources_sync/organizations.py +0 -0
  67. {planvortex-0.9.0 → planvortex-0.11.0}/src/planvortex/resources_sync/products.py +0 -0
  68. {planvortex-0.9.0 → planvortex-0.11.0}/src/planvortex/resources_sync/uploads.py +0 -0
  69. {planvortex-0.9.0 → planvortex-0.11.0}/src/planvortex/webhooks.py +0 -0
  70. {planvortex-0.9.0 → planvortex-0.11.0}/tests/__init__.py +0 -0
  71. {planvortex-0.9.0 → planvortex-0.11.0}/tests/conftest.py +0 -0
  72. {planvortex-0.9.0 → planvortex-0.11.0}/tests/contrato.py +0 -0
  73. {planvortex-0.9.0 → planvortex-0.11.0}/tests/live/__init__.py +0 -0
  74. {planvortex-0.9.0 → planvortex-0.11.0}/tests/live/conftest.py +0 -0
  75. {planvortex-0.9.0 → planvortex-0.11.0}/tests/live/test_auth.py +0 -0
  76. {planvortex-0.9.0 → planvortex-0.11.0}/tests/live/test_catalog.py +0 -0
  77. {planvortex-0.9.0 → planvortex-0.11.0}/tests/live/test_connect_flow.py +0 -0
  78. {planvortex-0.9.0 → planvortex-0.11.0}/tests/live/test_errors.py +0 -0
  79. {planvortex-0.9.0 → planvortex-0.11.0}/tests/live/test_publish.py +0 -0
  80. {planvortex-0.9.0 → planvortex-0.11.0}/tests/live/test_read.py +0 -0
  81. {planvortex-0.9.0 → planvortex-0.11.0}/tests/test_ai_plans.py +0 -0
  82. {planvortex-0.9.0 → planvortex-0.11.0}/tests/test_apps.py +0 -0
  83. {planvortex-0.9.0 → planvortex-0.11.0}/tests/test_catalog.py +0 -0
  84. {planvortex-0.9.0 → planvortex-0.11.0}/tests/test_client.py +0 -0
  85. {planvortex-0.9.0 → planvortex-0.11.0}/tests/test_clients.py +0 -0
  86. {planvortex-0.9.0 → planvortex-0.11.0}/tests/test_comments.py +0 -0
  87. {planvortex-0.9.0 → planvortex-0.11.0}/tests/test_contacts.py +0 -0
  88. {planvortex-0.9.0 → planvortex-0.11.0}/tests/test_dashboard.py +0 -0
  89. {planvortex-0.9.0 → planvortex-0.11.0}/tests/test_example_comments.py +0 -0
  90. {planvortex-0.9.0 → planvortex-0.11.0}/tests/test_example_connect.py +0 -0
  91. {planvortex-0.9.0 → planvortex-0.11.0}/tests/test_example_publish.py +0 -0
  92. {planvortex-0.9.0 → planvortex-0.11.0}/tests/test_example_schedule.py +0 -0
  93. {planvortex-0.9.0 → planvortex-0.11.0}/tests/test_example_webhooks.py +0 -0
  94. {planvortex-0.9.0 → planvortex-0.11.0}/tests/test_files.py +0 -0
  95. {planvortex-0.9.0 → planvortex-0.11.0}/tests/test_generate_models.py +0 -0
  96. {planvortex-0.9.0 → planvortex-0.11.0}/tests/test_generate_sync.py +0 -0
  97. {planvortex-0.9.0 → planvortex-0.11.0}/tests/test_messages.py +0 -0
  98. {planvortex-0.9.0 → planvortex-0.11.0}/tests/test_models.py +0 -0
  99. {planvortex-0.9.0 → planvortex-0.11.0}/tests/test_openapi_freshness.py +0 -0
  100. {planvortex-0.9.0 → planvortex-0.11.0}/tests/test_organizations.py +0 -0
  101. {planvortex-0.9.0 → planvortex-0.11.0}/tests/test_packaging.py +0 -0
  102. {planvortex-0.9.0 → planvortex-0.11.0}/tests/test_pagination.py +0 -0
  103. {planvortex-0.9.0 → planvortex-0.11.0}/tests/test_products.py +0 -0
  104. {planvortex-0.9.0 → planvortex-0.11.0}/tests/test_publications.py +0 -0
  105. {planvortex-0.9.0 → planvortex-0.11.0}/tests/test_query_parity.py +0 -0
  106. {planvortex-0.9.0 → planvortex-0.11.0}/tests/test_readme.py +0 -0
  107. {planvortex-0.9.0 → planvortex-0.11.0}/tests/test_shapes_parity.py +0 -0
  108. {planvortex-0.9.0 → planvortex-0.11.0}/tests/test_uploads.py +0 -0
  109. {planvortex-0.9.0 → planvortex-0.11.0}/tests/test_webhooks.py +0 -0
@@ -4,6 +4,113 @@ 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.11.0] - 2026-09-29
8
+
9
+ A connected **WooCommerce store** becomes a source for the AI planner: the `from_catalog` template
10
+ can now write a week of posts from the store's real products (name, description, price, picture and
11
+ the link to its page), not only from a Meta catalogue. Nothing was removed and no signature moved:
12
+ upgrading from `0.10.0` needs no changes, and `MIGRATION.md` gains no entry.
13
+
14
+ ### Added
15
+
16
+ - **`pv.integrations.products(id_organization, id_integration, cursor=, search=, limit=)`**, over
17
+ `GET /organizations/{id}/integrations/{id}/products`: one page of a connected store's catalogue,
18
+ to choose the products of a plan. Also on the synchronous client. Four things about it are not
19
+ obvious, and all four are in its docstring:
20
+ - **It pages by an opaque cursor**, not by number: send `next_cursor` back as `cursor` exactly as
21
+ it came. There is no `iterate_products` on purpose: every page is a live request to the
22
+ client's own hosting, and finding three products among ten thousand is what `search` is for.
23
+ - **Out-of-stock products come back with `available: False`**: show them, but do not let them be
24
+ chosen, or the plan is refused with 2112.
25
+ - **`price` is text to copy verbatim**, as the store displays it (tax, symbol, range). Absent
26
+ means no price.
27
+ - A store that rejects its key (2211) is marked until it is reconnected; a firewall (2212) or a
28
+ store that does not answer (2213) is not.
29
+ - **`url=` and `id_integration=` on `integrations.connect_link`.** The store's approval button: the
30
+ link points at the store's own WordPress, so it needs its address, and `id_integration`
31
+ reconnects a store instead of adding one. After approving, the user comes back with an
32
+ `id_integration`: **read that integration instead of trusting `success`** (2219 means the key is
33
+ still being checked).
34
+ - **`"provider": "woocommerce"` in `integrations.connect`**, with a read-only key created by hand
35
+ (`url`, `consumer_key`, `consumer_secret`). It is the way when the store uses plain permalinks and
36
+ the button cannot work (2216).
37
+ - **`source["id_integration_catalog"]`** on `ai_plans.create`: the store a `from_catalog` plan
38
+ reads from, exclusive with `id_account_catalog` (both at once is a 2112). The stored products gain
39
+ `permalink`, the product's page, which the texts use where a link can be clicked and where a
40
+ Pinterest pin leads unless the plan has its own `options["link"]`.
41
+ - **`unsupported_networks`** on `PlannerTemplate`: the networks whose accounts a plan of that
42
+ template cannot carry. A plan with one is refused with **2120** before anything is read or
43
+ charged; today that is YouTube on `from_images` and `from_catalog`.
44
+ - On `IntegrationProvider`, the gates `connect_link`, `connect_link_fields` and `catalog`. **Having a
45
+ link is not being OAuth**: branch on these, never on the provider's name.
46
+ - Types `IntegrationCatalogProduct`, `IntegrationCatalogPage`, `IntegrationConfig`,
47
+ `IntegrationFormField` and `WooCommerceConnectRequest`; `"woocommerce"` in
48
+ `INTEGRATION_PROVIDERS`.
49
+
50
+ ### Changed
51
+
52
+ - **`Integration["config"]` is typed as `IntegrationConfig`**, which adds the store's keys to the
53
+ feed's: `api_base`, `auth_mode`, `key_ending`, `currency` and `tax_location_missing`. Two of them
54
+ have to be shown, not just stored. `key_ending` is how the user finds the key to delete in their
55
+ WordPress after disconnecting, because **WooCommerce does not let an app revoke its own key**; and
56
+ `tax_location_missing: True` means the store's API gives prices without tax labelled as tax
57
+ included, so its taxable products come without a price until the store's setting is fixed and it
58
+ is reconnected. `RssConfig` stays what an `update` takes, and a store's `config` cannot be edited
59
+ at all (2220).
60
+ - A form field can now be of type `secret` (WooCommerce's consumer secret): mask it, never prefill
61
+ it, and mark it as a new password so the browser does not fill it with the user's own.
62
+
63
+ ## [0.10.0] - 2026-09-24
64
+
65
+ Pinterest, the fourteenth network, reaches the package — and it is the first one where choosing
66
+ the account does not choose where the publication comes out. **A pin goes to a board**, and that is
67
+ a field no other network has. Nothing was removed and no signature moved: upgrading from `0.9.0`
68
+ needs no changes, and `MIGRATION.md` gains no entry. The new fields are optional for the other
69
+ thirteen networks.
70
+
71
+ **`PublishableNetwork` is a closed `Literal` written by hand, and it went red on regeneration** —
72
+ which is how it is meant to find out. Pinterest is also the first network that enters
73
+ `PUBLISHABLE_NETWORKS` and **not** `COMMENT_NETWORKS`, so it is the first real proof that the two
74
+ lists are independent.
75
+
76
+ ### Added
77
+
78
+ - **`pv.accounts.destinations(id_organization, id_account)`** and
79
+ **`pv.accounts.destination(id_organization, id_account, id_destination)`**, over
80
+ `GET /organizations/{id}/accounts/{id}/destinations[/{id}]`: an account's Pinterest boards, and
81
+ one board with its sections. Every other network answers 992 — the account itself is where its
82
+ publications go. Both take `refresh=True` to skip the server's short cache, for a board created
83
+ a moment ago; not on every call, because all of PlanVortex's Pinterest traffic leaves through one
84
+ application. Also on the synchronous client.
85
+ - **`"pinterest"` in `PublishableNetwork` and `PUBLISHABLE_NETWORKS`**, and **`destination` and
86
+ `link` on `PublicationInput`.** On Pinterest the board is **required**, and leaving it out does
87
+ not raise: the publication is created in `withErrors` with code 987 and is never attempted.
88
+ `destination["id"]` is **always a string** — Pinterest's ids are long integers. `link` is where
89
+ the pin takes whoever clicks it: it goes in its own field, not inside `text`. On every other
90
+ network both fields are deleted on save. Ask `destinations` and `link` in
91
+ `catalog.social_capabilities()` rather than keeping a list of which network has which.
92
+ - **`destinations` on `AiPlanCreateRequest` and `AiPlan`, and `options["link"]`.** A plan with a
93
+ Pinterest account needs that account's board, one entry per account; without it
94
+ `ai_plans.create` raises **2118**, listing every account that fails. A plan that would leave pins
95
+ without an image is refused with **2119** before a single credit is spent, and an image that
96
+ fails halfway through the generation shows up as a **922** in `warnings`, with the publication
97
+ that was left without it.
98
+ - Types `Destination`, `PublicationDestination` and `AiPlanDestination`.
99
+
100
+ ### Fixed
101
+
102
+ - **Pinterest's error codes (987-996) arrived outside every family**, the third time a network's
103
+ codes were born above the ceiling of the publications range (after 978 and 980). They are now
104
+ `PublicationError`. The one that matters most is **991**: Pinterest throttling the application,
105
+ sent as HTTP 429 with `Retry-After` — the answer is to wait, and `error.retry_after` says how long.
106
+ - **547, 548 and 716 were unclassified too.** 547 (a client app's identifier cannot change) and
107
+ 548 (rotating the secret failed, the method that came with `0.9.0`) are now `AuthError`, and 716
108
+ (another process is renewing the Bluesky session; retry) is `AccountError`.
109
+ - A test now checks that **every** error code named in the specification's error tables falls into
110
+ some family, so the next network cannot repeat this without the build going red.
111
+ - The prose that counts networks said "nine of the eleven" and "eleven and not twelve" in places;
112
+ it now says fourteen, thirteen of which publish.
113
+
7
114
  ## [0.9.0] - 2026-09-17
8
115
 
9
116
  **Which AI plan worked?** The server can now answer it, and so can this package:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: planvortex
3
- Version: 0.9.0
3
+ Version: 0.11.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` |
@@ -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` |