-
Notifications
You must be signed in to change notification settings - Fork 76
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Adding auth implementation of prolific client
- Loading branch information
Showing
11 changed files
with
604 additions
and
295 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
#!/usr/bin/env python3 | ||
|
||
# Copyright (c) Facebook, Inc. and its affiliates. | ||
# This source code is licensed under the MIT license found in the | ||
# LICENSE file in the root directory of this source tree. | ||
|
||
from typing import Type, TypeVar, cast | ||
|
||
from .base_api_resource import BaseAPIResource | ||
from .bonuses import Bonuses as _Bonuses | ||
from .eligibility_requirements import ( | ||
EligibilityRequirements as _EligibilityRequirements, | ||
) | ||
from .invitations import Invitations as _Invitations | ||
from .messages import Messages as _Messages | ||
from .participant_groups import ParticipantGroups as _ParticipantGroups | ||
from .projects import Projects as _Projects | ||
from .studies import Studies as _Studies | ||
from .submissions import Submissions as _Submissions | ||
from .users import Users as _Users | ||
from .workspaces import Workspaces as _Workspaces | ||
|
||
T = TypeVar("T") | ||
|
||
|
||
def wrap_class(target_cls: Type[T], api_key: str) -> Type[T]: | ||
""" | ||
Create a wrapper around the given BaseAPIResource to have the | ||
api_key pre-bound | ||
""" | ||
assert issubclass(target_cls, BaseAPIResource), "Can only wrap BaseAPIResource" | ||
|
||
class Wrapper(target_cls): | ||
@classmethod | ||
def _base_request(cls, *args, **kwargs): | ||
new_args = {k: v for k, v in kwargs.items()} | ||
if new_args.get("api_key", None) is None: | ||
new_args["api_key"] = api_key | ||
return super()._base_request(*args, **new_args) | ||
|
||
return cast(Type[T], Wrapper) | ||
|
||
|
||
class ProlificClient: | ||
|
||
Bonuses: Type[_Bonuses] | ||
EligibilityRequirements: Type[_EligibilityRequirements] | ||
Invitations: Type[_Invitations] | ||
Messages: Type[_Messages] | ||
ParticipantGroups: Type[_ParticipantGroups] | ||
Projects: Type[_Projects] | ||
Studies: Type[_Studies] | ||
Submissions: Type[_Submissions] | ||
Users: Type[_Users] | ||
Workspaces: Type[_Workspaces] | ||
|
||
def __init__(self, api_key: str): | ||
""" | ||
Creates a client that can be used to call all of the | ||
prolific data model using the provided key. | ||
""" | ||
self.Bonuses = wrap_class(_Bonuses, api_key) | ||
self.EligibilityRequirements = wrap_class(_EligibilityRequirements, api_key) | ||
self.Invitations = wrap_class(_Invitations, api_key) | ||
self.Messages = wrap_class(_Messages, api_key) | ||
self.ParticipantGroups = wrap_class(_ParticipantGroups, api_key) | ||
self.Projects = wrap_class(_Projects, api_key) | ||
self.Studies = wrap_class(_Studies, api_key) | ||
self.Submissions = wrap_class(_Submissions, api_key) | ||
self.Users = wrap_class(_Users, api_key) | ||
self.Workspaces = wrap_class(_Workspaces, api_key) |
127 changes: 70 additions & 57 deletions
127
mephisto/abstractions/providers/prolific/api/constants.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,102 +1,115 @@ | ||
EMAIL_FORMAT = '^\\S+@\\S+\\.\\S+$' # Simple email format checking | ||
EMAIL_FORMAT = "^\\S+@\\S+\\.\\S+$" # Simple email format checking | ||
|
||
|
||
# --- Studies --- | ||
|
||
# HACK: Hardcoded Question IDs (Prolific doesn't have a better way for now) | ||
# TODO (#1008): Make this dynamic as soon as possible | ||
ER_AGE_RANGE_QUESTION_ID = '54ac6ea9fdf99b2204feb893' | ||
ER_AGE_RANGE_QUESTION_ID = "54ac6ea9fdf99b2204feb893" | ||
|
||
# https://docs.prolific.co/docs/api-docs/public/#tag/Studies/The-study-object | ||
# `external_study_url` field | ||
STUDY_URL_PARTICIPANT_ID_PARAM = 'participant_id' | ||
STUDY_URL_PARTICIPANT_ID_PARAM_PROLIFIC_VAR = '{{%PROLIFIC_PID%}}' | ||
STUDY_URL_STUDY_ID_PARAM = 'study_id' | ||
STUDY_URL_STUDY_ID_PARAM_PROLIFIC_VAR = '{{%STUDY_ID%}}' | ||
STUDY_URL_SUBMISSION_ID_PARAM = 'submission_id' | ||
STUDY_URL_SUBMISSION_ID_PARAM_PROLIFIC_VAR = '{{%SESSION_ID%}}' | ||
STUDY_URL_PARTICIPANT_ID_PARAM = "participant_id" | ||
STUDY_URL_PARTICIPANT_ID_PARAM_PROLIFIC_VAR = "{{%PROLIFIC_PID%}}" | ||
STUDY_URL_STUDY_ID_PARAM = "study_id" | ||
STUDY_URL_STUDY_ID_PARAM_PROLIFIC_VAR = "{{%STUDY_ID%}}" | ||
STUDY_URL_SUBMISSION_ID_PARAM = "submission_id" | ||
STUDY_URL_SUBMISSION_ID_PARAM_PROLIFIC_VAR = "{{%SESSION_ID%}}" | ||
|
||
|
||
class ProlificIDOption: | ||
NOT_REQUIRED = 'not_required' | ||
QUESTION = 'question' | ||
URL_PARAMETERS = 'url_parameters' | ||
NOT_REQUIRED = "not_required" | ||
QUESTION = "question" | ||
URL_PARAMETERS = "url_parameters" | ||
|
||
|
||
class StudyAction: | ||
AUTOMATICALLY_APPROVE = 'AUTOMATICALLY_APPROVE' | ||
MANUALLY_REVIEW = 'MANUALLY_REVIEW' | ||
PUBLISH = 'PUBLISH' | ||
START = 'START' | ||
STOP = 'STOP' | ||
UNPUBLISHED = 'UNPUBLISHED' | ||
AUTOMATICALLY_APPROVE = "AUTOMATICALLY_APPROVE" | ||
MANUALLY_REVIEW = "MANUALLY_REVIEW" | ||
PUBLISH = "PUBLISH" | ||
START = "START" | ||
STOP = "STOP" | ||
UNPUBLISHED = "UNPUBLISHED" | ||
|
||
|
||
class StudyStatus: | ||
UNPUBLISHED = 'UNPUBLISHED' | ||
ACTIVE = 'ACTIVE' | ||
SCHEDULED = 'SCHEDULED' | ||
PAUSED = 'PAUSED' | ||
AWAITING_REVIEW = 'AWAITING REVIEW' | ||
COMPLETED = 'COMPLETED' | ||
_EXPIRED = 'EXPIRED' # Pseudo status that we will use in `Study.internal_name` as a hack | ||
UNPUBLISHED = "UNPUBLISHED" | ||
ACTIVE = "ACTIVE" | ||
SCHEDULED = "SCHEDULED" | ||
PAUSED = "PAUSED" | ||
AWAITING_REVIEW = "AWAITING REVIEW" | ||
COMPLETED = "COMPLETED" | ||
_EXPIRED = ( | ||
"EXPIRED" # Pseudo status that we will use in `Study.internal_name` as a hack | ||
) | ||
|
||
|
||
class StudyCompletionOption: | ||
CODE = 'code' | ||
URL = 'url' | ||
CODE = "code" | ||
URL = "url" | ||
|
||
|
||
class StudyCodeType: | ||
COMPLETED = 'COMPLETED' | ||
FAILED_ATTENTION_CHECK = 'FAILED_ATTENTION_CHECK' | ||
FOLLOW_UP_STUDY = 'FOLLOW_UP_STUDY' | ||
GIVE_BONUS = 'GIVE_BONUS' | ||
INCOMPATIBLE_DEVICE = 'INCOMPATIBLE_DEVICE' | ||
NO_CONSENT = 'NO_CONSENT' | ||
OTHER = 'OTHER' | ||
COMPLETED = "COMPLETED" | ||
FAILED_ATTENTION_CHECK = "FAILED_ATTENTION_CHECK" | ||
FOLLOW_UP_STUDY = "FOLLOW_UP_STUDY" | ||
GIVE_BONUS = "GIVE_BONUS" | ||
INCOMPATIBLE_DEVICE = "INCOMPATIBLE_DEVICE" | ||
NO_CONSENT = "NO_CONSENT" | ||
OTHER = "OTHER" | ||
|
||
|
||
# --- Submissions --- | ||
|
||
# It must be at least 100 chars long | ||
DEFAULT_REJECTION_CATEGORY_MESSAGE = ( | ||
'This is default automatical rejection message ' | ||
'as Prolific requires some text at least 100 chars long.' | ||
"This is default automatical rejection message " | ||
"as Prolific requires some text at least 100 chars long." | ||
) | ||
|
||
|
||
class SubmissionStatus: | ||
""" | ||
Submission statuses explained | ||
https://researcher-help.prolific.co/hc/en-gb/articles/360009094114-Submission-statuses-explained | ||
""" | ||
RESERVED = 'RESERVED' | ||
ACTIVE = 'ACTIVE' | ||
TIMED_OUT = 'TIMED-OUT' | ||
AWAITING_REVIEW = 'AWAITING REVIEW' | ||
APPROVED = 'APPROVED' | ||
RETURNED = 'RETURNED' | ||
REJECTED = 'REJECTED' | ||
|
||
RESERVED = "RESERVED" | ||
ACTIVE = "ACTIVE" | ||
TIMED_OUT = "TIMED-OUT" | ||
AWAITING_REVIEW = "AWAITING REVIEW" | ||
APPROVED = "APPROVED" | ||
RETURNED = "RETURNED" | ||
REJECTED = "REJECTED" | ||
# After you approve or reject a submission, it may have the ‘Processing’ status | ||
# for a short time before showing as ‘Approved’ or ‘Rejected’. | ||
PROCESSING = 'PROCESSING' | ||
PROCESSING = "PROCESSING" | ||
|
||
|
||
class SubmissionAction: | ||
APPROVE = 'APPROVE' | ||
REJECT = 'REJECT' | ||
APPROVE = "APPROVE" | ||
REJECT = "REJECT" | ||
|
||
|
||
class SubmissionRejectionCategory: | ||
BAD_CODE = 'BAD_CODE' | ||
FAILED_CHECK = 'FAILED_CHECK' | ||
FAILED_INSTRUCTIONS = 'FAILED_INSTRUCTIONS' | ||
INCOMP_LONGITUDINAL = 'INCOMP_LONGITUDINAL' | ||
LOW_EFFORT = 'LOW_EFFORT' | ||
MALINGERING = 'MALINGERING' | ||
NO_CODE = 'NO_CODE' | ||
NO_DATA = 'NO_DATA' | ||
OTHER = 'OTHER' | ||
TOO_QUICKLY = 'TOO_QUICKLY' | ||
TOO_SLOWLY = 'TOO_SLOWLY' | ||
UNSUPP_DEVICE = 'UNSUPP_DEVICE' | ||
BAD_CODE = "BAD_CODE" | ||
FAILED_CHECK = "FAILED_CHECK" | ||
FAILED_INSTRUCTIONS = "FAILED_INSTRUCTIONS" | ||
INCOMP_LONGITUDINAL = "INCOMP_LONGITUDINAL" | ||
LOW_EFFORT = "LOW_EFFORT" | ||
MALINGERING = "MALINGERING" | ||
NO_CODE = "NO_CODE" | ||
NO_DATA = "NO_DATA" | ||
OTHER = "OTHER" | ||
TOO_QUICKLY = "TOO_QUICKLY" | ||
TOO_SLOWLY = "TOO_SLOWLY" | ||
UNSUPP_DEVICE = "UNSUPP_DEVICE" | ||
|
||
|
||
# --- Workspaces --- | ||
|
||
|
||
class WorkspaceRole: | ||
WORKSPACE_ADMIN = "WORKSPACE_ADMIN" | ||
WORKSPACE_COLLABORATOR = "WORKSPACE_COLLABORATOR" | ||
PROJECT_EDITOR = "PROJECT_EDITOR" |
Oops, something went wrong.