Skip to content

Commit 938cf26

Browse files
committed
Add support for the endpoint /challenge/{id}/addFileTasks, closes #83
1 parent a10b1f3 commit 938cf26

2 files changed

Lines changed: 68 additions & 0 deletions

File tree

maproulette/api/challenge.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,29 @@ def add_tasks_to_challenge(self, data, challenge_id):
278278
body=data)
279279
return response
280280

281+
def add_file_tasks_to_challenge(self, data, challenge_id, line_by_line="true", remove_unmatched="false", data_origin_date="", skip_snapshot="false"):
282+
"""Method to add tasks to an existing challenge with tasks as GeoJSON
283+
284+
:param data: a GeoJSON containing geometry of tasks to be added to a challenge
285+
:param challenge_id: the ID corresponding to the challenge that tasks will be added to
286+
:param lineByLine: whether or not the provided data is in line-by-line GeoJSON format
287+
:param skipSnapshot: whether or not to skip recording a snapshot before proceeding
288+
:returns: the API response from the PUT request
289+
"""
290+
query_params = {
291+
"lineByLine": str(line_by_line),
292+
"removeUnmatched": str(remove_unmatched),
293+
"dataOriginDate": str(data_origin_date),
294+
"skipSnapshot": str(skip_snapshot)
295+
}
296+
body = {'json': ('data', data)} # server only accepts dict with key 'json'
297+
298+
response = self.put_file(
299+
endpoint=f"/challenge/{challenge_id}/addFileTasks",
300+
body=body,
301+
params=query_params)
302+
return response
303+
281304
def delete_challenge(self, challenge_id, immediate="false"):
282305
"""Method to delete a challenge by using the corresponding challenge ID
283306

maproulette/api/maproulette_server.py

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,51 @@ def put(self, endpoint, body=None, params=None):
180180
"status": response.status_code
181181
}
182182

183+
def put_file(self, endpoint, body=None, params=None):
184+
"""Method that completes a multipart PUT request to the MapRoulette API
185+
186+
:param endpoint: the server endpoint to use for the PUT request
187+
:param body: the body of the request (optional)
188+
:param params: the parameters that pertain to the request (optional)
189+
:returns: a dictionary containing the API response status code as well as the decoded JSON response if decoding
190+
was successful. If not, the response text is returned.
191+
"""
192+
response = self.session.put(
193+
self.url + endpoint,
194+
params=params,
195+
files=body
196+
)
197+
try:
198+
response.raise_for_status()
199+
except requests.exceptions.HTTPError as e:
200+
if e.response.status_code == 400:
201+
raise InvalidJsonError(
202+
message=self.parse_response_message(e.response),
203+
status=e.response.status_code
204+
) from None
205+
elif e.response.status_code == 401:
206+
raise UnauthorizedError(
207+
message=self.parse_response_message(e.response),
208+
status=e.response.status_code
209+
) from None
210+
else:
211+
raise HttpError(
212+
message=self.parse_response_message(e.response),
213+
status=e.response.status_code
214+
) from None
215+
except (requests.ConnectionError, requests.Timeout) as e:
216+
raise ConnectionUnavailableError(e) from None
217+
try:
218+
return {
219+
"data": response.json(),
220+
"status": response.status_code
221+
}
222+
except ValueError:
223+
return {
224+
"data": response.text,
225+
"status": response.status_code
226+
}
227+
183228
def delete(self, endpoint, params=None):
184229
"""Method that completes a DELETE request to the MapRoulette API
185230

0 commit comments

Comments
 (0)