Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: refacto repo archi #1392

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .pylintrc
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ disable=raw-checker-failed,
logging-fstring-interpolation,
cyclic-import,
too-few-public-methods,
fixme,


# Enable the message, report, category or checker with the given id(s). You can
Expand Down
4 changes: 1 addition & 3 deletions docs/sdk/issue.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
# Issue module

## Queries
::: kili.presentation.client.issue.IssueClientMethods
::: kili.entrypoints.queries.issue.__init__.QueriesIssue

## Mutations
theodu marked this conversation as resolved.
Show resolved Hide resolved
::: kili.entrypoints.mutations.issue.__init__.MutationsIssue
9 changes: 7 additions & 2 deletions src/kili/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,9 @@
from kili.entrypoints.queries.user import QueriesUser
from kili.entrypoints.subscriptions.label import SubscriptionsLabel
from kili.exceptions import AuthenticationFailed, UserNotFoundError
from kili.internal import KiliInternal
from kili.gateways.kili_api_gateway import KiliAPIGateway
from kili.presentation.client.internal import InternalClientMethods
from kili.presentation.client.issue import IssueClientMethods
from kili.utils.logcontext import LogContext, log_call

warnings.filterwarnings("default", module="kili", category=DeprecationWarning)
Expand Down Expand Up @@ -77,6 +79,7 @@ class Kili( # pylint: disable=too-many-ancestors,too-many-instance-attributes
QueriesProjectVersion,
QueriesUser,
SubscriptionsLabel,
IssueClientMethods,
):
"""Kili Client."""

Expand Down Expand Up @@ -170,11 +173,13 @@ def __init__(
**(graphql_client_params or {}), # type: ignore
)

self.kili_api_gateway = KiliAPIGateway(self.graphql_client, self.http_client)

if not skip_checks:
api_key_query = APIKeyQuery(self.graphql_client, self.http_client)
self._check_expiry_of_key_is_close(api_key_query, self.api_key)

self.internal = KiliInternal(self)
self.internal = InternalClientMethods(self)

@log_call
def _is_api_key_valid(self) -> bool:
Expand Down
13 changes: 0 additions & 13 deletions src/kili/core/enums.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,19 +39,6 @@
"VIDEO_LEGACY",
]


IssueStatus = Literal[
"OPEN",
"SOLVED",
]


IssueType = Literal[
"ISSUE",
"QUESTION",
]


LabelFormat = Literal[
"RAW",
"SIMPLE",
Expand Down
Empty file added src/kili/domain/__init__.py
Empty file.
13 changes: 13 additions & 0 deletions src/kili/domain/issue.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
"""Issue domain."""
from dataclasses import dataclass
from typing import Literal

IssueType = Literal["ISSUE", "QUESTION"]
IssueStatus = Literal["OPEN", "SOLVED"]


@dataclass
class Issue:
"""Issue Entity."""

id_: str
50 changes: 2 additions & 48 deletions src/kili/entrypoints/mutations/issue/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
"""Issue mutations."""

from itertools import repeat
from typing import Dict, List, Literal, Optional

from typeguard import typechecked
Expand All @@ -10,11 +9,11 @@
from kili.core.helpers import deprecate
from kili.entrypoints.base import BaseOperationEntrypointMixin
from kili.entrypoints.mutations.asset.helpers import get_asset_ids_or_throw_error
from kili.gateways.kili_api_gateway.issue.operations import GQL_CREATE_ISSUES
theodu marked this conversation as resolved.
Show resolved Hide resolved
from kili.services.helpers import assert_all_arrays_have_same_size
from kili.utils.logcontext import for_all_methods, log_call

from .helpers import get_issue_numbers, get_labels_asset_ids_map
from .queries import GQL_CREATE_ISSUES
from .helpers import get_issue_numbers


@for_all_methods(log_call, exclude=["__init__"])
Expand Down Expand Up @@ -91,51 +90,6 @@ def append_to_issues(
result = self.graphql_client.execute(GQL_CREATE_ISSUES, variables)
return self.format_result("data", result)[0]

@typechecked
def create_issues(
self,
project_id: str,
label_id_array: List[str],
object_mid_array: Optional[List[Optional[str]]] = None,
text_array: Optional[List[Optional[str]]] = None,
) -> List[Dict]:
"""Create an issue.

Args:
project_id: Id of the project.
label_id_array: List of Ids of the labels to add an issue to.
object_mid_array: List of mids of the objects in the labels to associate the issues to.
text_array: List of texts to associate to the issues.

Returns:
A list of dictionary with the `id` key of the created issues.
"""
assert_all_arrays_have_same_size([label_id_array, object_mid_array, text_array])
issue_number_array = get_issue_numbers(self, project_id, "ISSUE", len(label_id_array))
label_asset_ids_map = get_labels_asset_ids_map(self, project_id, label_id_array)
variables = {
"issues": [
{
"issueNumber": issue_number,
"labelID": label_id,
"objectMid": object_mid,
"type": "ISSUE",
"assetId": label_asset_ids_map[label_id],
"text": text,
}
for (issue_number, label_id, object_mid, text) in zip(
issue_number_array,
label_id_array,
object_mid_array or repeat(None),
text_array or repeat(None),
)
],
"where": {"idIn": list(label_asset_ids_map.values())},
}

result = self.graphql_client.execute(GQL_CREATE_ISSUES, variables)
return self.format_result("data", result)

@typechecked
def create_questions(
self,
Expand Down
5 changes: 0 additions & 5 deletions src/kili/entrypoints/mutations/issue/fragments.py

This file was deleted.

31 changes: 0 additions & 31 deletions src/kili/entrypoints/mutations/issue/queries.py

This file was deleted.

Empty file added src/kili/gateways/__init__.py
Empty file.
13 changes: 13 additions & 0 deletions src/kili/gateways/kili_api_gateway/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
"""Kili API Gateway module for interacting with Kili."""
import requests

from kili.core.graphql.graphql_client import GraphQLClient
from kili.gateways.kili_api_gateway.issue import IssueOperationMixin


class KiliAPIGateway(IssueOperationMixin):
"""GraphQL gateway to communicate with Kili backend."""

def __init__(self, graphql_client: GraphQLClient, http_client: requests.Session):
self.graphql_client = graphql_client
self.http_client = http_client
68 changes: 68 additions & 0 deletions src/kili/gateways/kili_api_gateway/issue/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
"""Mixin extending Kili API Gateway class with Issue related operations."""

from typing import List, Optional

from kili.core.graphql.graphql_client import GraphQLClient
from kili.core.utils.pagination import BatchIteratorBuilder
from kili.domain.issue import Issue, IssueStatus, IssueType
from kili.gateways.kili_api_gateway.issue.operations import (
GQL_COUNT_ISSUES,
GQL_CREATE_ISSUES,
)
from kili.gateways.kili_api_gateway.issue.types import (
IssueToCreateKiliAPIGatewayInput,
IssueWhere,
)
from kili.utils import tqdm


class IssueOperationMixin:
"""GraphQL Mixin extending GraphQL Gateway class with Issue related operations."""

graphql_client: GraphQLClient

def create_issues(
self, type_: IssueType, issues: List[IssueToCreateKiliAPIGatewayInput]
) -> List[Issue]:
"""Send a GraphQL request calling createIssues resolver."""
created_issue_entities: List[Issue] = []
with tqdm.tqdm(total=len(issues)) as pbar:
for issues_batch in BatchIteratorBuilder(issues):
batch_targeted_asset_ids = [issue.asset_id for issue in issues_batch]
payload = {
"issues": [
{
"issueNumber": 0,
"labelID": issue.label_id,
"objectMid": issue.object_mid,
"type": type_,
"assetId": issue.asset_id,
"text": issue.text,
}
for issue in issues_batch
],
"where": {"idIn": batch_targeted_asset_ids},
}
result = self.graphql_client.execute(GQL_CREATE_ISSUES, payload)
batch_created_issues = result["data"]
created_issue_entities.extend(
[Issue(id_=issue["id"]) for issue in batch_created_issues]
)
pbar.update(len(issues_batch))
return created_issue_entities

def count_issues( # pylint: disable=too-many-arguments,
self,
project_id: str,
asset_id: Optional[str] = None,
asset_id_in: Optional[List[str]] = None,
issue_type: Optional[IssueType] = None,
status: Optional[IssueStatus] = None,
) -> int:
"""Send a GraphQL request calling countIssues resolver."""
where = IssueWhere(project_id, asset_id, asset_id_in, issue_type, status)
payload = {
"where": where.get_graphql_where_value(),
}
count_result = self.graphql_client.execute(GQL_COUNT_ISSUES, payload)
return count_result["data"]
21 changes: 21 additions & 0 deletions src/kili/gateways/kili_api_gateway/issue/operations.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
"""GraphQL Issues operations."""

GQL_CREATE_ISSUES = """
mutation createIssues(
$issues: [IssueToCreate!]!
$where: AssetWhere!
) {
data: createIssues(
issues: $issues
where: $where
) {
id
}
}
"""

GQL_COUNT_ISSUES = """
query countIssues($where: IssueWhere!) {
data: countIssues(where: $where)
}
"""
36 changes: 36 additions & 0 deletions src/kili/gateways/kili_api_gateway/issue/types.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
"""Types for the Issue-related Kili API gateway functions."""
from dataclasses import dataclass
from typing import List, Optional

from kili.domain.issue import IssueStatus, IssueType


@dataclass
class IssueToCreateKiliAPIGatewayInput:
"""Data about an issue to create needed in graphql createIssue resolver."""

label_id: Optional[str]
object_mid: Optional[str]
asset_id: str
text: Optional[str]


@dataclass
class IssueWhere:
"""Tuple to be passed to the IssueQuery to restrict query."""

project_id: str
asset_id: Optional[str] = None
asset_id_in: Optional[List[str]] = None
issue_type: Optional[IssueType] = None
status: Optional[IssueStatus] = None

def get_graphql_where_value(self):
"""Build the GraphQL IssueWhere variable value to be sent in an operation."""
return {
"project": {"id": self.project_id},
"asset": {"id": self.asset_id},
"assetIn": self.asset_id_in,
"status": self.status,
"type": self.issue_type,
}
Empty file.
Empty file.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
"""Module for methods and classes that are for internal use by Kili Technology only."""
"""Module for methods that are for internal use by Kili Technology only."""

from typeguard import typechecked

Expand All @@ -8,8 +8,8 @@
from kili.entrypoints.queries.api_key import QueriesApiKey


class KiliInternal(MutationsOrganization, QueriesApiKey):
"""Inherit classes for internal use by Kili Technology only."""
class InternalClientMethods(MutationsOrganization, QueriesApiKey):
"""Kili client methods for internal use by Kili Technology only."""

def __init__(self, kili):
"""Initializes the class.
Expand Down
Loading