surge-api 1.5.7__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.
- surge-api-1.5.7/LICENSE +21 -0
- surge-api-1.5.7/PKG-INFO +172 -0
- surge-api-1.5.7/README.md +160 -0
- surge-api-1.5.7/setup.cfg +4 -0
- surge-api-1.5.7/setup.py +23 -0
- surge-api-1.5.7/surge/__init__.py +9 -0
- surge-api-1.5.7/surge/api_resource.py +99 -0
- surge-api-1.5.7/surge/carousel.py +35 -0
- surge-api-1.5.7/surge/errors.py +52 -0
- surge-api-1.5.7/surge/projects.py +383 -0
- surge-api-1.5.7/surge/questions.py +709 -0
- surge-api-1.5.7/surge/reports.py +166 -0
- surge-api-1.5.7/surge/responses.py +39 -0
- surge-api-1.5.7/surge/tasks.py +166 -0
- surge-api-1.5.7/surge/teams.py +149 -0
- surge-api-1.5.7/surge/utils.py +18 -0
- surge-api-1.5.7/surge_api.egg-info/PKG-INFO +172 -0
- surge-api-1.5.7/surge_api.egg-info/SOURCES.txt +19 -0
- surge-api-1.5.7/surge_api.egg-info/dependency_links.txt +1 -0
- surge-api-1.5.7/surge_api.egg-info/requires.txt +2 -0
- surge-api-1.5.7/surge_api.egg-info/top_level.txt +1 -0
surge-api-1.5.7/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2021 Surge
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
surge-api-1.5.7/PKG-INFO
ADDED
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: surge-api
|
|
3
|
+
Version: 1.5.7
|
|
4
|
+
Summary: Surge Python SDK
|
|
5
|
+
Home-page: https://github.com/surge-ai/surge-python
|
|
6
|
+
Author: Surge
|
|
7
|
+
Author-email: team@surgehq.ai
|
|
8
|
+
License: MIT
|
|
9
|
+
Description: # Surge Python SDK
|
|
10
|
+
|
|
11
|
+
The Surge Python SDK provides convenient access to the Surge API from applications written in the Python language.
|
|
12
|
+
|
|
13
|
+
## Installation
|
|
14
|
+
|
|
15
|
+
Install this package by using pip:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
pip install --upgrade surge-api
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
### Requirements
|
|
22
|
+
|
|
23
|
+
* Python 3.6+
|
|
24
|
+
|
|
25
|
+
## Usage
|
|
26
|
+
|
|
27
|
+
Documentation and and examples are available [here](https://app.surgehq.ai/docs/api#).
|
|
28
|
+
|
|
29
|
+
### Authentication
|
|
30
|
+
|
|
31
|
+
The library needs to be configured with your account's API key which is available in your Surge Profile. Set `surge.api_key` to its value:
|
|
32
|
+
|
|
33
|
+
```python
|
|
34
|
+
import surge
|
|
35
|
+
surge.api_key = "YOUR API KEY"
|
|
36
|
+
```
|
|
37
|
+
Or set the API key as an environment variable:
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
export SURGE_API_KEY=<YOUR API KEY>
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### Projects
|
|
44
|
+
|
|
45
|
+
Once the API key has been set, you can list all of the Projects under your Surge account or retrieve a specific Project by its ID.
|
|
46
|
+
|
|
47
|
+
```python
|
|
48
|
+
# List your Projects
|
|
49
|
+
projects = surge.Project.list()
|
|
50
|
+
|
|
51
|
+
# Print the name of the first Project
|
|
52
|
+
print(projects[0].name)
|
|
53
|
+
|
|
54
|
+
# Retrieve a specific Project
|
|
55
|
+
project = surge.Project.retrieve("076d207b-c207-41ca-b73a-5822fe2248ab")
|
|
56
|
+
|
|
57
|
+
# print the number of tasks in that Project
|
|
58
|
+
print(project.num_tasks)
|
|
59
|
+
```
|
|
60
|
+
If you have an existing project, you can use it as a template to get a new batch of data annotated.
|
|
61
|
+
You can add new labeling tasks from a CSV or with a list of dictionaries.
|
|
62
|
+
|
|
63
|
+
```python
|
|
64
|
+
# Create a project from a template
|
|
65
|
+
template_project_id = "076d207b-c207-41ca-b73a-5822fe2248ab"
|
|
66
|
+
project = surge.Project.create("My Labeling Project (July 2023 Batch)", template_id=template_project_id)
|
|
67
|
+
|
|
68
|
+
# Add data from a CSV file
|
|
69
|
+
project.create_tasks_from_csv('my_data.csv')
|
|
70
|
+
|
|
71
|
+
# Or add data directly
|
|
72
|
+
tasks = project.create_tasks([{
|
|
73
|
+
"company": "Surge",
|
|
74
|
+
"city": "San Francisco",
|
|
75
|
+
"state": "CA"
|
|
76
|
+
}])
|
|
77
|
+
|
|
78
|
+
# Launch the project to send it to the Surge workforce
|
|
79
|
+
project.launch()
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
Or you can create a new project from scratch by creating your own template and list of Question:
|
|
84
|
+
|
|
85
|
+
```python
|
|
86
|
+
from surge.questions import FreeResponseQuestion, MultipleChoiceQuestion, CheckboxQuestion
|
|
87
|
+
|
|
88
|
+
# Create a new Project
|
|
89
|
+
free_response_q = FreeResponseQuestion(
|
|
90
|
+
text="What is this company's website?",
|
|
91
|
+
label="")
|
|
92
|
+
|
|
93
|
+
multiple_choice_q = MultipleChoiceQuestion(
|
|
94
|
+
text="What category does this company belong to?",
|
|
95
|
+
label="Category",
|
|
96
|
+
options=["Tech", "Sports", "Gaming"])
|
|
97
|
+
|
|
98
|
+
checkbox_q = CheckboxQuestion(
|
|
99
|
+
text="Check all the social media accounts this company has",
|
|
100
|
+
label="",
|
|
101
|
+
options=["Facebook", "Twitter", "Pinterest", "Google+"])
|
|
102
|
+
|
|
103
|
+
fields_template_text = '''
|
|
104
|
+
<p>Company: {{company}}</p>
|
|
105
|
+
'''
|
|
106
|
+
|
|
107
|
+
project = surge.Project.create(
|
|
108
|
+
name="Categorize this company",
|
|
109
|
+
instructions="You will be asked to categorize a company.",
|
|
110
|
+
questions=[free_response_q, multiple_choice_q, checkbox_q],
|
|
111
|
+
callback_url="https://customer-callback-url/",
|
|
112
|
+
fields_template=fields_template_text,
|
|
113
|
+
num_workers_per_task=3)
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### Tasks
|
|
117
|
+
|
|
118
|
+
You can create new Tasks for a project, list all of the Tasks in a given project, or retrieve a specific Task given its ID.
|
|
119
|
+
|
|
120
|
+
```python
|
|
121
|
+
# Create Tasks for the new Project
|
|
122
|
+
tasks_data = [{"id": 1, "company": "Surge AI"}, {"id": 2, "company":"Twitch TV"}]
|
|
123
|
+
tasks = project.create_tasks(tasks_data)
|
|
124
|
+
|
|
125
|
+
# List all Tasks in the Project
|
|
126
|
+
all_tasks = project.list_tasks()
|
|
127
|
+
|
|
128
|
+
# Retrieve a specific Task
|
|
129
|
+
task = surge.Task.retrieve(task_id = "eaa44610-c8f6-4480-b746-28b6c8defd4d")
|
|
130
|
+
|
|
131
|
+
# Print the fields of that Task
|
|
132
|
+
print(task.fields)
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
You can also create Tasks in bulk by uploading a local CSV file. The header of the CSV file must specify the fields that are used in your Tasks.
|
|
136
|
+
|
|
137
|
+
| id | company |
|
|
138
|
+
| :--- | :----: |
|
|
139
|
+
| 1 | Surge AI |
|
|
140
|
+
| 2 | Twitch TV |
|
|
141
|
+
|
|
142
|
+
```python
|
|
143
|
+
# Create Tasks in bulk via CSV file
|
|
144
|
+
file_path = "./companies_to_classify.csv"
|
|
145
|
+
tasks = project.create_tasks_from_csv(file_path)
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
## Development
|
|
150
|
+
|
|
151
|
+
The test suite depends on `pytest`, which you can install using pip:
|
|
152
|
+
|
|
153
|
+
```bash
|
|
154
|
+
pip install pytest
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
To run tests from the command line:
|
|
158
|
+
|
|
159
|
+
```bash
|
|
160
|
+
# Run all tests
|
|
161
|
+
pytest
|
|
162
|
+
|
|
163
|
+
# Run tests in a specific file
|
|
164
|
+
pytest tests/test_projects.py
|
|
165
|
+
|
|
166
|
+
# Run a specific test
|
|
167
|
+
pytest tests/test_projects.py::test_init_complete
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
Platform: UNKNOWN
|
|
171
|
+
Requires-Python: >=3.6
|
|
172
|
+
Description-Content-Type: text/markdown
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
# Surge Python SDK
|
|
2
|
+
|
|
3
|
+
The Surge Python SDK provides convenient access to the Surge API from applications written in the Python language.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
Install this package by using pip:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
pip install --upgrade surge-api
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
### Requirements
|
|
14
|
+
|
|
15
|
+
* Python 3.6+
|
|
16
|
+
|
|
17
|
+
## Usage
|
|
18
|
+
|
|
19
|
+
Documentation and and examples are available [here](https://app.surgehq.ai/docs/api#).
|
|
20
|
+
|
|
21
|
+
### Authentication
|
|
22
|
+
|
|
23
|
+
The library needs to be configured with your account's API key which is available in your Surge Profile. Set `surge.api_key` to its value:
|
|
24
|
+
|
|
25
|
+
```python
|
|
26
|
+
import surge
|
|
27
|
+
surge.api_key = "YOUR API KEY"
|
|
28
|
+
```
|
|
29
|
+
Or set the API key as an environment variable:
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
export SURGE_API_KEY=<YOUR API KEY>
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### Projects
|
|
36
|
+
|
|
37
|
+
Once the API key has been set, you can list all of the Projects under your Surge account or retrieve a specific Project by its ID.
|
|
38
|
+
|
|
39
|
+
```python
|
|
40
|
+
# List your Projects
|
|
41
|
+
projects = surge.Project.list()
|
|
42
|
+
|
|
43
|
+
# Print the name of the first Project
|
|
44
|
+
print(projects[0].name)
|
|
45
|
+
|
|
46
|
+
# Retrieve a specific Project
|
|
47
|
+
project = surge.Project.retrieve("076d207b-c207-41ca-b73a-5822fe2248ab")
|
|
48
|
+
|
|
49
|
+
# print the number of tasks in that Project
|
|
50
|
+
print(project.num_tasks)
|
|
51
|
+
```
|
|
52
|
+
If you have an existing project, you can use it as a template to get a new batch of data annotated.
|
|
53
|
+
You can add new labeling tasks from a CSV or with a list of dictionaries.
|
|
54
|
+
|
|
55
|
+
```python
|
|
56
|
+
# Create a project from a template
|
|
57
|
+
template_project_id = "076d207b-c207-41ca-b73a-5822fe2248ab"
|
|
58
|
+
project = surge.Project.create("My Labeling Project (July 2023 Batch)", template_id=template_project_id)
|
|
59
|
+
|
|
60
|
+
# Add data from a CSV file
|
|
61
|
+
project.create_tasks_from_csv('my_data.csv')
|
|
62
|
+
|
|
63
|
+
# Or add data directly
|
|
64
|
+
tasks = project.create_tasks([{
|
|
65
|
+
"company": "Surge",
|
|
66
|
+
"city": "San Francisco",
|
|
67
|
+
"state": "CA"
|
|
68
|
+
}])
|
|
69
|
+
|
|
70
|
+
# Launch the project to send it to the Surge workforce
|
|
71
|
+
project.launch()
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
Or you can create a new project from scratch by creating your own template and list of Question:
|
|
76
|
+
|
|
77
|
+
```python
|
|
78
|
+
from surge.questions import FreeResponseQuestion, MultipleChoiceQuestion, CheckboxQuestion
|
|
79
|
+
|
|
80
|
+
# Create a new Project
|
|
81
|
+
free_response_q = FreeResponseQuestion(
|
|
82
|
+
text="What is this company's website?",
|
|
83
|
+
label="")
|
|
84
|
+
|
|
85
|
+
multiple_choice_q = MultipleChoiceQuestion(
|
|
86
|
+
text="What category does this company belong to?",
|
|
87
|
+
label="Category",
|
|
88
|
+
options=["Tech", "Sports", "Gaming"])
|
|
89
|
+
|
|
90
|
+
checkbox_q = CheckboxQuestion(
|
|
91
|
+
text="Check all the social media accounts this company has",
|
|
92
|
+
label="",
|
|
93
|
+
options=["Facebook", "Twitter", "Pinterest", "Google+"])
|
|
94
|
+
|
|
95
|
+
fields_template_text = '''
|
|
96
|
+
<p>Company: {{company}}</p>
|
|
97
|
+
'''
|
|
98
|
+
|
|
99
|
+
project = surge.Project.create(
|
|
100
|
+
name="Categorize this company",
|
|
101
|
+
instructions="You will be asked to categorize a company.",
|
|
102
|
+
questions=[free_response_q, multiple_choice_q, checkbox_q],
|
|
103
|
+
callback_url="https://customer-callback-url/",
|
|
104
|
+
fields_template=fields_template_text,
|
|
105
|
+
num_workers_per_task=3)
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### Tasks
|
|
109
|
+
|
|
110
|
+
You can create new Tasks for a project, list all of the Tasks in a given project, or retrieve a specific Task given its ID.
|
|
111
|
+
|
|
112
|
+
```python
|
|
113
|
+
# Create Tasks for the new Project
|
|
114
|
+
tasks_data = [{"id": 1, "company": "Surge AI"}, {"id": 2, "company":"Twitch TV"}]
|
|
115
|
+
tasks = project.create_tasks(tasks_data)
|
|
116
|
+
|
|
117
|
+
# List all Tasks in the Project
|
|
118
|
+
all_tasks = project.list_tasks()
|
|
119
|
+
|
|
120
|
+
# Retrieve a specific Task
|
|
121
|
+
task = surge.Task.retrieve(task_id = "eaa44610-c8f6-4480-b746-28b6c8defd4d")
|
|
122
|
+
|
|
123
|
+
# Print the fields of that Task
|
|
124
|
+
print(task.fields)
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
You can also create Tasks in bulk by uploading a local CSV file. The header of the CSV file must specify the fields that are used in your Tasks.
|
|
128
|
+
|
|
129
|
+
| id | company |
|
|
130
|
+
| :--- | :----: |
|
|
131
|
+
| 1 | Surge AI |
|
|
132
|
+
| 2 | Twitch TV |
|
|
133
|
+
|
|
134
|
+
```python
|
|
135
|
+
# Create Tasks in bulk via CSV file
|
|
136
|
+
file_path = "./companies_to_classify.csv"
|
|
137
|
+
tasks = project.create_tasks_from_csv(file_path)
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
## Development
|
|
142
|
+
|
|
143
|
+
The test suite depends on `pytest`, which you can install using pip:
|
|
144
|
+
|
|
145
|
+
```bash
|
|
146
|
+
pip install pytest
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
To run tests from the command line:
|
|
150
|
+
|
|
151
|
+
```bash
|
|
152
|
+
# Run all tests
|
|
153
|
+
pytest
|
|
154
|
+
|
|
155
|
+
# Run tests in a specific file
|
|
156
|
+
pytest tests/test_projects.py
|
|
157
|
+
|
|
158
|
+
# Run a specific test
|
|
159
|
+
pytest tests/test_projects.py::test_init_complete
|
|
160
|
+
```
|
surge-api-1.5.7/setup.py
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
from setuptools import setup, find_packages
|
|
2
|
+
|
|
3
|
+
VERSION = '1.5.7'
|
|
4
|
+
|
|
5
|
+
with open('requirements.txt') as f:
|
|
6
|
+
requirements = f.read().splitlines()
|
|
7
|
+
|
|
8
|
+
with open('README.md', 'r') as fh:
|
|
9
|
+
long_description = fh.read()
|
|
10
|
+
|
|
11
|
+
setup(name='surge-api',
|
|
12
|
+
version=VERSION,
|
|
13
|
+
description='Surge Python SDK',
|
|
14
|
+
author='Surge',
|
|
15
|
+
author_email='team@surgehq.ai',
|
|
16
|
+
url='https://github.com/surge-ai/surge-python',
|
|
17
|
+
license='MIT',
|
|
18
|
+
long_description=long_description,
|
|
19
|
+
long_description_content_type='text/markdown',
|
|
20
|
+
python_requires='>=3.6',
|
|
21
|
+
packages=find_packages(exclude=['tests', 'tests.*']),
|
|
22
|
+
install_requires=requirements,
|
|
23
|
+
tests_require=['pytest >= 6.0.0'])
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import os
|
|
2
|
+
|
|
3
|
+
from surge.projects import Project
|
|
4
|
+
from surge.tasks import Task
|
|
5
|
+
from surge.teams import Team
|
|
6
|
+
from surge.reports import Report
|
|
7
|
+
|
|
8
|
+
api_key = os.environ.get("SURGE_API_KEY", None)
|
|
9
|
+
base_url = os.environ.get("SURGE_BASE_URL", "https://app.surgehq.ai/api")
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import requests
|
|
2
|
+
|
|
3
|
+
import surge
|
|
4
|
+
from surge.errors import SurgeRequestError, SurgeMissingAPIKeyError
|
|
5
|
+
|
|
6
|
+
PROJECTS_ENDPOINT = "projects"
|
|
7
|
+
TASKS_ENDPOINT = "tasks"
|
|
8
|
+
REPORTS_ENDPOINT = "projects"
|
|
9
|
+
QUESTIONS_ENDPOINT = "items"
|
|
10
|
+
TEAMS_ENDPOINT = "teams"
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class APIResource(object):
|
|
14
|
+
|
|
15
|
+
def __init__(self, id=None):
|
|
16
|
+
self.id = id
|
|
17
|
+
|
|
18
|
+
def print_attrs(self, forbid_list: list = []):
|
|
19
|
+
return " ".join(
|
|
20
|
+
[f'{k}="{v}"' for k, v in self.__dict__.items() if not k in forbid_list]
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
@classmethod
|
|
24
|
+
def _base_request(cls, method, api_endpoint, params=None, api_key=None):
|
|
25
|
+
api_key_to_use = api_key or surge.api_key
|
|
26
|
+
if api_key_to_use is None:
|
|
27
|
+
raise SurgeMissingAPIKeyError
|
|
28
|
+
|
|
29
|
+
try:
|
|
30
|
+
url = f"{surge.base_url}/{api_endpoint}"
|
|
31
|
+
|
|
32
|
+
# GET request
|
|
33
|
+
if method == "get":
|
|
34
|
+
response = requests.get(url, auth=(api_key_to_use, ""), params=params)
|
|
35
|
+
|
|
36
|
+
# POST request
|
|
37
|
+
elif method == "post":
|
|
38
|
+
response = requests.post(url, auth=(api_key_to_use, ""), json=params)
|
|
39
|
+
|
|
40
|
+
# PUT request
|
|
41
|
+
elif method == "put":
|
|
42
|
+
if params is not None and len(params):
|
|
43
|
+
response = requests.put(url, auth=(api_key_to_use, ""), data=params)
|
|
44
|
+
else:
|
|
45
|
+
response = requests.put(url, auth=(api_key_to_use, ""))
|
|
46
|
+
|
|
47
|
+
elif method == "delete":
|
|
48
|
+
response = requests.delete(url, auth=(api_key_to_use, ""))
|
|
49
|
+
|
|
50
|
+
else:
|
|
51
|
+
raise SurgeRequestError("Invalid HTTP method.")
|
|
52
|
+
|
|
53
|
+
# Raise exception if there is an http error
|
|
54
|
+
response.raise_for_status()
|
|
55
|
+
|
|
56
|
+
# If no errors, return response as json
|
|
57
|
+
return response.json()
|
|
58
|
+
|
|
59
|
+
except requests.exceptions.HTTPError as err:
|
|
60
|
+
message = err.args[0]
|
|
61
|
+
message = f"{message}. {err.response.text}"
|
|
62
|
+
raise SurgeRequestError(message) from None
|
|
63
|
+
|
|
64
|
+
except requests.exceptions.JSONDecodeError as err:
|
|
65
|
+
message = err.args[0]
|
|
66
|
+
raise SurgeRequestError(message) from None
|
|
67
|
+
|
|
68
|
+
except Exception:
|
|
69
|
+
# Generic exception handling
|
|
70
|
+
raise SurgeRequestError
|
|
71
|
+
|
|
72
|
+
@classmethod
|
|
73
|
+
def get(cls, api_endpoint, params=None, api_key=None):
|
|
74
|
+
method = "get"
|
|
75
|
+
return cls._base_request(method,
|
|
76
|
+
api_endpoint,
|
|
77
|
+
params=params,
|
|
78
|
+
api_key=api_key)
|
|
79
|
+
|
|
80
|
+
@classmethod
|
|
81
|
+
def post(cls, api_endpoint, params=None, api_key=None):
|
|
82
|
+
method = "post"
|
|
83
|
+
return cls._base_request(method,
|
|
84
|
+
api_endpoint,
|
|
85
|
+
params=params,
|
|
86
|
+
api_key=api_key)
|
|
87
|
+
|
|
88
|
+
@classmethod
|
|
89
|
+
def put(cls, api_endpoint, params=None, api_key=None):
|
|
90
|
+
method = "put"
|
|
91
|
+
return cls._base_request(method,
|
|
92
|
+
api_endpoint,
|
|
93
|
+
params=params,
|
|
94
|
+
api_key=api_key)
|
|
95
|
+
|
|
96
|
+
@classmethod
|
|
97
|
+
def delete_request(cls, api_endpoint, api_key=None):
|
|
98
|
+
method = "delete"
|
|
99
|
+
return cls._base_request(method, api_endpoint, api_key=api_key)
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import json
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class Carousel(object):
|
|
5
|
+
|
|
6
|
+
def __init__(self, carousel_type=None):
|
|
7
|
+
self.carousel_type = carousel_type
|
|
8
|
+
|
|
9
|
+
def to_dict(self):
|
|
10
|
+
return self.__dict__
|
|
11
|
+
|
|
12
|
+
def to_json(self):
|
|
13
|
+
return json.dumps(self.to_dict())
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class BoundedRoundsCarousel(Carousel):
|
|
17
|
+
|
|
18
|
+
def __init__(self, min_rounds_for_carousel=1, max_rounds_for_carousel=1):
|
|
19
|
+
super().__init__(carousel_type="bounded_rounds")
|
|
20
|
+
self.min_rounds_for_carousel = min_rounds_for_carousel
|
|
21
|
+
self.max_rounds_for_carousel = max_rounds_for_carousel
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class DataKeyCarousel(Carousel):
|
|
25
|
+
|
|
26
|
+
def __init__(self, carousel_data_key=None):
|
|
27
|
+
super().__init__(carousel_type="data_key")
|
|
28
|
+
self.carousel_data_key = carousel_data_key
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class OrdinalColumnsCarousel(Carousel):
|
|
32
|
+
|
|
33
|
+
def __init__(self, max_rounds_for_carousel=1):
|
|
34
|
+
super().__init__(carousel_type="ordinal_columns")
|
|
35
|
+
self.max_rounds_for_carousel = max_rounds_for_carousel
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
class SurgeRequestError(Exception):
|
|
2
|
+
"""Catch-all exception for errors that occur when making a request"""
|
|
3
|
+
|
|
4
|
+
def __init__(self, message="Something went wrong with the API request."):
|
|
5
|
+
self.message = message
|
|
6
|
+
super().__init__(self.message)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class SurgeMissingAPIKeyError(Exception):
|
|
10
|
+
"""Raise when user has not set their API key"""
|
|
11
|
+
|
|
12
|
+
def __init__(self, message="Surge API key has not been set."):
|
|
13
|
+
self.message = message
|
|
14
|
+
super().__init__(self.message)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class SurgeMissingIDError(Exception):
|
|
18
|
+
"""Raise when a Surge object is missing an ID"""
|
|
19
|
+
|
|
20
|
+
def __init__(self, message="Must be initialized with an id."):
|
|
21
|
+
self.message = message
|
|
22
|
+
super().__init__(self.message)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class SurgeMissingAttributeError(Exception):
|
|
26
|
+
"""Raise when a Surge object is missing a required attribute"""
|
|
27
|
+
|
|
28
|
+
def __init__(self, message="Object is missing a required attribute."):
|
|
29
|
+
self.message = message
|
|
30
|
+
super().__init__(self.message)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class SurgeProjectQuestionError(Exception):
|
|
34
|
+
"""Raise for exceptions that occur when adding Questions to a new Project"""
|
|
35
|
+
|
|
36
|
+
def __init__(
|
|
37
|
+
self,
|
|
38
|
+
message="All questions added to a Project must be of type Question."
|
|
39
|
+
):
|
|
40
|
+
self.message = message
|
|
41
|
+
super().__init__(self.message)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
class SurgeTaskDataError(Exception):
|
|
45
|
+
"""Raise for exceptions that occur when creating Task objects"""
|
|
46
|
+
|
|
47
|
+
def __init__(
|
|
48
|
+
self,
|
|
49
|
+
message="Invalid argument: task_data must be a non-empty list of dicts."
|
|
50
|
+
):
|
|
51
|
+
self.message = message
|
|
52
|
+
super().__init__(self.message)
|