Skip to content

Commit

Permalink
feat: add pageResolution field (#1303)
Browse files Browse the repository at this point in the history
  • Loading branch information
PierreLeveau committed Jul 3, 2023
1 parent da33398 commit 0d5e22a
Show file tree
Hide file tree
Showing 6 changed files with 156 additions and 4 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ jobs:
pip install -e ".[dev]"
- name: Unit tests
run: pytest -n auto -ra -sv --color yes --code-highlight yes --durations=15 -vv --ignore tests/test_notebooks.py --ignore tests/e2e/ --cov=src/kili --cov-report=term-missing --cov-config=.coveragerc --cov-fail-under=79
run: pytest -n auto -ra -sv --color yes --code-highlight yes --durations=15 -vv --ignore tests/test_notebooks.py --ignore tests/e2e/ --cov=src/kili --cov-report=term-missing --cov-config=.coveragerc --cov-fail-under=80

markdown-link-check:
timeout-minutes: 2
Expand Down
26 changes: 26 additions & 0 deletions src/kili/entrypoints/mutations/asset/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
from kili.exceptions import MissingArgumentError
from kili.orm import Asset
from kili.services.asset_import import import_assets
from kili.utils.assets import PageResolution
from kili.utils.logcontext import for_all_methods, log_call

from ..exceptions import MutationError
Expand Down Expand Up @@ -169,6 +170,9 @@ def update_properties_in_assets(
is_used_for_consensus_array: Optional[List[bool]] = None,
is_honeypot_array: Optional[List[bool]] = None,
project_id: Optional[str] = None,
page_resolutions_array: Optional[
Union[List[List[dict]], List[List[PageResolution]]]
] = None,
) -> List[Dict[Literal["id"], str]]:
"""Update the properties of one or more assets.
Expand Down Expand Up @@ -196,6 +200,11 @@ def update_properties_in_assets(
is_used_for_consensus_array: Whether to use the asset to compute consensus kpis or not.
is_honeypot_array: Whether to use the asset for honeypot.
project_id: The project ID. Only required if `external_ids` argument is provided.
page_resolutions_array: The resolution of each page of the asset (for PDF projects).
Note that each element of the array should contain all the pages resolutions of the
corresponding asset. Each resolution can be passed as a
`kili.utils.assets.PageResolution` object, or as a dictionary with keys `width`,
`height`, `pageNumber` and optionally `rotation`.
Returns:
A list of dictionaries with the asset ids.
Expand All @@ -212,6 +221,21 @@ def update_properties_in_assets(
status_array=['LABELED', 'REVIEWED'],
to_be_labeled_by_array=[['test+pierre@kili-technology.com'], None],
)
# The following call updates the pages resolutions of PDF assets.
>>> kili.update_properties_in_assets(
asset_ids=["ckg22d81r0jrg0885unmuswj8", "ckg22d81s0jrh0885pdxfd03n"],
page_resolutions_array=[
[
PageResolution(width=480, height=640, pageNumber=0),
PageResolution(width=480, height=640, pageNumber=1),
],[
PageResolution(width=340, height=512, pageNumber=0),
PageResolution(width=680, height=1024, pageNumber=1, rotation=90),
PageResolution(width=680, height=1024, pageNumber=2),
]
],
)
"""
if is_empty_list_with_warning(
"update_properties_in_assets", "asset_ids", asset_ids
Expand Down Expand Up @@ -262,6 +286,7 @@ def update_properties_in_assets(
"status_array",
"is_used_for_consensus_array",
"is_honeypot_array",
"page_resolutions_array",
]
}
properties_to_batch = process_update_properties_in_assets_parameters(parameters)
Expand All @@ -279,6 +304,7 @@ def generate_variables(batch: Dict) -> Dict:
"status": batch["status_array"],
"isUsedForConsensus": batch["is_used_for_consensus_array"],
"isHoneypot": batch["is_honeypot_array"],
"pageResolutions": batch["page_resolutions_array"],
}
data_array = [dict(zip(data, t)) for t in zip(*data.values())] # type: ignore
return {
Expand Down
34 changes: 32 additions & 2 deletions src/kili/entrypoints/mutations/asset/helpers.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,22 @@
"""Helpers for the asset mutations."""
from typing import Dict, List, Optional
from typing import Dict, List, Optional, Union

from kili.core.helpers import convert_to_list_of_none, format_metadata, is_none_or_empty
from kili.entrypoints.mutations.helpers import check_asset_identifier_arguments
from kili.services.helpers import infer_ids_from_external_ids
from kili.utils.assets import PageResolution


def process_update_properties_in_assets_parameters(properties) -> Dict:
"""Process arguments of the update_properties_in_assets method
and return the properties for the paginated loop."""
and return the properties for the paginated loop.
properties should have the following keys:
- asset_ids: list of asset ids.
- json_metadatas: list of json metadatas, can be none.
- to_be_labeled_by_array: list of users, must be iterable.
- page_resolutions_array: list of page resolutions, must be iterable.
"""
formatted_json_metadatas = None
if properties["json_metadatas"] is None:
formatted_json_metadatas = None
Expand All @@ -21,16 +29,38 @@ def process_update_properties_in_assets_parameters(properties) -> Dict:
"Should be either a None or a list of None, string, list or dict",
)
properties["json_metadatas"] = formatted_json_metadatas
assert properties["asset_ids"]
nb_assets_to_modify = len(properties["asset_ids"])
properties = {
k: convert_to_list_of_none(v, length=nb_assets_to_modify) for k, v in properties.items()
}
properties["should_reset_to_be_labeled_by_array"] = list(
map(is_none_or_empty, properties["to_be_labeled_by_array"])
)

properties["page_resolutions_array"] = _ensure_page_resolution_dicts(
properties["page_resolutions_array"]
)

return properties


def _ensure_page_resolution_dicts(
page_resolutions_array: Union[List[List[PageResolution]], List[List[Dict]]]
):
page_resolutions_array_batch = []
for page_resolution_array in page_resolutions_array:
output_page_resolution_array = []
for page_resolution in page_resolution_array:
output_page_resolution_array.append(
page_resolution.as_dict()
if isinstance(page_resolution, PageResolution)
else page_resolution
)
page_resolutions_array_batch.append(output_page_resolution_array)
return page_resolutions_array_batch


def get_asset_ids_or_throw_error(
kili,
asset_ids: Optional[List[str]],
Expand Down
3 changes: 2 additions & 1 deletion src/kili/types.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
# pylint: disable:invalid-name,too-many-instance-attributes
"""GraphQL types."""

from typing import Dict, List

from typing_extensions import TypedDict
Expand All @@ -21,6 +20,8 @@
from kili.core.helpers import deprecate


#######
# The following types are deprecated and will be removed in the next major release.
@deprecate()
class License(TypedDict):
"""A Wrapper for License GraphQL object."""
Expand Down
25 changes: 25 additions & 0 deletions src/kili/utils/assets/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
"""Utilities to handle assets."""
from dataclasses import dataclass
from typing import Any, Dict


@dataclass
class PageResolution:
"""A wrapper for PageResolution GraphQL object."""

width: float
height: float
page_number: int
rotation: int = 0

def as_dict(self) -> Dict[str, Any]:
"""Return a dictionary representation of the object."""
output = {
"width": self.width,
"height": self.height,
"pageNumber": self.page_number,
}
if self.rotation != 0:
output["rotation"] = self.rotation

return output
70 changes: 70 additions & 0 deletions tests/integration/entrypoints/mutations/test_assets.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
"""Tests for the asset mutations."""
import pytest
import pytest_mock

from kili.entrypoints.mutations.asset import MutationsAsset, PageResolution


@pytest.mark.parametrize(
"page_resolutions_array",
[
[
[
{"width": 100, "height": 200, "pageNumber": 1},
{"width": 200, "height": 300, "pageNumber": 0},
]
],
[
[
PageResolution(width=100, height=200, page_number=1),
PageResolution(width=200, height=300, page_number=0),
]
],
],
)
def test_given_page_resolutions_when_i_call_update_properties_in_assets_it_calls_the_resolvers_correctly(
page_resolutions_array,
mocker: pytest_mock.MockerFixture,
):
"""Test update_properties_in_assets for resolution update."""
# Given
kili = MutationsAsset()
kili.graphql_client = mocker.MagicMock()

asset_ids = ["asset_id"]

# When
kili.update_properties_in_assets(
asset_ids=asset_ids, page_resolutions_array=page_resolutions_array
)

# Then
kili.graphql_client.execute.assert_called_once_with(
(
"\nmutation(\n $whereArray: [AssetWhere!]!\n $dataArray: [AssetData!]!\n) {\n"
" data: updatePropertiesInAssets(\n where: $whereArray,\n data: $dataArray\n"
" ) {\n id\n }\n}\n"
),
{
"whereArray": [{"id": "asset_id"}],
"dataArray": [
{
"priority": None,
"jsonMetadata": None,
"consensusMark": None,
"honeypotMark": None,
"toBeLabeledBy": None,
"shouldResetToBeLabeledBy": True,
"content": None,
"jsonContent": None,
"status": None,
"isUsedForConsensus": None,
"isHoneypot": None,
"pageResolutions": [
{"width": 100, "height": 200, "pageNumber": 1},
{"width": 200, "height": 300, "pageNumber": 0},
],
}
],
},
)

0 comments on commit 0d5e22a

Please sign in to comment.