magicfeedback 1.0.19__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 (54) hide show
  1. magicfeedback-1.0.19/LICENCE +19 -0
  2. magicfeedback-1.0.19/PKG-INFO +241 -0
  3. magicfeedback-1.0.19/README.md +218 -0
  4. magicfeedback-1.0.19/pyproject.toml +42 -0
  5. magicfeedback-1.0.19/setup.cfg +4 -0
  6. magicfeedback-1.0.19/setup.py +23 -0
  7. magicfeedback-1.0.19/src/deepdots_sdk/__init__.py +12 -0
  8. magicfeedback-1.0.19/src/deepdots_sdk/api/__init__.py +0 -0
  9. magicfeedback-1.0.19/src/deepdots_sdk/api/campaigns.py +5 -0
  10. magicfeedback-1.0.19/src/deepdots_sdk/api/companies.py +5 -0
  11. magicfeedback-1.0.19/src/deepdots_sdk/api/contacts.py +5 -0
  12. magicfeedback-1.0.19/src/deepdots_sdk/api/feedback.py +5 -0
  13. magicfeedback-1.0.19/src/deepdots_sdk/api/integrations_questions.py +5 -0
  14. magicfeedback-1.0.19/src/deepdots_sdk/api/metrics.py +5 -0
  15. magicfeedback-1.0.19/src/deepdots_sdk/api/products.py +5 -0
  16. magicfeedback-1.0.19/src/deepdots_sdk/api/reports.py +5 -0
  17. magicfeedback-1.0.19/src/deepdots_sdk/api/requests.py +5 -0
  18. magicfeedback-1.0.19/src/deepdots_sdk/api/signals.py +5 -0
  19. magicfeedback-1.0.19/src/deepdots_sdk/auth.py +5 -0
  20. magicfeedback-1.0.19/src/deepdots_sdk/client.py +5 -0
  21. magicfeedback-1.0.19/src/deepdots_sdk/logging_config.py +5 -0
  22. magicfeedback-1.0.19/src/deepdots_sdk/utils/__init__.py +0 -0
  23. magicfeedback-1.0.19/src/deepdots_sdk/utils/request.py +5 -0
  24. magicfeedback-1.0.19/src/magicfeedback.egg-info/PKG-INFO +241 -0
  25. magicfeedback-1.0.19/src/magicfeedback.egg-info/SOURCES.txt +52 -0
  26. magicfeedback-1.0.19/src/magicfeedback.egg-info/dependency_links.txt +1 -0
  27. magicfeedback-1.0.19/src/magicfeedback.egg-info/requires.txt +3 -0
  28. magicfeedback-1.0.19/src/magicfeedback.egg-info/top_level.txt +2 -0
  29. magicfeedback-1.0.19/src/magicfeedback_sdk/__init__.py +3 -0
  30. magicfeedback-1.0.19/src/magicfeedback_sdk/api/__init__.py +0 -0
  31. magicfeedback-1.0.19/src/magicfeedback_sdk/api/campaigns.py +47 -0
  32. magicfeedback-1.0.19/src/magicfeedback_sdk/api/companies.py +22 -0
  33. magicfeedback-1.0.19/src/magicfeedback_sdk/api/contacts.py +31 -0
  34. magicfeedback-1.0.19/src/magicfeedback_sdk/api/feedback.py +63 -0
  35. magicfeedback-1.0.19/src/magicfeedback_sdk/api/integrations_questions.py +15 -0
  36. magicfeedback-1.0.19/src/magicfeedback_sdk/api/metrics.py +15 -0
  37. magicfeedback-1.0.19/src/magicfeedback_sdk/api/products.py +15 -0
  38. magicfeedback-1.0.19/src/magicfeedback_sdk/api/reports.py +51 -0
  39. magicfeedback-1.0.19/src/magicfeedback_sdk/api/requests.py +94 -0
  40. magicfeedback-1.0.19/src/magicfeedback_sdk/api/signals.py +45 -0
  41. magicfeedback-1.0.19/src/magicfeedback_sdk/auth.py +217 -0
  42. magicfeedback-1.0.19/src/magicfeedback_sdk/client.py +117 -0
  43. magicfeedback-1.0.19/src/magicfeedback_sdk/logging_config.py +7 -0
  44. magicfeedback-1.0.19/src/magicfeedback_sdk/utils/__init__.py +0 -0
  45. magicfeedback-1.0.19/src/magicfeedback_sdk/utils/request.py +16 -0
  46. magicfeedback-1.0.19/tests/test_apikey.py +16 -0
  47. magicfeedback-1.0.19/tests/test_campaign.py +88 -0
  48. magicfeedback-1.0.19/tests/test_contact.py +59 -0
  49. magicfeedback-1.0.19/tests/test_datastore_token.py +200 -0
  50. magicfeedback-1.0.19/tests/test_deepdots_alias.py +62 -0
  51. magicfeedback-1.0.19/tests/test_feedback_answers_array.py +51 -0
  52. magicfeedback-1.0.19/tests/test_feedback_create.py +47 -0
  53. magicfeedback-1.0.19/tests/test_integrations_questions.py +28 -0
  54. magicfeedback-1.0.19/tests/test_request_done_message.py +60 -0
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2024 MagicFeedback OÜ
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in all
11
+ copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ SOFTWARE.  
@@ -0,0 +1,241 @@
1
+ Metadata-Version: 2.4
2
+ Name: magicfeedback
3
+ Version: 1.0.19
4
+ Summary: SDK for the Deepdots API (formerly MagicFeedback)
5
+ Home-page: https://github.com/MagicFeedback/magicfeedback_python_sdk
6
+ Author: Francisco Arias
7
+ Author-email: Francisco Arias <farias@magicfeedback.io>
8
+ Project-URL: Homepage, https://github.com/MagicFeedback/magicfeedback_python_sdk
9
+ Project-URL: Issues, https://github.com/MagicFeedback/magicfeedback_python_sdk/issues
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: License :: OSI Approved :: MIT License
12
+ Classifier: Operating System :: OS Independent
13
+ Requires-Python: >=3.8
14
+ Description-Content-Type: text/markdown
15
+ License-File: LICENCE
16
+ Requires-Dist: requests>=2.0.0
17
+ Requires-Dist: google-cloud-pubsub>=2.0.0
18
+ Requires-Dist: google-cloud-datastore>=2.16.0
19
+ Dynamic: author
20
+ Dynamic: home-page
21
+ Dynamic: license-file
22
+ Dynamic: requires-python
23
+
24
+ # Deepdots Python SDK
25
+
26
+ Python SDK for the Deepdots API (the company was formerly called MagicFeedback).
27
+
28
+ ## Installation
29
+
30
+ ```bash
31
+ pip install deepdots
32
+ ```
33
+
34
+ The original distribution is still published and still works:
35
+
36
+ ```bash
37
+ pip install magicfeedback
38
+ ```
39
+
40
+ ## Naming
41
+
42
+ MagicFeedback was renamed **Deepdots**. Both sets of names work and refer to the
43
+ *same* objects, so **no existing code needs to change**:
44
+
45
+ | | Current name | Original name |
46
+ |---|---|---|
47
+ | PyPI distribution | `deepdots` | `magicfeedback` |
48
+ | Import package | `deepdots_sdk` | `magicfeedback_sdk` |
49
+ | Client class | `Deepdots` | `MagicFeedback` |
50
+
51
+ Distribution names are written lowercase throughout — that is the packaging
52
+ convention, and PyPI treats names case-insensitively anyway, so
53
+ `pip install MagicFeedback` keeps working for anyone who has it written that way.
54
+
55
+ `deepdots_sdk` re-exports `magicfeedback_sdk` module by module, and `Deepdots`
56
+ is the same class object as `MagicFeedback` — `MagicFeedback is Deepdots` is
57
+ `True`, so `isinstance()` checks and subclasses behave identically. Submodule
58
+ imports work under either name (`from deepdots_sdk.api.feedback import
59
+ FeedbackAPI`). New code should prefer the Deepdots names.
60
+
61
+ ## Usage
62
+
63
+ ```python
64
+ from deepdots_sdk import Deepdots
65
+
66
+ client = Deepdots("email", "password")
67
+ ```
68
+
69
+ The original names remain fully supported:
70
+
71
+ ```python
72
+ from magicfeedback_sdk import MagicFeedback
73
+
74
+ client = MagicFeedback("email", "password")
75
+ ```
76
+
77
+ ## Authentication
78
+
79
+ The bearer token is resolved from one of two sources, selected with
80
+ `auth_source`:
81
+
82
+ - `"datastore"` **(default)** — read the token cached in Google Cloud Datastore
83
+ by the `update-token` job (kind `token-storage`, email
84
+ `robot@magicfeedback.io`, database `shared`). This avoids an Identity Platform
85
+ login on every use. If the cached token is missing, stale (older than
86
+ `token_max_age_min`, default 50 min) or Datastore is unreachable, the client
87
+ falls back to Identity Platform using `email`/`password`.
88
+ - `"identity"` — always log in via Identity Platform (`signInWithPassword`), the
89
+ original behaviour, with no Datastore lookup.
90
+
91
+ ```python
92
+ # Datastore-cached token (default), with Identity Platform fallback.
93
+ # email/password are only needed for the fallback.
94
+ client = MagicFeedback("email", "password")
95
+
96
+ # Tune the Datastore lookup (all optional; shown with their defaults):
97
+ client = MagicFeedback(
98
+ "email", "password",
99
+ auth_source="datastore",
100
+ gcp_project_id=None, # None => inferred from Application Default Credentials
101
+ datastore_database_id="shared",
102
+ token_kind="token-storage",
103
+ token_email="robot@magicfeedback.io",
104
+ token_max_age_min=50,
105
+ datastore_timeout_s=5.0, # cap the lookup so the fallback stays fast
106
+ )
107
+
108
+ # Original behaviour — always mint a fresh token via Identity Platform:
109
+ client = MagicFeedback("email", "password", auth_source="identity")
110
+ ```
111
+
112
+ The Datastore lookup is bounded by `datastore_timeout_s` (default 5s): if the
113
+ cache is unreachable or the credentials are stale, the client falls back to
114
+ Identity Platform within that budget instead of blocking on the Datastore
115
+ client's default ~60s retry deadline.
116
+
117
+ The Datastore path needs the `google-cloud-datastore` package (installed as a
118
+ dependency) and Google Application Default Credentials with read access to the
119
+ token entity (`gcloud auth application-default login` or
120
+ `GOOGLE_APPLICATION_CREDENTIALS`).
121
+
122
+ Helper methods:
123
+
124
+ - `client.refresh_token()` — re-resolve the token (same `auth_source`) and
125
+ update the auth header in place across all sub-API clients. Useful for
126
+ long-lived clients whose token has expired.
127
+ - `client.auth.get_token_from_datastore(allow_stale=False)` — read the cached
128
+ token directly; returns `None` when missing, stale or unreachable.
129
+
130
+ ## API Reference
131
+
132
+ ### `client.feedbacks`
133
+ - `create(feedback)` — creates a new feedback item. Required fields: `name`, `type`, `identity`, `integrationId`, `companyId`, `productId`.
134
+ - `get(filter=None)` — lists feedback items.
135
+ - `get_id(feedback_id, filter=None)` — retrieves a specific feedback item.
136
+ - `update(feedback_id, feedback)` — updates a feedback item.
137
+ - `delete(feedback_id)` — deletes a feedback item.
138
+ - `upload_attachment(feedback_id, file_path, filename=None, extra_data=None)` — uploads a file and attaches it to a feedback.
139
+
140
+ ### `client.contacts`
141
+ - `create(contact)`, `get(filter=None)`, `update(contact_id, contact)`, `delete(contact_id)`
142
+
143
+ ### `client.campaigns`
144
+ - `create(campaign)`, `get(filter=None)`
145
+ - `create_session(campaign_id, session)`, `get_sessions(campaign_id, filter=None)`, `get_sessions_feedbacks(campaign_id, filter=None)`
146
+
147
+ ### `client.metrics`
148
+ - `get(filter=None)`
149
+
150
+ ### `client.products`
151
+ - `get(filter=None)`
152
+
153
+ ### `client.companies`
154
+ - `get(filter=None)`, `get_id(id, filter=None)`
155
+
156
+ ### `client.integrations_questions`
157
+ - `get(integration_id, filter=None)`
158
+
159
+ ### `client.reports`
160
+ - `get(filter=None)`, `get_newsletter(filter=None)`, `update(report_id, report)`
161
+
162
+ ### `client.requests`
163
+ - `get(filter=None)`, `get_id(request_id, filter=None)`, `update(request_id, request)`
164
+
165
+ To mark a request DONE/ERROR asynchronously, publish a completion event to the
166
+ `request-done` Pub/Sub topic (project `magicfeedback-prod-api`, topic
167
+ `request-done`); the `request-done` Cloud Function consumes it and PATCHes the
168
+ request. The SDK does not publish this itself — build the envelope with
169
+ `build_done_message` and publish it directly. See
170
+ [`examples/mark_request_done.py`](examples/mark_request_done.py).
171
+
172
+ ## Examples
173
+
174
+ ```python
175
+ # Create a feedback
176
+ client.feedbacks.create({
177
+ "name": "Test Feedback",
178
+ "type": "APP",
179
+ "identity": "MAGICFORM",
180
+ "integrationId": "your-integration-id",
181
+ "companyId": "YOUR_COMPANY",
182
+ "productId": "YOUR_PRODUCT",
183
+ "answers": [
184
+ {"key": "score", "value": "4"},
185
+ {"key": "comment", "value": "Great service!"},
186
+ ],
187
+ })
188
+
189
+ # Get a feedback with its attachments
190
+ client.feedbacks.get_id(
191
+ "<feedback_id>",
192
+ filter={"include": [{"relation": "feedbackAttachments"}]}
193
+ )
194
+
195
+ # Upload a file attachment
196
+ client.feedbacks.upload_attachment(
197
+ "<feedback_id>",
198
+ file_path="/path/to/file.pdf",
199
+ filename="report.pdf", # optional, defaults to file name
200
+ extra_data={"source": "crm"} # optional, any JSON-serialisable dict
201
+ )
202
+
203
+ # Mark a request DONE via the request-done Pub/Sub topic.
204
+ # The SDK builds the envelope; the producer publishes it directly.
205
+ import json
206
+ from google.cloud import pubsub_v1
207
+ from magicfeedback_sdk.api.requests import build_done_message
208
+
209
+ message = build_done_message(
210
+ "<request_id>",
211
+ "<company_id>",
212
+ output={"value": "…final result…"},
213
+ sources=["<feedbackId1>", "<feedbackId2>"], # optional
214
+ logs="processed 2 items", # optional
215
+ # success=False, error={"message": "processing failed"} # to mark ERROR
216
+ )
217
+
218
+ publisher = pubsub_v1.PublisherClient()
219
+ topic_path = publisher.topic_path("magicfeedback-prod-api", "request-done")
220
+ publisher.publish(topic_path, json.dumps(message).encode("utf-8")).result()
221
+ ```
222
+
223
+ ## Logging
224
+
225
+ ```python
226
+ import logging
227
+ client.set_logging(logging.DEBUG)
228
+ ```
229
+
230
+ ## License
231
+
232
+ MIT
233
+
234
+ ## Contributing
235
+
236
+ Developing on the SDK itself — layout, tests, and how to cut a release — is
237
+ documented in [DEVELOPERS.md](DEVELOPERS.md).
238
+
239
+ ## Contact
240
+
241
+ farias@magicfeedback.io
@@ -0,0 +1,218 @@
1
+ # Deepdots Python SDK
2
+
3
+ Python SDK for the Deepdots API (the company was formerly called MagicFeedback).
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ pip install deepdots
9
+ ```
10
+
11
+ The original distribution is still published and still works:
12
+
13
+ ```bash
14
+ pip install magicfeedback
15
+ ```
16
+
17
+ ## Naming
18
+
19
+ MagicFeedback was renamed **Deepdots**. Both sets of names work and refer to the
20
+ *same* objects, so **no existing code needs to change**:
21
+
22
+ | | Current name | Original name |
23
+ |---|---|---|
24
+ | PyPI distribution | `deepdots` | `magicfeedback` |
25
+ | Import package | `deepdots_sdk` | `magicfeedback_sdk` |
26
+ | Client class | `Deepdots` | `MagicFeedback` |
27
+
28
+ Distribution names are written lowercase throughout — that is the packaging
29
+ convention, and PyPI treats names case-insensitively anyway, so
30
+ `pip install MagicFeedback` keeps working for anyone who has it written that way.
31
+
32
+ `deepdots_sdk` re-exports `magicfeedback_sdk` module by module, and `Deepdots`
33
+ is the same class object as `MagicFeedback` — `MagicFeedback is Deepdots` is
34
+ `True`, so `isinstance()` checks and subclasses behave identically. Submodule
35
+ imports work under either name (`from deepdots_sdk.api.feedback import
36
+ FeedbackAPI`). New code should prefer the Deepdots names.
37
+
38
+ ## Usage
39
+
40
+ ```python
41
+ from deepdots_sdk import Deepdots
42
+
43
+ client = Deepdots("email", "password")
44
+ ```
45
+
46
+ The original names remain fully supported:
47
+
48
+ ```python
49
+ from magicfeedback_sdk import MagicFeedback
50
+
51
+ client = MagicFeedback("email", "password")
52
+ ```
53
+
54
+ ## Authentication
55
+
56
+ The bearer token is resolved from one of two sources, selected with
57
+ `auth_source`:
58
+
59
+ - `"datastore"` **(default)** — read the token cached in Google Cloud Datastore
60
+ by the `update-token` job (kind `token-storage`, email
61
+ `robot@magicfeedback.io`, database `shared`). This avoids an Identity Platform
62
+ login on every use. If the cached token is missing, stale (older than
63
+ `token_max_age_min`, default 50 min) or Datastore is unreachable, the client
64
+ falls back to Identity Platform using `email`/`password`.
65
+ - `"identity"` — always log in via Identity Platform (`signInWithPassword`), the
66
+ original behaviour, with no Datastore lookup.
67
+
68
+ ```python
69
+ # Datastore-cached token (default), with Identity Platform fallback.
70
+ # email/password are only needed for the fallback.
71
+ client = MagicFeedback("email", "password")
72
+
73
+ # Tune the Datastore lookup (all optional; shown with their defaults):
74
+ client = MagicFeedback(
75
+ "email", "password",
76
+ auth_source="datastore",
77
+ gcp_project_id=None, # None => inferred from Application Default Credentials
78
+ datastore_database_id="shared",
79
+ token_kind="token-storage",
80
+ token_email="robot@magicfeedback.io",
81
+ token_max_age_min=50,
82
+ datastore_timeout_s=5.0, # cap the lookup so the fallback stays fast
83
+ )
84
+
85
+ # Original behaviour — always mint a fresh token via Identity Platform:
86
+ client = MagicFeedback("email", "password", auth_source="identity")
87
+ ```
88
+
89
+ The Datastore lookup is bounded by `datastore_timeout_s` (default 5s): if the
90
+ cache is unreachable or the credentials are stale, the client falls back to
91
+ Identity Platform within that budget instead of blocking on the Datastore
92
+ client's default ~60s retry deadline.
93
+
94
+ The Datastore path needs the `google-cloud-datastore` package (installed as a
95
+ dependency) and Google Application Default Credentials with read access to the
96
+ token entity (`gcloud auth application-default login` or
97
+ `GOOGLE_APPLICATION_CREDENTIALS`).
98
+
99
+ Helper methods:
100
+
101
+ - `client.refresh_token()` — re-resolve the token (same `auth_source`) and
102
+ update the auth header in place across all sub-API clients. Useful for
103
+ long-lived clients whose token has expired.
104
+ - `client.auth.get_token_from_datastore(allow_stale=False)` — read the cached
105
+ token directly; returns `None` when missing, stale or unreachable.
106
+
107
+ ## API Reference
108
+
109
+ ### `client.feedbacks`
110
+ - `create(feedback)` — creates a new feedback item. Required fields: `name`, `type`, `identity`, `integrationId`, `companyId`, `productId`.
111
+ - `get(filter=None)` — lists feedback items.
112
+ - `get_id(feedback_id, filter=None)` — retrieves a specific feedback item.
113
+ - `update(feedback_id, feedback)` — updates a feedback item.
114
+ - `delete(feedback_id)` — deletes a feedback item.
115
+ - `upload_attachment(feedback_id, file_path, filename=None, extra_data=None)` — uploads a file and attaches it to a feedback.
116
+
117
+ ### `client.contacts`
118
+ - `create(contact)`, `get(filter=None)`, `update(contact_id, contact)`, `delete(contact_id)`
119
+
120
+ ### `client.campaigns`
121
+ - `create(campaign)`, `get(filter=None)`
122
+ - `create_session(campaign_id, session)`, `get_sessions(campaign_id, filter=None)`, `get_sessions_feedbacks(campaign_id, filter=None)`
123
+
124
+ ### `client.metrics`
125
+ - `get(filter=None)`
126
+
127
+ ### `client.products`
128
+ - `get(filter=None)`
129
+
130
+ ### `client.companies`
131
+ - `get(filter=None)`, `get_id(id, filter=None)`
132
+
133
+ ### `client.integrations_questions`
134
+ - `get(integration_id, filter=None)`
135
+
136
+ ### `client.reports`
137
+ - `get(filter=None)`, `get_newsletter(filter=None)`, `update(report_id, report)`
138
+
139
+ ### `client.requests`
140
+ - `get(filter=None)`, `get_id(request_id, filter=None)`, `update(request_id, request)`
141
+
142
+ To mark a request DONE/ERROR asynchronously, publish a completion event to the
143
+ `request-done` Pub/Sub topic (project `magicfeedback-prod-api`, topic
144
+ `request-done`); the `request-done` Cloud Function consumes it and PATCHes the
145
+ request. The SDK does not publish this itself — build the envelope with
146
+ `build_done_message` and publish it directly. See
147
+ [`examples/mark_request_done.py`](examples/mark_request_done.py).
148
+
149
+ ## Examples
150
+
151
+ ```python
152
+ # Create a feedback
153
+ client.feedbacks.create({
154
+ "name": "Test Feedback",
155
+ "type": "APP",
156
+ "identity": "MAGICFORM",
157
+ "integrationId": "your-integration-id",
158
+ "companyId": "YOUR_COMPANY",
159
+ "productId": "YOUR_PRODUCT",
160
+ "answers": [
161
+ {"key": "score", "value": "4"},
162
+ {"key": "comment", "value": "Great service!"},
163
+ ],
164
+ })
165
+
166
+ # Get a feedback with its attachments
167
+ client.feedbacks.get_id(
168
+ "<feedback_id>",
169
+ filter={"include": [{"relation": "feedbackAttachments"}]}
170
+ )
171
+
172
+ # Upload a file attachment
173
+ client.feedbacks.upload_attachment(
174
+ "<feedback_id>",
175
+ file_path="/path/to/file.pdf",
176
+ filename="report.pdf", # optional, defaults to file name
177
+ extra_data={"source": "crm"} # optional, any JSON-serialisable dict
178
+ )
179
+
180
+ # Mark a request DONE via the request-done Pub/Sub topic.
181
+ # The SDK builds the envelope; the producer publishes it directly.
182
+ import json
183
+ from google.cloud import pubsub_v1
184
+ from magicfeedback_sdk.api.requests import build_done_message
185
+
186
+ message = build_done_message(
187
+ "<request_id>",
188
+ "<company_id>",
189
+ output={"value": "…final result…"},
190
+ sources=["<feedbackId1>", "<feedbackId2>"], # optional
191
+ logs="processed 2 items", # optional
192
+ # success=False, error={"message": "processing failed"} # to mark ERROR
193
+ )
194
+
195
+ publisher = pubsub_v1.PublisherClient()
196
+ topic_path = publisher.topic_path("magicfeedback-prod-api", "request-done")
197
+ publisher.publish(topic_path, json.dumps(message).encode("utf-8")).result()
198
+ ```
199
+
200
+ ## Logging
201
+
202
+ ```python
203
+ import logging
204
+ client.set_logging(logging.DEBUG)
205
+ ```
206
+
207
+ ## License
208
+
209
+ MIT
210
+
211
+ ## Contributing
212
+
213
+ Developing on the SDK itself — layout, tests, and how to cut a release — is
214
+ documented in [DEVELOPERS.md](DEVELOPERS.md).
215
+
216
+ ## Contact
217
+
218
+ farias@magicfeedback.io
@@ -0,0 +1,42 @@
1
+ [project]
2
+ name = "magicfeedback"
3
+ version = "1.0.19"
4
+ authors = [
5
+ { name="Francisco Arias", email="farias@magicfeedback.io" },
6
+ ]
7
+ description = "SDK for the Deepdots API (formerly MagicFeedback)"
8
+ readme = "README.md"
9
+ requires-python = ">=3.8"
10
+ # Must be kept in sync with setup.py's install_requires. When this [project]
11
+ # table is present, setuptools uses it for metadata and IGNORES setup.py's
12
+ # install_requires, so dependencies declared only there never reach the built
13
+ # wheel (that was the case up to 1.0.16 — the published wheels had no
14
+ # Requires-Dist). google-cloud-datastore>=2.16.0 is required for the named
15
+ # `database=` kwarg the Datastore-first auth relies on.
16
+ dependencies = [
17
+ "requests>=2.0.0",
18
+ "google-cloud-pubsub>=2.0.0",
19
+ "google-cloud-datastore>=2.16.0",
20
+ ]
21
+ classifiers = [
22
+ "Programming Language :: Python :: 3",
23
+ "License :: OSI Approved :: MIT License",
24
+ "Operating System :: OS Independent",
25
+ ]
26
+
27
+ # src-layout with TWO top-level packages: `magicfeedback_sdk` (the implementation)
28
+ # and `deepdots_sdk` (re-export mirror under the new company name). Declared
29
+ # explicitly so both are guaranteed to ship in the wheel rather than relying on
30
+ # setuptools auto-discovery.
31
+ [tool.setuptools.packages.find]
32
+ where = ["src"]
33
+
34
+ [project.urls]
35
+ Homepage = "https://github.com/MagicFeedback/magicfeedback_python_sdk"
36
+ Issues = "https://github.com/MagicFeedback/magicfeedback_python_sdk/issues"
37
+
38
+ [tool.pytest.ini_options]
39
+ # src-layout project: put src/ on sys.path so tests import the working tree
40
+ # (not a stale installed build) without requiring `pip install -e .`.
41
+ pythonpath = ["src"]
42
+ testpaths = ["tests"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,23 @@
1
+ from setuptools import find_packages, setup
2
+
3
+ setup(
4
+ name="magicfeedback_sdk",
5
+ version="1.0.19",
6
+ description="A Python SDK for interacting with the MagicFeedback API",
7
+ author="Francisco Arias",
8
+ author_email="farias@magicfeedback.io",
9
+ url="https://github.com/MagicFeedback/magicfeedback_python_sdk",
10
+ package_dir={"": "src"},
11
+ packages=find_packages(where="src"),
12
+ install_requires=[
13
+ "requests>=2.0.0",
14
+ "google-cloud-pubsub>=2.0.0",
15
+ "google-cloud-datastore>=2.16.0",
16
+ ],
17
+ classifiers=[
18
+ "Programming Language :: Python :: 3",
19
+ "License :: OSI Approved :: MIT License",
20
+ "Operating System :: OS Independent",
21
+ ],
22
+ python_requires=">=3.8",
23
+ )
@@ -0,0 +1,12 @@
1
+ """Deepdots Python SDK.
2
+
3
+ ``Deepdots`` is the current name of the company formerly called MagicFeedback.
4
+ This package is the forward-looking import name; the implementation still lives
5
+ in :mod:`magicfeedback_sdk` and is re-exported here module by module, so both
6
+ import paths expose the very same objects. Existing code importing
7
+ ``magicfeedback_sdk`` keeps working unchanged.
8
+ """
9
+
10
+ from magicfeedback_sdk.client import Deepdots, MagicFeedback
11
+
12
+ __all__ = ["Deepdots", "MagicFeedback"]
File without changes
@@ -0,0 +1,5 @@
1
+ """Re-export of :mod:`magicfeedback_sdk.api.campaigns` under the Deepdots name."""
2
+
3
+ from magicfeedback_sdk.api.campaigns import CampaignsAPI
4
+
5
+ __all__ = ['CampaignsAPI']
@@ -0,0 +1,5 @@
1
+ """Re-export of :mod:`magicfeedback_sdk.api.companies` under the Deepdots name."""
2
+
3
+ from magicfeedback_sdk.api.companies import CompaniesAPI
4
+
5
+ __all__ = ['CompaniesAPI']
@@ -0,0 +1,5 @@
1
+ """Re-export of :mod:`magicfeedback_sdk.api.contacts` under the Deepdots name."""
2
+
3
+ from magicfeedback_sdk.api.contacts import ContactsAPI
4
+
5
+ __all__ = ['ContactsAPI']
@@ -0,0 +1,5 @@
1
+ """Re-export of :mod:`magicfeedback_sdk.api.feedback` under the Deepdots name."""
2
+
3
+ from magicfeedback_sdk.api.feedback import FeedbackAPI
4
+
5
+ __all__ = ['FeedbackAPI']
@@ -0,0 +1,5 @@
1
+ """Re-export of :mod:`magicfeedback_sdk.api.integrations_questions` under the Deepdots name."""
2
+
3
+ from magicfeedback_sdk.api.integrations_questions import IntegrationsQuestionsAPI
4
+
5
+ __all__ = ['IntegrationsQuestionsAPI']
@@ -0,0 +1,5 @@
1
+ """Re-export of :mod:`magicfeedback_sdk.api.metrics` under the Deepdots name."""
2
+
3
+ from magicfeedback_sdk.api.metrics import MetricsAPI
4
+
5
+ __all__ = ['MetricsAPI']
@@ -0,0 +1,5 @@
1
+ """Re-export of :mod:`magicfeedback_sdk.api.products` under the Deepdots name."""
2
+
3
+ from magicfeedback_sdk.api.products import ProductsAPI
4
+
5
+ __all__ = ['ProductsAPI']
@@ -0,0 +1,5 @@
1
+ """Re-export of :mod:`magicfeedback_sdk.api.reports` under the Deepdots name."""
2
+
3
+ from magicfeedback_sdk.api.reports import ReportsAPI
4
+
5
+ __all__ = ['ReportsAPI']
@@ -0,0 +1,5 @@
1
+ """Re-export of :mod:`magicfeedback_sdk.api.requests` under the Deepdots name."""
2
+
3
+ from magicfeedback_sdk.api.requests import build_done_message, RequestsAPI
4
+
5
+ __all__ = ['build_done_message', 'RequestsAPI']
@@ -0,0 +1,5 @@
1
+ """Re-export of :mod:`magicfeedback_sdk.api.signals` under the Deepdots name."""
2
+
3
+ from magicfeedback_sdk.api.signals import SignalsAPI
4
+
5
+ __all__ = ['SignalsAPI']
@@ -0,0 +1,5 @@
1
+ """Re-export of :mod:`magicfeedback_sdk.auth` under the Deepdots name."""
2
+
3
+ from magicfeedback_sdk.auth import AuthManager
4
+
5
+ __all__ = ["AuthManager"]
@@ -0,0 +1,5 @@
1
+ """Re-export of :mod:`magicfeedback_sdk.client` under the Deepdots name."""
2
+
3
+ from magicfeedback_sdk.client import Deepdots, MagicFeedback
4
+
5
+ __all__ = ["Deepdots", "MagicFeedback"]
@@ -0,0 +1,5 @@
1
+ """Re-export of :mod:`magicfeedback_sdk.logging_config` under the Deepdots name."""
2
+
3
+ from magicfeedback_sdk.logging_config import configure_logger
4
+
5
+ __all__ = ["configure_logger"]
@@ -0,0 +1,5 @@
1
+ """Re-export of :mod:`magicfeedback_sdk.utils.request` under the Deepdots name."""
2
+
3
+ from magicfeedback_sdk.utils.request import make_request
4
+
5
+ __all__ = ["make_request"]