Skip to content

Commit 879b821

Browse files
Merge branch 'dev' into POP-2280
2 parents 95cb151 + 97b20a5 commit 879b821

15 files changed

+394
-46
lines changed

.flake8

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
[flake8]
2+
exclude=.git,.pytest_cache,venv

.github/workflows/pythonpackage.yml

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
name: python-tests
2+
3+
on: [push]
4+
5+
jobs:
6+
build:
7+
8+
runs-on: ubuntu-latest
9+
strategy:
10+
max-parallel: 4
11+
matrix:
12+
python-version: [2.7, 3.5, 3.6, 3.7]
13+
14+
steps:
15+
- uses: actions/checkout@v1
16+
- name: Set up Python ${{ matrix.python-version }}
17+
uses: actions/setup-python@v1
18+
with:
19+
python-version: ${{ matrix.python-version }}
20+
- name: Install dependencies
21+
run: |
22+
python -m pip install --upgrade pip
23+
pip install -r requirements.txt
24+
- name: Lint with flake8
25+
run: |
26+
pip install flake8
27+
# stop the build if there are Python syntax errors or undefined names
28+
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
29+
# the GitHub editor is 127 chars wide
30+
flake8 . --count --max-complexity=10 --max-line-length=127 --statistics
31+
- name: Test with pytest
32+
run: |
33+
pip install pytest
34+
pytest

CONTRIBUTING.md

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ This is an InnerSource python project. It is the work of someone who thought it
77
This repository is maintained by
88

99
1. [Ridley Larsen](@RidleyLarsen)
10-
1. [Bradley Wogsland](@wogsland)
10+
2. [Bradley Wogsland](@wogsland)
11+
3. [Nathan Workman](@nathanworkman)
1112

1213
### Community Guidelines
1314

@@ -23,6 +24,14 @@ Linting software is strongly recommended to improve code quality and maintain re
2324

2425
Read more [here](http://flake8.pycqa.org/en/latest/)
2526

27+
To lint the files,
28+
29+
virtualenv venv
30+
. venv/bin/activate
31+
pip install flake8
32+
flake8 . --count --max-complexity=10 --max-line-length=127 --statistics
33+
deactivate
34+
2635
### Testing
2736

2837
To run the tests,

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
# python-demandapi-client
2+
3+
<a href="https://github.com/dynata/python-demandapi-client"><img alt="GitHub Actions status" src="https://github.com/dynata/python-demandapi-client/workflows/python-tests/badge.svg"></a>
4+
25
A Python client library for the [Dynata Demand API](https://developers.dynata.com/)
36
## Setup
47

dynatademand/api.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
SCHEMAS = [
99
"project_new",
1010
"project_update",
11+
"lineitem_update",
1112
]
1213

1314

@@ -182,6 +183,22 @@ def get_project_detailed_report(self, project_id):
182183
def get_line_item(self, project_id, line_item_id):
183184
return self._api_get('/projects/{}/lineItems/{}'.format(project_id, line_item_id))
184185

186+
def update_line_item(self, project_id, lineitem_id, lineitem_data):
187+
'''
188+
Updates the specified line item by setting the values of the parameters passed.
189+
Any parameters not provided will be left unchanged.
190+
'''
191+
# Update an existing line item. Uses the "lineitem_update" schema.
192+
self._validate_object("lineitem_update", lineitem_data)
193+
response_data = self._api_post('/projects/{}/lineItems/{}'.format(project_id, lineitem_id), lineitem_data)
194+
if response_data.get('status').get('message') != 'success':
195+
raise DemandAPIError(
196+
"Could not update line item. Demand API responded with: {}".format(
197+
response_data
198+
)
199+
)
200+
return response_data
201+
185202
def get_line_items(self, project_id):
186203
return self._api_get('/projects/{}/lineItems'.format(project_id))
187204

Lines changed: 195 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,195 @@
1+
{
2+
"type": "object",
3+
"title": "New Line Item",
4+
"properties": {
5+
"extLineItemId": {
6+
"type": "string",
7+
"description": "A unique identifier for your Line Item"
8+
},
9+
"title": {
10+
"type": "string",
11+
"description": "A Line Item title of your choosing"
12+
},
13+
"countryISOCode": {
14+
"type": "string",
15+
"description": "2 letter ISO Country Code",
16+
"minLength": 2,
17+
"maxLength": 2
18+
},
19+
"languageISOCode": {
20+
"type": "string",
21+
"description": "2 letter ISO Language Code",
22+
"minLength": 2,
23+
"maxLength": 2
24+
},
25+
"surveyURL": {
26+
"type": "string",
27+
"description": "Survey URL to send panelist into. "
28+
},
29+
"surveyTestURL": {
30+
"type": "string",
31+
"description": "Survey Test URL. Required for survey verification"
32+
},
33+
"indicativeIncidence": {
34+
"type": "integer",
35+
"description": "Percent of panelists you expect to qualify for the survey after they go in"
36+
},
37+
"daysInField": {
38+
"type": "integer",
39+
"description": "Number of days the survey should be active in the field. We do not stop the survey after daysInField has expired"
40+
},
41+
"lengthOfInterview": {
42+
"type": "integer",
43+
"description": "Average number of minutes it takes a user to complete your survey"
44+
},
45+
"deliveryType": {
46+
"type": "string",
47+
"default": "BALANCED",
48+
"description": "The plan on how responses will flow into the survey.",
49+
"enum": [
50+
"SLOW",
51+
"BALANCED",
52+
"FAST"
53+
]
54+
},
55+
"sources": {
56+
"type": "array",
57+
"description": "The supplier source that you would like to buy sample from. You can get the list of sources available to your account using the [Get List of Sources](/demand-api-reference/data_endpoints/supplier-sources/get-sources) endpoint",
58+
"default": 100,
59+
"items": {
60+
"type": "object",
61+
"properties": {
62+
"id": {
63+
"type": "integer"
64+
}
65+
}
66+
}
67+
},
68+
"targets": {
69+
"type": "array",
70+
"description": "Total count of survey completes required for this line item",
71+
"items": {
72+
"type": "object",
73+
"properties": {
74+
"count": {
75+
"description": "Total number of counts required for this line item for the specified target type",
76+
"type": "integer"
77+
},
78+
"dailyLimit": {
79+
"description": "Total number of daily counts required for this line item",
80+
"type": "integer"
81+
},
82+
"type": {
83+
"type": "string",
84+
"description": "The type of counts required for this line item.",
85+
"enum": [
86+
"COMPLETE"
87+
]
88+
}
89+
}
90+
}
91+
},
92+
"quotaPlan": {
93+
"type": "object",
94+
"title": "Quota Plan",
95+
"description": "Defines the type of respondents you want to invite for the survey",
96+
"properties": {
97+
"filters": {
98+
"type": "array",
99+
"description": "Filters are minimum set of targeting that every respondent must have in order to qualify for the study. Only attributes that have `isAllowedInFilters = true` is allowed to be used in `filters`",
100+
"items": {
101+
"type": "object",
102+
"properties": {
103+
"attributeId": {
104+
"type": "string",
105+
"description": "The attribute you want to target respondents on"
106+
},
107+
"options": {
108+
"type": "array",
109+
"description": "The options of the attribute you want to target respondents on",
110+
"uniqueItems": true,
111+
"items": {
112+
"type": "string"
113+
}
114+
},
115+
"operator": {
116+
"type": "string",
117+
"enum": [
118+
"exclude",
119+
"include"
120+
],
121+
"default": "include",
122+
"description": "The operator to use for the attribute options."
123+
}
124+
}
125+
}
126+
},
127+
"quotaGroups": {
128+
"type": "array",
129+
"description": "Quota groups define the allocated targeting attributes for panelists within this line item. Only attributes that have `isAllowedInQuotas = true` is allowed in `quotaGroups`.",
130+
"items": {
131+
"type": "object",
132+
"properties": {
133+
"name": {
134+
"type": "string",
135+
"description": "A quota group name of your choosing"
136+
},
137+
"quotaCells": {
138+
"type": "array",
139+
"description": "Quota Cells define the percentage allocation for the required targeting. A quota cell is made up of a collection of quota Nodes",
140+
"items": {
141+
"type": "object",
142+
"properties": {
143+
"quotaNodes": {
144+
"type": "array",
145+
"description": "Quota Nodes define the collection of attributes and options being targeted.",
146+
"items": {
147+
"type": "object",
148+
"properties": {
149+
"attributeId": {
150+
"type": "string",
151+
"description": "The attribute you want to target respondents on"
152+
},
153+
"options": {
154+
"type": "array",
155+
"description": "The options of the attribute you want to target respondents on",
156+
"uniqueItems": true,
157+
"items": {
158+
"type": "string"
159+
}
160+
},
161+
"operator": {
162+
"type": "string",
163+
"enum": [
164+
"exclude",
165+
"include"
166+
],
167+
"default": "include",
168+
"description": "**Deprecated field** The operator to use for the attribute options."
169+
}
170+
}
171+
}
172+
},
173+
"count": {
174+
"type": "integer",
175+
"description": "The count of respondents you want to qualify for the defined quota cell"
176+
}
177+
}
178+
}
179+
}
180+
}
181+
}
182+
}
183+
}
184+
}
185+
},
186+
"required": [
187+
"extLineItemId",
188+
"countryISOCode",
189+
"languageISOCode",
190+
"indicativeIncidence",
191+
"daysInField",
192+
"lengthOfInterview",
193+
"targets"
194+
]
195+
}

tests/test_attributes.py

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,6 @@
55
import unittest
66
import responses
77

8-
try:
9-
from unittest.mock import patch
10-
except ImportError:
11-
from mock import patch
12-
138
from dynatademand.api import DemandAPIClient
149

1510
BASE_HOST = "http://test-url.example"

tests/test_categories.py

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,6 @@
55
import unittest
66
import responses
77

8-
try:
9-
from unittest.mock import patch
10-
except ImportError:
11-
from mock import patch
12-
138
from dynatademand.api import DemandAPIClient
149

1510
BASE_HOST = "http://test-url.example"
@@ -24,7 +19,11 @@ def setUp(self):
2419
def test_get_survey_topics(self):
2520
with open('./tests/test_files/get_survey_topics.json', 'r') as survey_topics_file:
2621
survey_topics_json = json.load(survey_topics_file)
27-
responses.add(responses.GET, '{}/sample/v1/categories/surveyTopics'.format(BASE_HOST), json=survey_topics_json, status=200)
22+
responses.add(
23+
responses.GET,
24+
'{}/sample/v1/categories/surveyTopics'.format(BASE_HOST),
25+
json=survey_topics_json,
26+
status=200)
2827
self.api.get_survey_topics()
2928
self.assertEqual(len(responses.calls), 1)
3029
self.assertEqual(responses.calls[0].response.json(), survey_topics_json)

tests/test_countries.py

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,6 @@
55
import unittest
66
import responses
77

8-
try:
9-
from unittest.mock import patch
10-
except ImportError:
11-
from mock import patch
12-
138
from dynatademand.api import DemandAPIClient
149

1510
BASE_HOST = "http://test-url.example"

tests/test_events.py

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,6 @@
55
import unittest
66
import responses
77

8-
try:
9-
from unittest.mock import patch
10-
except ImportError:
11-
from mock import patch
12-
138
from dynatademand.api import DemandAPIClient
149

1510
BASE_HOST = "http://test-url.example"

0 commit comments

Comments
 (0)