Project module
Methods attached to the Kili client, to run actions on projects.
Source code in kili/presentation/client/project.py
          class ProjectClientMethods(BaseClientMethods):
    """Methods attached to the Kili client, to run actions on projects."""
    @typechecked
    # pylint: disable=too-many-arguments
    def create_project(
        self,
        input_type: InputType,
        json_interface: Dict,
        title: str,
        description: str = "",
        project_type: Optional[ProjectType] = None,
        tags: Optional[ListOrTuple[str]] = None,
    ) -> Dict[Literal["id"], str]:
        # pylint: disable=line-too-long
        """Create a project.
        Args:
            input_type: Currently, one of `IMAGE`, `PDF`, `TEXT` or `VIDEO`.
            json_interface: The json parameters of the project, see Edit your interface.
            title: Title of the project.
            description: Description of the project.
            project_type: Currently, one of:
                - `IMAGE_CLASSIFICATION_MULTI`
                - `IMAGE_CLASSIFICATION_SINGLE`
                - `IMAGE_OBJECT_DETECTION_POLYGON`
                - `IMAGE_OBJECT_DETECTION_RECTANGLE`
                - `IMAGE_OBJECT_DETECTION_SEMANTIC`
                - `IMAGE_POSE_ESTIMATION`
                - `OCR`
                - `PDF_CLASSIFICATION_MULTI`
                - `PDF_CLASSIFICATION_SINGLE`
                - `PDF_NAMED_ENTITY_RECOGNITION`
                - `PDF_OBJECT_DETECTION_RECTANGLE`
                - `SPEECH_TO_TEXT`
                - `TEXT_CLASSIFICATION_MULTI`
                - `TEXT_CLASSIFICATION_SINGLE`
                - `TEXT_NER`
                - `TEXT_TRANSCRIPTION`
                - `TIME_SERIES`
                - `VIDEO_CLASSIFICATION_SINGLE`
                - `VIDEO_FRAME_CLASSIFICATION`
                - `VIDEO_FRAME_OBJECT_TRACKING`
            tags: Tags to add to the project. The tags must already exist in the organization.
        Returns:
            A dict with the id of the created project.
        Examples:
            >>> kili.create_project(input_type='IMAGE', json_interface=json_interface, title='Example')
        !!! example "Recipe"
            For more detailed examples on how to create projects,
                see [the recipe](https://docs.kili-technology.com/recipes/creating-a-project).
        """
        project_id = ProjectUseCases(self.kili_api_gateway).create_project(
            input_type=input_type,
            json_interface=json_interface,
            title=title,
            description=description,
            project_type=project_type,
        )
        if tags is not None:
            tag_use_cases = TagUseCases(self.kili_api_gateway)
            tag_ids = tag_use_cases.get_tag_ids_from_labels(labels=tags)
            tag_use_cases.tag_project(
                project_id=project_id, tag_ids=cast(ListOrTuple[TagId], tag_ids), disable_tqdm=True
            )
        return {"id": project_id}
    @overload
    # pylint: disable=too-many-arguments
    def projects(
        self,
        project_id: Optional[str] = None,
        search_query: Optional[str] = None,
        should_relaunch_kpi_computation: Optional[bool] = None,
        updated_at_gte: Optional[str] = None,
        updated_at_lte: Optional[str] = None,
        archived: Optional[bool] = None,
        starred: Optional[bool] = None,
        tags_in: Optional[ListOrTuple[str]] = None,
        fields: ListOrTuple[str] = (
            "consensusTotCoverage",
            "id",
            "inputType",
            "jsonInterface",
            "minConsensusSize",
            "reviewCoverage",
            "roles.id",
            "roles.role",
            "roles.user.email",
            "roles.user.id",
            "title",
        ),
        first: Optional[int] = None,
        skip: int = 0,
        disable_tqdm: Optional[bool] = None,
        *,
        as_generator: Literal[True],
    ) -> Generator[Dict, None, None]: ...
    @overload
    # pylint: disable=too-many-arguments
    def projects(
        self,
        project_id: Optional[str] = None,
        search_query: Optional[str] = None,
        should_relaunch_kpi_computation: Optional[bool] = None,
        updated_at_gte: Optional[str] = None,
        updated_at_lte: Optional[str] = None,
        archived: Optional[bool] = None,
        starred: Optional[bool] = None,
        tags_in: Optional[ListOrTuple[str]] = None,
        fields: ListOrTuple[str] = (
            "consensusTotCoverage",
            "id",
            "inputType",
            "jsonInterface",
            "minConsensusSize",
            "reviewCoverage",
            "roles.id",
            "roles.role",
            "roles.user.email",
            "roles.user.id",
            "title",
        ),
        first: Optional[int] = None,
        skip: int = 0,
        disable_tqdm: Optional[bool] = None,
        *,
        as_generator: Literal[False] = False,
    ) -> List[Dict]: ...
    @typechecked
    # pylint: disable=too-many-arguments,too-many-locals
    def projects(
        self,
        project_id: Optional[str] = None,
        search_query: Optional[str] = None,
        should_relaunch_kpi_computation: Optional[bool] = None,
        updated_at_gte: Optional[str] = None,
        updated_at_lte: Optional[str] = None,
        archived: Optional[bool] = None,
        starred: Optional[bool] = None,
        tags_in: Optional[ListOrTuple[str]] = None,
        fields: ListOrTuple[str] = (
            "consensusTotCoverage",
            "id",
            "inputType",
            "jsonInterface",
            "minConsensusSize",
            "reviewCoverage",
            "roles.id",
            "roles.role",
            "roles.user.email",
            "roles.user.id",
            "title",
        ),
        first: Optional[int] = None,
        skip: int = 0,
        disable_tqdm: Optional[bool] = None,
        *,
        as_generator: bool = False,
    ) -> Iterable[Dict]:
        # pylint: disable=line-too-long
        """Get a generator or a list of projects that match a set of criteria.
        Args:
            project_id: Select a specific project through its project_id.
            search_query: Returned projects with a title or a description matching this [PostgreSQL ILIKE](https://www.postgresql.org/docs/current/functions-matching.html#FUNCTIONS-LIKE) pattern.
            should_relaunch_kpi_computation: Deprecated, do not use.
            updated_at_gte: Returned projects should have a label whose update date is greater or equal
                to this date.
            updated_at_lte: Returned projects should have a label whose update date is lower or equal to this date.
            archived: If `True`, only archived projects are returned, if `False`, only active projects are returned.
                `None` disables this filter.
            starred: If `True`, only starred projects are returned, if `False`, only unstarred projects are returned.
                `None` disables this filter.
            tags_in: Returned projects should have at least one of these tags.
            fields: All the fields to request among the possible fields for the projects.
                See [the documentation](https://docs.kili-technology.com/reference/graphql-api#project) for all possible fields.
            first: Maximum number of projects to return.
            skip: Number of projects to skip (they are ordered by their creation).
            disable_tqdm: If `True`, the progress bar will be disabled.
            as_generator: If `True`, a generator on the projects is returned.
        !!! info "Dates format"
            Date strings should have format: "YYYY-MM-DD"
        Returns:
            A list of projects or a generator of projects if `as_generator` is `True`.
        Examples:
            >>> # List all my projects
            >>> kili.projects()
        """
        tag_ids = (
            TagUseCases(self.kili_api_gateway).get_tag_ids_from_labels(tags_in) if tags_in else None
        )
        projects_gen = ProjectUseCases(self.kili_api_gateway).list_projects(
            ProjectFilters(
                id=ProjectId(project_id) if project_id else None,
                archived=archived,
                search_query=search_query,
                should_relaunch_kpi_computation=should_relaunch_kpi_computation,
                starred=starred,
                updated_at_gte=updated_at_gte,
                updated_at_lte=updated_at_lte,
                created_at_gte=None,
                created_at_lte=None,
                tag_ids=tag_ids,
            ),
            fields,
            first,
            skip,
            disable_tqdm,
        )
        if as_generator:
            return projects_gen
        return list(projects_gen)
create_project(self, input_type, json_interface, title, description='', project_type=None, tags=None)
    Create a project.
Parameters:
| Name | Type | Description | Default | 
|---|---|---|---|
| input_type | Literal['IMAGE', 'PDF', 'TEXT', 'VIDEO', 'VIDEO_LEGACY'] | Currently, one of  | required | 
| json_interface | Dict | The json parameters of the project, see Edit your interface. | required | 
| title | str | Title of the project. | required | 
| description | str | Description of the project. | '' | 
| project_type | Optional[Literal['IMAGE_CLASSIFICATION_SINGLE', 'IMAGE_CLASSIFICATION_MULTI', 'IMAGE_OBJECT_DETECTION_RECTANGLE', 'IMAGE_OBJECT_DETECTION_POLYGON', 'IMAGE_OBJECT_DETECTION_SEMANTIC', 'IMAGE_POSE_ESTIMATION', 'OCR', 'PDF_CLASSIFICATION_SINGLE', 'PDF_CLASSIFICATION_MULTI', 'PDF_OBJECT_DETECTION_RECTANGLE', 'PDF_NAMED_ENTITY_RECOGNITION', 'SPEECH_TO_TEXT', 'TEXT_CLASSIFICATION_SINGLE', 'TEXT_CLASSIFICATION_MULTI', 'TEXT_TRANSCRIPTION', 'TEXT_NER', 'TIME_SERIES', 'VIDEO_CLASSIFICATION_SINGLE', 'VIDEO_OBJECT_DETECTION', 'VIDEO_FRAME_CLASSIFICATION', 'VIDEO_FRAME_OBJECT_TRACKING']] | Currently, one of: 
 | None | 
| tags | Union[List[str], Tuple[str, ...]] | Tags to add to the project. The tags must already exist in the organization. | None | 
Returns:
| Type | Description | 
|---|---|
| Dict[Literal['id'], str] | A dict with the id of the created project. | 
Examples:
>>> kili.create_project(input_type='IMAGE', json_interface=json_interface, title='Example')
Recipe
For more detailed examples on how to create projects, see the recipe.
Source code in kili/presentation/client/project.py
          @typechecked
# pylint: disable=too-many-arguments
def create_project(
    self,
    input_type: InputType,
    json_interface: Dict,
    title: str,
    description: str = "",
    project_type: Optional[ProjectType] = None,
    tags: Optional[ListOrTuple[str]] = None,
) -> Dict[Literal["id"], str]:
    # pylint: disable=line-too-long
    """Create a project.
    Args:
        input_type: Currently, one of `IMAGE`, `PDF`, `TEXT` or `VIDEO`.
        json_interface: The json parameters of the project, see Edit your interface.
        title: Title of the project.
        description: Description of the project.
        project_type: Currently, one of:
            - `IMAGE_CLASSIFICATION_MULTI`
            - `IMAGE_CLASSIFICATION_SINGLE`
            - `IMAGE_OBJECT_DETECTION_POLYGON`
            - `IMAGE_OBJECT_DETECTION_RECTANGLE`
            - `IMAGE_OBJECT_DETECTION_SEMANTIC`
            - `IMAGE_POSE_ESTIMATION`
            - `OCR`
            - `PDF_CLASSIFICATION_MULTI`
            - `PDF_CLASSIFICATION_SINGLE`
            - `PDF_NAMED_ENTITY_RECOGNITION`
            - `PDF_OBJECT_DETECTION_RECTANGLE`
            - `SPEECH_TO_TEXT`
            - `TEXT_CLASSIFICATION_MULTI`
            - `TEXT_CLASSIFICATION_SINGLE`
            - `TEXT_NER`
            - `TEXT_TRANSCRIPTION`
            - `TIME_SERIES`
            - `VIDEO_CLASSIFICATION_SINGLE`
            - `VIDEO_FRAME_CLASSIFICATION`
            - `VIDEO_FRAME_OBJECT_TRACKING`
        tags: Tags to add to the project. The tags must already exist in the organization.
    Returns:
        A dict with the id of the created project.
    Examples:
        >>> kili.create_project(input_type='IMAGE', json_interface=json_interface, title='Example')
    !!! example "Recipe"
        For more detailed examples on how to create projects,
            see [the recipe](https://docs.kili-technology.com/recipes/creating-a-project).
    """
    project_id = ProjectUseCases(self.kili_api_gateway).create_project(
        input_type=input_type,
        json_interface=json_interface,
        title=title,
        description=description,
        project_type=project_type,
    )
    if tags is not None:
        tag_use_cases = TagUseCases(self.kili_api_gateway)
        tag_ids = tag_use_cases.get_tag_ids_from_labels(labels=tags)
        tag_use_cases.tag_project(
            project_id=project_id, tag_ids=cast(ListOrTuple[TagId], tag_ids), disable_tqdm=True
        )
    return {"id": project_id}
projects(self, project_id=None, search_query=None, should_relaunch_kpi_computation=None, updated_at_gte=None, updated_at_lte=None, archived=None, starred=None, tags_in=None, fields=('consensusTotCoverage', 'id', 'inputType', 'jsonInterface', 'minConsensusSize', 'reviewCoverage', 'roles.id', 'roles.role', 'roles.user.email', 'roles.user.id', 'title'), first=None, skip=0, disable_tqdm=None, *, as_generator=False)
    Get a generator or a list of projects that match a set of criteria.
Parameters:
| Name | Type | Description | Default | 
|---|---|---|---|
| project_id | Optional[str] | Select a specific project through its project_id. | None | 
| search_query | Optional[str] | Returned projects with a title or a description matching this PostgreSQL ILIKE pattern. | None | 
| should_relaunch_kpi_computation | Optional[bool] | Deprecated, do not use. | None | 
| updated_at_gte | Optional[str] | Returned projects should have a label whose update date is greater or equal to this date. | None | 
| updated_at_lte | Optional[str] | Returned projects should have a label whose update date is lower or equal to this date. | None | 
| archived | Optional[bool] | If  | None | 
| starred | Optional[bool] | If  | None | 
| tags_in | Union[List[str], Tuple[str, ...]] | Returned projects should have at least one of these tags. | None | 
| fields | Union[List[str], Tuple[str, ...]] | All the fields to request among the possible fields for the projects. See the documentation for all possible fields. | ('consensusTotCoverage', 'id', 'inputType', 'jsonInterface', 'minConsensusSize', 'reviewCoverage', 'roles.id', 'roles.role', 'roles.user.email', 'roles.user.id', 'title') | 
| first | Optional[int] | Maximum number of projects to return. | None | 
| skip | int | Number of projects to skip (they are ordered by their creation). | 0 | 
| disable_tqdm | Optional[bool] | If  | None | 
| as_generator | bool | If  | False | 
Dates format
Date strings should have format: "YYYY-MM-DD"
Returns:
| Type | Description | 
|---|---|
| Iterable[Dict] | A list of projects or a generator of projects if  | 
Examples:
>>> # List all my projects
>>> kili.projects()
Source code in kili/presentation/client/project.py
          @typechecked
# pylint: disable=too-many-arguments,too-many-locals
def projects(
    self,
    project_id: Optional[str] = None,
    search_query: Optional[str] = None,
    should_relaunch_kpi_computation: Optional[bool] = None,
    updated_at_gte: Optional[str] = None,
    updated_at_lte: Optional[str] = None,
    archived: Optional[bool] = None,
    starred: Optional[bool] = None,
    tags_in: Optional[ListOrTuple[str]] = None,
    fields: ListOrTuple[str] = (
        "consensusTotCoverage",
        "id",
        "inputType",
        "jsonInterface",
        "minConsensusSize",
        "reviewCoverage",
        "roles.id",
        "roles.role",
        "roles.user.email",
        "roles.user.id",
        "title",
    ),
    first: Optional[int] = None,
    skip: int = 0,
    disable_tqdm: Optional[bool] = None,
    *,
    as_generator: bool = False,
) -> Iterable[Dict]:
    # pylint: disable=line-too-long
    """Get a generator or a list of projects that match a set of criteria.
    Args:
        project_id: Select a specific project through its project_id.
        search_query: Returned projects with a title or a description matching this [PostgreSQL ILIKE](https://www.postgresql.org/docs/current/functions-matching.html#FUNCTIONS-LIKE) pattern.
        should_relaunch_kpi_computation: Deprecated, do not use.
        updated_at_gte: Returned projects should have a label whose update date is greater or equal
            to this date.
        updated_at_lte: Returned projects should have a label whose update date is lower or equal to this date.
        archived: If `True`, only archived projects are returned, if `False`, only active projects are returned.
            `None` disables this filter.
        starred: If `True`, only starred projects are returned, if `False`, only unstarred projects are returned.
            `None` disables this filter.
        tags_in: Returned projects should have at least one of these tags.
        fields: All the fields to request among the possible fields for the projects.
            See [the documentation](https://docs.kili-technology.com/reference/graphql-api#project) for all possible fields.
        first: Maximum number of projects to return.
        skip: Number of projects to skip (they are ordered by their creation).
        disable_tqdm: If `True`, the progress bar will be disabled.
        as_generator: If `True`, a generator on the projects is returned.
    !!! info "Dates format"
        Date strings should have format: "YYYY-MM-DD"
    Returns:
        A list of projects or a generator of projects if `as_generator` is `True`.
    Examples:
        >>> # List all my projects
        >>> kili.projects()
    """
    tag_ids = (
        TagUseCases(self.kili_api_gateway).get_tag_ids_from_labels(tags_in) if tags_in else None
    )
    projects_gen = ProjectUseCases(self.kili_api_gateway).list_projects(
        ProjectFilters(
            id=ProjectId(project_id) if project_id else None,
            archived=archived,
            search_query=search_query,
            should_relaunch_kpi_computation=should_relaunch_kpi_computation,
            starred=starred,
            updated_at_gte=updated_at_gte,
            updated_at_lte=updated_at_lte,
            created_at_gte=None,
            created_at_lte=None,
            tag_ids=tag_ids,
        ),
        fields,
        first,
        skip,
        disable_tqdm,
    )
    if as_generator:
        return projects_gen
    return list(projects_gen)
Set of Project queries.
Source code in kili/entrypoints/queries/project/__init__.py
          class QueriesProject(BaseOperationEntrypointMixin):
    """Set of Project queries."""
    # pylint: disable=too-many-arguments
    @typechecked
    def count_projects(
        self,
        project_id: Optional[str] = None,
        search_query: Optional[str] = None,
        should_relaunch_kpi_computation: Optional[bool] = None,
        updated_at_gte: Optional[str] = None,
        updated_at_lte: Optional[str] = None,
        archived: Optional[bool] = None,
    ) -> int:
        # pylint: disable=line-too-long
        """Count the number of projects with a search_query.
        Args:
            project_id: Select a specific project through its project_id.
            search_query: Returned projects with a title or a description matching this [PostgreSQL ILIKE](https://www.postgresql.org/docs/current/functions-matching.html#FUNCTIONS-LIKE) pattern.
            should_relaunch_kpi_computation: Technical field, added to indicate changes in honeypot
                or consensus settings
            updated_at_gte: Returned projects should have a label
                whose update date is greater
                or equal to this date.
            updated_at_lte: Returned projects should have a label
                whose update date is lower or equal to this date.
            archived: If `True`, only archived projects are returned, if `False`, only active projects are returned.
                None disable this filter.
        !!! info "Dates format"
            Date strings should have format: "YYYY-MM-DD"
        Returns:
            The number of projects with the parameters provided
        """
        where = ProjectWhere(
            project_id=project_id,
            search_query=search_query,
            should_relaunch_kpi_computation=should_relaunch_kpi_computation,
            updated_at_gte=updated_at_gte,
            updated_at_lte=updated_at_lte,
            archived=archived,
        )
        return ProjectQuery(self.graphql_client, self.http_client).count(where)
count_projects(self, project_id=None, search_query=None, should_relaunch_kpi_computation=None, updated_at_gte=None, updated_at_lte=None, archived=None)
    Count the number of projects with a search_query.
Parameters:
| Name | Type | Description | Default | 
|---|---|---|---|
| project_id | Optional[str] | Select a specific project through its project_id. | None | 
| search_query | Optional[str] | Returned projects with a title or a description matching this PostgreSQL ILIKE pattern. | None | 
| should_relaunch_kpi_computation | Optional[bool] | Technical field, added to indicate changes in honeypot or consensus settings | None | 
| updated_at_gte | Optional[str] | Returned projects should have a label whose update date is greater or equal to this date. | None | 
| updated_at_lte | Optional[str] | Returned projects should have a label whose update date is lower or equal to this date. | None | 
| archived | Optional[bool] | If  | None | 
Dates format
Date strings should have format: "YYYY-MM-DD"
Returns:
| Type | Description | 
|---|---|
| int | The number of projects with the parameters provided | 
Source code in kili/entrypoints/queries/project/__init__.py
          @typechecked
def count_projects(
    self,
    project_id: Optional[str] = None,
    search_query: Optional[str] = None,
    should_relaunch_kpi_computation: Optional[bool] = None,
    updated_at_gte: Optional[str] = None,
    updated_at_lte: Optional[str] = None,
    archived: Optional[bool] = None,
) -> int:
    # pylint: disable=line-too-long
    """Count the number of projects with a search_query.
    Args:
        project_id: Select a specific project through its project_id.
        search_query: Returned projects with a title or a description matching this [PostgreSQL ILIKE](https://www.postgresql.org/docs/current/functions-matching.html#FUNCTIONS-LIKE) pattern.
        should_relaunch_kpi_computation: Technical field, added to indicate changes in honeypot
            or consensus settings
        updated_at_gte: Returned projects should have a label
            whose update date is greater
            or equal to this date.
        updated_at_lte: Returned projects should have a label
            whose update date is lower or equal to this date.
        archived: If `True`, only archived projects are returned, if `False`, only active projects are returned.
            None disable this filter.
    !!! info "Dates format"
        Date strings should have format: "YYYY-MM-DD"
    Returns:
        The number of projects with the parameters provided
    """
    where = ProjectWhere(
        project_id=project_id,
        search_query=search_query,
        should_relaunch_kpi_computation=should_relaunch_kpi_computation,
        updated_at_gte=updated_at_gte,
        updated_at_lte=updated_at_lte,
        archived=archived,
    )
    return ProjectQuery(self.graphql_client, self.http_client).count(where)
Set of Project mutations.
Source code in kili/entrypoints/mutations/project/__init__.py
          class MutationsProject(BaseOperationEntrypointMixin):
    """Set of Project mutations."""
    # pylint: disable=too-many-arguments,too-many-locals
    @typechecked
    def append_to_roles(
        self,
        project_id: str,
        user_email: str,
        role: Literal["ADMIN", "TEAM_MANAGER", "REVIEWER", "LABELER"] = "LABELER",
    ) -> Dict:
        """Add a user to a project.
        !!! info
            If the user does not exist in your organization, he/she is invited and added
                both to your organization and project. This function can also be used to change
                the role of the user in the project.
        Args:
            project_id: Identifier of the project
            user_email: The email of the user.
                This email is used as the unique identifier of the user.
            role: The role of the user.
        Returns:
            A dictionary with the project user information.
        Examples:
            >>> kili.append_to_roles(project_id=project_id, user_email='john@doe.com')
        """
        variables = {
            "data": {"role": role, "userEmail": user_email},
            "where": {"id": project_id},
        }
        result = self.graphql_client.execute(GQL_APPEND_TO_ROLES, variables)
        project_data = self.format_result("data", result)
        for project_user in project_data["roles"]:
            if project_user["user"]["email"] == user_email.lower() and project_user["role"] == role:
                return project_user
        raise MutationError(
            f"Failed to mutate user {user_email} to role {role} for project {project_id}."
        )
    @typechecked
    def update_properties_in_project(
        self,
        project_id: str,
        can_navigate_between_assets: Optional[bool] = None,
        can_skip_asset: Optional[bool] = None,
        consensus_mark: Optional[float] = None,
        consensus_tot_coverage: Optional[int] = None,
        description: Optional[str] = None,
        honeypot_mark: Optional[float] = None,
        instructions: Optional[str] = None,
        input_type: Optional[str] = None,
        json_interface: Optional[dict] = None,
        min_consensus_size: Optional[int] = None,
        number_of_assets: Optional[int] = None,
        number_of_skipped_assets: Optional[int] = None,
        number_of_remaining_assets: Optional[int] = None,
        number_of_reviewed_assets: Optional[int] = None,
        review_coverage: Optional[int] = None,
        should_relaunch_kpi_computation: Optional[bool] = None,
        title: Optional[str] = None,
        use_honeypot: Optional[bool] = None,
        metadata_types: Optional[dict] = None,
    ) -> Dict[str, Any]:
        """Update properties of a project.
        Args:
            project_id: Identifier of the project.
            can_navigate_between_assets:
                Activate / Deactivate the use of next and previous buttons in labeling interface.
            can_skip_asset: Activate / Deactivate the use of skip button in labeling interface.
            consensus_mark: Should be between 0 and 1.
            consensus_tot_coverage: Should be between 0 and 100.
                It is the percentage of the dataset that will be annotated several times.
            description: Description of the project.
            honeypot_mark: Should be between 0 and 1
            instructions: Instructions of the project.
            input_type: Currently, one of `IMAGE`, `PDF`, `TEXT` or `VIDEO`.
            json_interface: The json parameters of the project, see Edit your interface.
            min_consensus_size: Should be between 1 and 10
                Number of people that will annotate the same asset, for consensus computation.
            number_of_assets: Defaults to 0
            number_of_skipped_assets: Defaults to 0
            number_of_remaining_assets: Defaults to 0
            number_of_reviewed_assets: Defaults to 0
            review_coverage: Allow to set the percentage of assets
                that will be queued in the review interface.
                Should be between 0 and 100
            should_relaunch_kpi_computation: Technical field, added to indicate changes
                in honeypot or consensus settings
            title: Title of the project
            use_honeypot: Activate / Deactivate the use of honeypot in the project
            metadata_types: Types of the project metadata.
                Should be a `dict` of metadata fields name as keys and metadata types as values.
                Currently, possible types are: `string`, `number`
        Returns:
            A dict with the changed properties which indicates if the mutation was successful,
                else an error message.
        !!! example "Change Metadata Types"
            Metadata fields are by default interpreted as `string` types. To change the type
            of a metadata field, you can use the `update_properties_in_project` function with the
            metadata_types argument. `metadata_types` is given as a dict of metadata field names
            as keys and metadata types as values.
            ```python
            kili.update_properties_in_project(
                project_id = project_id,
                metadata_types = {
                    'customConsensus': 'number',
                    'sensitiveData': 'string',
                    'uploadedFromCloud': 'string',
                    'modelLabelErrorScore': 'number'
                }
            )
            ```
            Not providing a type for a metadata field or providing an unsupported one
            will default to the `string` type.
        """
        verify_argument_ranges(consensus_tot_coverage, min_consensus_size, review_coverage)
        variables = {
            "canNavigateBetweenAssets": can_navigate_between_assets,
            "canSkipAsset": can_skip_asset,
            "consensusMark": consensus_mark,
            "consensusTotCoverage": consensus_tot_coverage,
            "description": description,
            "honeypotMark": honeypot_mark,
            "instructions": instructions,
            "inputType": input_type,
            "jsonInterface": dumps(json_interface) if json_interface is not None else None,
            "metadataTypes": metadata_types,
            "minConsensusSize": min_consensus_size,
            "numberOfAssets": number_of_assets,
            "numberOfSkippedAssets": number_of_skipped_assets,
            "numberOfRemainingAssets": number_of_remaining_assets,
            "numberOfReviewedAssets": number_of_reviewed_assets,
            "projectID": project_id,
            "reviewCoverage": review_coverage,
            "shouldRelaunchKpiComputation": should_relaunch_kpi_computation,
            "title": title,
            "useHoneyPot": use_honeypot,
        }
        result = self.graphql_client.execute(GQL_UPDATE_PROPERTIES_IN_PROJECT, variables)
        result = self.format_result("data", result)
        variables.pop("projectID")
        variables = {k: v for k, v in variables.items() if v is not None}
        new_project_settings = get_project(self, project_id, list(variables.keys()))
        return {**result, **new_project_settings}
    @typechecked
    def update_properties_in_role(
        self, role_id: str, project_id: str, user_id: str, role: str
    ) -> Dict:
        """Update properties of a role.
        !!! info
            To be able to change someone's role, you must be either of:
            - an admin of the project
            - a team manager of the project
            - an admin of the organization
        Args:
            role_id: Role identifier of the user. E.g. : 'to-be-deactivated'
            project_id: Identifier of the project
            user_id: The email or identifier of the user with updated role
            role: The new role.
                Possible choices are: `ADMIN`, `TEAM_MANAGER`, `REVIEWER`, `LABELER`
        Returns:
            A dictionary with the project user information.
        """
        variables = {
            "roleID": role_id,
            "projectID": project_id,
            "userID": user_id,
            "role": role,
        }
        result = self.graphql_client.execute(GQL_UPDATE_PROPERTIES_IN_ROLE, variables)
        return self.format_result("data", result)
    @typechecked
    def delete_from_roles(self, role_id: str) -> Dict[Literal["id"], str]:
        """Delete users by their role_id.
        Args:
            role_id: Identifier of the project user (not the ID of the user)
        Returns:
            A dict with the project id.
        """
        variables = {"where": {"id": role_id}}
        result = self.graphql_client.execute(GQL_DELETE_FROM_ROLES, variables)
        return self.format_result("data", result)
    @typechecked
    def delete_project(self, project_id: str) -> str:
        """Delete a project permanently.
        Args:
            project_id: Identifier of the project
        Returns:
            A string with the deleted project id.
        """
        variables = {"where": {"id": project_id}}
        result = self.graphql_client.execute(GQL_PROJECT_DELETE_ASYNCHRONOUSLY, variables)
        return self.format_result("data", result)
    @typechecked
    def archive_project(self, project_id: str) -> Dict[Literal["id"], str]:
        """Archive a project.
        Args:
            project_id: Identifier of the project.
        Returns:
            A dict with the id of the project.
        """
        variables = {
            "projectID": project_id,
            "archived": True,
        }
        result = self.graphql_client.execute(GQL_UPDATE_PROPERTIES_IN_PROJECT, variables)
        return self.format_result("data", result)
    @typechecked
    def unarchive_project(self, project_id: str) -> Dict[Literal["id"], str]:
        """Unarchive a project.
        Args:
            project_id: Identifier of the project
        Returns:
            A dict with the id of the project.
        """
        variables = {
            "projectID": project_id,
            "archived": False,
        }
        result = self.graphql_client.execute(GQL_UPDATE_PROPERTIES_IN_PROJECT, variables)
        return self.format_result("data", result)
    @typechecked
    def copy_project(  # pylint: disable=too-many-arguments
        self,
        from_project_id: str,
        title: Optional[str] = None,
        description: Optional[str] = None,
        copy_json_interface: bool = True,
        copy_quality_settings: bool = True,
        copy_members: bool = True,
        copy_assets: bool = False,
        copy_labels: bool = False,
        disable_tqdm: Optional[bool] = None,
    ) -> str:
        """Create new project from an existing project.
        Args:
            from_project_id: Project ID to copy from.
            title: Title for the new project. Defaults to source project
                title if `None` is provided.
            description: Description for the new project. Defaults to empty string
                if `None` is provided.
            copy_json_interface: Include json interface in the copy.
            copy_quality_settings: Include quality settings in the copy.
            copy_members: Include members in the copy.
            copy_assets: Include assets in the copy.
            copy_labels: Include labels in the copy.
            disable_tqdm: Disable tqdm progress bars.
        Returns:
            The created project ID.
        Examples:
            >>> kili.copy_project(from_project_id="clbqn56b331234567890l41c0")
        """
        return ProjectCopier(self).copy_project(
            from_project_id,
            title,
            description,
            copy_json_interface,
            copy_quality_settings,
            copy_members,
            copy_assets,
            copy_labels,
            disable_tqdm,
        )
    @typechecked
    def update_project_anonymization(
        self, project_id: str, should_anonymize: bool = True
    ) -> Dict[Literal["id"], str]:
        """Anonymize the project for the labelers and reviewers.
        !!! info
            Compatible with versions of the Kili app >= 2.135.0
        Args:
            project_id: Identifier of the project
            should_anonymize: The value to be applied. Defaults to `True`.
        Returns:
            A dict with the id of the project which indicates if the mutation was successful,
                or an error message.
        Examples:
            >>> kili.update_project_anonymization(project_id=project_id)
            >>> kili.update_project_anonymization(project_id=project_id, should_anonymize=False)
        """
        variables = {
            "input": {
                "id": project_id,
                "shouldAnonymize": should_anonymize,
            }
        }
        result = self.graphql_client.execute(GQL_PROJECT_UPDATE_ANONYMIZATION, variables)
        return self.format_result("data", result)
append_to_roles(self, project_id, user_email, role='LABELER')
    Add a user to a project.
Info
If the user does not exist in your organization, he/she is invited and added both to your organization and project. This function can also be used to change the role of the user in the project.
Parameters:
| Name | Type | Description | Default | 
|---|---|---|---|
| project_id | str | Identifier of the project | required | 
| user_email | str | The email of the user. This email is used as the unique identifier of the user. | required | 
| role | Literal['ADMIN', 'TEAM_MANAGER', 'REVIEWER', 'LABELER'] | The role of the user. | 'LABELER' | 
Returns:
| Type | Description | 
|---|---|
| Dict | A dictionary with the project user information. | 
Examples:
>>> kili.append_to_roles(project_id=project_id, user_email='john@doe.com')
Source code in kili/entrypoints/mutations/project/__init__.py
          @typechecked
def append_to_roles(
    self,
    project_id: str,
    user_email: str,
    role: Literal["ADMIN", "TEAM_MANAGER", "REVIEWER", "LABELER"] = "LABELER",
) -> Dict:
    """Add a user to a project.
    !!! info
        If the user does not exist in your organization, he/she is invited and added
            both to your organization and project. This function can also be used to change
            the role of the user in the project.
    Args:
        project_id: Identifier of the project
        user_email: The email of the user.
            This email is used as the unique identifier of the user.
        role: The role of the user.
    Returns:
        A dictionary with the project user information.
    Examples:
        >>> kili.append_to_roles(project_id=project_id, user_email='john@doe.com')
    """
    variables = {
        "data": {"role": role, "userEmail": user_email},
        "where": {"id": project_id},
    }
    result = self.graphql_client.execute(GQL_APPEND_TO_ROLES, variables)
    project_data = self.format_result("data", result)
    for project_user in project_data["roles"]:
        if project_user["user"]["email"] == user_email.lower() and project_user["role"] == role:
            return project_user
    raise MutationError(
        f"Failed to mutate user {user_email} to role {role} for project {project_id}."
    )
archive_project(self, project_id)
    Archive a project.
Parameters:
| Name | Type | Description | Default | 
|---|---|---|---|
| project_id | str | Identifier of the project. | required | 
Returns:
| Type | Description | 
|---|---|
| Dict[Literal['id'], str] | A dict with the id of the project. | 
Source code in kili/entrypoints/mutations/project/__init__.py
          @typechecked
def archive_project(self, project_id: str) -> Dict[Literal["id"], str]:
    """Archive a project.
    Args:
        project_id: Identifier of the project.
    Returns:
        A dict with the id of the project.
    """
    variables = {
        "projectID": project_id,
        "archived": True,
    }
    result = self.graphql_client.execute(GQL_UPDATE_PROPERTIES_IN_PROJECT, variables)
    return self.format_result("data", result)
copy_project(self, from_project_id, title=None, description=None, copy_json_interface=True, copy_quality_settings=True, copy_members=True, copy_assets=False, copy_labels=False, disable_tqdm=None)
    Create new project from an existing project.
Parameters:
| Name | Type | Description | Default | 
|---|---|---|---|
| from_project_id | str | Project ID to copy from. | required | 
| title | Optional[str] | Title for the new project. Defaults to source project
title if  | None | 
| description | Optional[str] | Description for the new project. Defaults to empty string
if  | None | 
| copy_json_interface | bool | Include json interface in the copy. | True | 
| copy_quality_settings | bool | Include quality settings in the copy. | True | 
| copy_members | bool | Include members in the copy. | True | 
| copy_assets | bool | Include assets in the copy. | False | 
| copy_labels | bool | Include labels in the copy. | False | 
| disable_tqdm | Optional[bool] | Disable tqdm progress bars. | None | 
Returns:
| Type | Description | 
|---|---|
| str | The created project ID. | 
Examples:
>>> kili.copy_project(from_project_id="clbqn56b331234567890l41c0")
Source code in kili/entrypoints/mutations/project/__init__.py
          @typechecked
def copy_project(  # pylint: disable=too-many-arguments
    self,
    from_project_id: str,
    title: Optional[str] = None,
    description: Optional[str] = None,
    copy_json_interface: bool = True,
    copy_quality_settings: bool = True,
    copy_members: bool = True,
    copy_assets: bool = False,
    copy_labels: bool = False,
    disable_tqdm: Optional[bool] = None,
) -> str:
    """Create new project from an existing project.
    Args:
        from_project_id: Project ID to copy from.
        title: Title for the new project. Defaults to source project
            title if `None` is provided.
        description: Description for the new project. Defaults to empty string
            if `None` is provided.
        copy_json_interface: Include json interface in the copy.
        copy_quality_settings: Include quality settings in the copy.
        copy_members: Include members in the copy.
        copy_assets: Include assets in the copy.
        copy_labels: Include labels in the copy.
        disable_tqdm: Disable tqdm progress bars.
    Returns:
        The created project ID.
    Examples:
        >>> kili.copy_project(from_project_id="clbqn56b331234567890l41c0")
    """
    return ProjectCopier(self).copy_project(
        from_project_id,
        title,
        description,
        copy_json_interface,
        copy_quality_settings,
        copy_members,
        copy_assets,
        copy_labels,
        disable_tqdm,
    )
delete_from_roles(self, role_id)
    Delete users by their role_id.
Parameters:
| Name | Type | Description | Default | 
|---|---|---|---|
| role_id | str | Identifier of the project user (not the ID of the user) | required | 
Returns:
| Type | Description | 
|---|---|
| Dict[Literal['id'], str] | A dict with the project id. | 
Source code in kili/entrypoints/mutations/project/__init__.py
          @typechecked
def delete_from_roles(self, role_id: str) -> Dict[Literal["id"], str]:
    """Delete users by their role_id.
    Args:
        role_id: Identifier of the project user (not the ID of the user)
    Returns:
        A dict with the project id.
    """
    variables = {"where": {"id": role_id}}
    result = self.graphql_client.execute(GQL_DELETE_FROM_ROLES, variables)
    return self.format_result("data", result)
delete_project(self, project_id)
    Delete a project permanently.
Parameters:
| Name | Type | Description | Default | 
|---|---|---|---|
| project_id | str | Identifier of the project | required | 
Returns:
| Type | Description | 
|---|---|
| str | A string with the deleted project id. | 
Source code in kili/entrypoints/mutations/project/__init__.py
          @typechecked
def delete_project(self, project_id: str) -> str:
    """Delete a project permanently.
    Args:
        project_id: Identifier of the project
    Returns:
        A string with the deleted project id.
    """
    variables = {"where": {"id": project_id}}
    result = self.graphql_client.execute(GQL_PROJECT_DELETE_ASYNCHRONOUSLY, variables)
    return self.format_result("data", result)
unarchive_project(self, project_id)
    Unarchive a project.
Parameters:
| Name | Type | Description | Default | 
|---|---|---|---|
| project_id | str | Identifier of the project | required | 
Returns:
| Type | Description | 
|---|---|
| Dict[Literal['id'], str] | A dict with the id of the project. | 
Source code in kili/entrypoints/mutations/project/__init__.py
          @typechecked
def unarchive_project(self, project_id: str) -> Dict[Literal["id"], str]:
    """Unarchive a project.
    Args:
        project_id: Identifier of the project
    Returns:
        A dict with the id of the project.
    """
    variables = {
        "projectID": project_id,
        "archived": False,
    }
    result = self.graphql_client.execute(GQL_UPDATE_PROPERTIES_IN_PROJECT, variables)
    return self.format_result("data", result)
update_project_anonymization(self, project_id, should_anonymize=True)
    Anonymize the project for the labelers and reviewers.
Info
Compatible with versions of the Kili app >= 2.135.0
Parameters:
| Name | Type | Description | Default | 
|---|---|---|---|
| project_id | str | Identifier of the project | required | 
| should_anonymize | bool | The value to be applied. Defaults to  | True | 
Returns:
| Type | Description | 
|---|---|
| Dict[Literal['id'], str] | A dict with the id of the project which indicates if the mutation was successful, or an error message. | 
Examples:
>>> kili.update_project_anonymization(project_id=project_id)
>>> kili.update_project_anonymization(project_id=project_id, should_anonymize=False)
Source code in kili/entrypoints/mutations/project/__init__.py
          @typechecked
def update_project_anonymization(
    self, project_id: str, should_anonymize: bool = True
) -> Dict[Literal["id"], str]:
    """Anonymize the project for the labelers and reviewers.
    !!! info
        Compatible with versions of the Kili app >= 2.135.0
    Args:
        project_id: Identifier of the project
        should_anonymize: The value to be applied. Defaults to `True`.
    Returns:
        A dict with the id of the project which indicates if the mutation was successful,
            or an error message.
    Examples:
        >>> kili.update_project_anonymization(project_id=project_id)
        >>> kili.update_project_anonymization(project_id=project_id, should_anonymize=False)
    """
    variables = {
        "input": {
            "id": project_id,
            "shouldAnonymize": should_anonymize,
        }
    }
    result = self.graphql_client.execute(GQL_PROJECT_UPDATE_ANONYMIZATION, variables)
    return self.format_result("data", result)
update_properties_in_project(self, project_id, can_navigate_between_assets=None, can_skip_asset=None, consensus_mark=None, consensus_tot_coverage=None, description=None, honeypot_mark=None, instructions=None, input_type=None, json_interface=None, min_consensus_size=None, number_of_assets=None, number_of_skipped_assets=None, number_of_remaining_assets=None, number_of_reviewed_assets=None, review_coverage=None, should_relaunch_kpi_computation=None, title=None, use_honeypot=None, metadata_types=None)
    Update properties of a project.
Parameters:
| Name | Type | Description | Default | 
|---|---|---|---|
| project_id | str | Identifier of the project. | required | 
| can_navigate_between_assets | Optional[bool] | Activate / Deactivate the use of next and previous buttons in labeling interface. | None | 
| can_skip_asset | Optional[bool] | Activate / Deactivate the use of skip button in labeling interface. | None | 
| consensus_mark | Optional[float] | Should be between 0 and 1. | None | 
| consensus_tot_coverage | Optional[int] | Should be between 0 and 100. It is the percentage of the dataset that will be annotated several times. | None | 
| description | Optional[str] | Description of the project. | None | 
| honeypot_mark | Optional[float] | Should be between 0 and 1 | None | 
| instructions | Optional[str] | Instructions of the project. | None | 
| input_type | Optional[str] | Currently, one of  | None | 
| json_interface | Optional[dict] | The json parameters of the project, see Edit your interface. | None | 
| min_consensus_size | Optional[int] | Should be between 1 and 10 Number of people that will annotate the same asset, for consensus computation. | None | 
| number_of_assets | Optional[int] | Defaults to 0 | None | 
| number_of_skipped_assets | Optional[int] | Defaults to 0 | None | 
| number_of_remaining_assets | Optional[int] | Defaults to 0 | None | 
| number_of_reviewed_assets | Optional[int] | Defaults to 0 | None | 
| review_coverage | Optional[int] | Allow to set the percentage of assets that will be queued in the review interface. Should be between 0 and 100 | None | 
| should_relaunch_kpi_computation | Optional[bool] | Technical field, added to indicate changes in honeypot or consensus settings | None | 
| title | Optional[str] | Title of the project | None | 
| use_honeypot | Optional[bool] | Activate / Deactivate the use of honeypot in the project | None | 
| metadata_types | Optional[dict] | Types of the project metadata.
Should be a  | None | 
Returns:
| Type | Description | 
|---|---|
| Dict[str, Any] | A dict with the changed properties which indicates if the mutation was successful, else an error message. | 
Change Metadata Types
Metadata fields are by default interpreted as string types. To change the type
of a metadata field, you can use the update_properties_in_project function with the
metadata_types argument. metadata_types is given as a dict of metadata field names
as keys and metadata types as values.
kili.update_properties_in_project(
    project_id = project_id,
    metadata_types = {
        'customConsensus': 'number',
        'sensitiveData': 'string',
        'uploadedFromCloud': 'string',
        'modelLabelErrorScore': 'number'
    }
)
Not providing a type for a metadata field or providing an unsupported one
will default to the string type.
Source code in kili/entrypoints/mutations/project/__init__.py
          @typechecked
def update_properties_in_project(
    self,
    project_id: str,
    can_navigate_between_assets: Optional[bool] = None,
    can_skip_asset: Optional[bool] = None,
    consensus_mark: Optional[float] = None,
    consensus_tot_coverage: Optional[int] = None,
    description: Optional[str] = None,
    honeypot_mark: Optional[float] = None,
    instructions: Optional[str] = None,
    input_type: Optional[str] = None,
    json_interface: Optional[dict] = None,
    min_consensus_size: Optional[int] = None,
    number_of_assets: Optional[int] = None,
    number_of_skipped_assets: Optional[int] = None,
    number_of_remaining_assets: Optional[int] = None,
    number_of_reviewed_assets: Optional[int] = None,
    review_coverage: Optional[int] = None,
    should_relaunch_kpi_computation: Optional[bool] = None,
    title: Optional[str] = None,
    use_honeypot: Optional[bool] = None,
    metadata_types: Optional[dict] = None,
) -> Dict[str, Any]:
    """Update properties of a project.
    Args:
        project_id: Identifier of the project.
        can_navigate_between_assets:
            Activate / Deactivate the use of next and previous buttons in labeling interface.
        can_skip_asset: Activate / Deactivate the use of skip button in labeling interface.
        consensus_mark: Should be between 0 and 1.
        consensus_tot_coverage: Should be between 0 and 100.
            It is the percentage of the dataset that will be annotated several times.
        description: Description of the project.
        honeypot_mark: Should be between 0 and 1
        instructions: Instructions of the project.
        input_type: Currently, one of `IMAGE`, `PDF`, `TEXT` or `VIDEO`.
        json_interface: The json parameters of the project, see Edit your interface.
        min_consensus_size: Should be between 1 and 10
            Number of people that will annotate the same asset, for consensus computation.
        number_of_assets: Defaults to 0
        number_of_skipped_assets: Defaults to 0
        number_of_remaining_assets: Defaults to 0
        number_of_reviewed_assets: Defaults to 0
        review_coverage: Allow to set the percentage of assets
            that will be queued in the review interface.
            Should be between 0 and 100
        should_relaunch_kpi_computation: Technical field, added to indicate changes
            in honeypot or consensus settings
        title: Title of the project
        use_honeypot: Activate / Deactivate the use of honeypot in the project
        metadata_types: Types of the project metadata.
            Should be a `dict` of metadata fields name as keys and metadata types as values.
            Currently, possible types are: `string`, `number`
    Returns:
        A dict with the changed properties which indicates if the mutation was successful,
            else an error message.
    !!! example "Change Metadata Types"
        Metadata fields are by default interpreted as `string` types. To change the type
        of a metadata field, you can use the `update_properties_in_project` function with the
        metadata_types argument. `metadata_types` is given as a dict of metadata field names
        as keys and metadata types as values.
        ```python
        kili.update_properties_in_project(
            project_id = project_id,
            metadata_types = {
                'customConsensus': 'number',
                'sensitiveData': 'string',
                'uploadedFromCloud': 'string',
                'modelLabelErrorScore': 'number'
            }
        )
        ```
        Not providing a type for a metadata field or providing an unsupported one
        will default to the `string` type.
    """
    verify_argument_ranges(consensus_tot_coverage, min_consensus_size, review_coverage)
    variables = {
        "canNavigateBetweenAssets": can_navigate_between_assets,
        "canSkipAsset": can_skip_asset,
        "consensusMark": consensus_mark,
        "consensusTotCoverage": consensus_tot_coverage,
        "description": description,
        "honeypotMark": honeypot_mark,
        "instructions": instructions,
        "inputType": input_type,
        "jsonInterface": dumps(json_interface) if json_interface is not None else None,
        "metadataTypes": metadata_types,
        "minConsensusSize": min_consensus_size,
        "numberOfAssets": number_of_assets,
        "numberOfSkippedAssets": number_of_skipped_assets,
        "numberOfRemainingAssets": number_of_remaining_assets,
        "numberOfReviewedAssets": number_of_reviewed_assets,
        "projectID": project_id,
        "reviewCoverage": review_coverage,
        "shouldRelaunchKpiComputation": should_relaunch_kpi_computation,
        "title": title,
        "useHoneyPot": use_honeypot,
    }
    result = self.graphql_client.execute(GQL_UPDATE_PROPERTIES_IN_PROJECT, variables)
    result = self.format_result("data", result)
    variables.pop("projectID")
    variables = {k: v for k, v in variables.items() if v is not None}
    new_project_settings = get_project(self, project_id, list(variables.keys()))
    return {**result, **new_project_settings}
update_properties_in_role(self, role_id, project_id, user_id, role)
    Update properties of a role.
Info
To be able to change someone's role, you must be either of:
- an admin of the project
- a team manager of the project
- an admin of the organization
Parameters:
| Name | Type | Description | Default | 
|---|---|---|---|
| role_id | str | Role identifier of the user. E.g. : 'to-be-deactivated' | required | 
| project_id | str | Identifier of the project | required | 
| user_id | str | The email or identifier of the user with updated role | required | 
| role | str | The new role.
Possible choices are:  | required | 
Returns:
| Type | Description | 
|---|---|
| Dict | A dictionary with the project user information. | 
Source code in kili/entrypoints/mutations/project/__init__.py
          @typechecked
def update_properties_in_role(
    self, role_id: str, project_id: str, user_id: str, role: str
) -> Dict:
    """Update properties of a role.
    !!! info
        To be able to change someone's role, you must be either of:
        - an admin of the project
        - a team manager of the project
        - an admin of the organization
    Args:
        role_id: Role identifier of the user. E.g. : 'to-be-deactivated'
        project_id: Identifier of the project
        user_id: The email or identifier of the user with updated role
        role: The new role.
            Possible choices are: `ADMIN`, `TEAM_MANAGER`, `REVIEWER`, `LABELER`
    Returns:
        A dictionary with the project user information.
    """
    variables = {
        "roleID": role_id,
        "projectID": project_id,
        "userID": user_id,
        "role": role,
    }
    result = self.graphql_client.execute(GQL_UPDATE_PROPERTIES_IN_ROLE, variables)
    return self.format_result("data", result)