Skip to content

Commit 1a7ca5e

Browse files
Merge pull request #1908 from kili-technology/feature/lab-3753-aa-sdk-user-i-can-install-kili-with-optional-dependencies
chore(lab-3743): refine dependencies and make some optional
2 parents 24d0cea + c4751d9 commit 1a7ca5e

File tree

13 files changed

+164
-71
lines changed

13 files changed

+164
-71
lines changed

pyproject.toml

Lines changed: 48 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -32,25 +32,19 @@ dependencies = [
3232
"pandas >= 1.0.0, < 3.0.0",
3333
"click >= 8.0.0, < 8.1.8",
3434
"requests >= 2.0.0, < 3.0.0",
35-
"tabulate >= 0.9.0, < 0.10.0",
3635
"tenacity >= 8.0.0, < 9.0.0",
3736
"tqdm >= 4.0.0, < 5.0.0",
3837
"typeguard >= 4, < 5",
3938
"typing-extensions >= 4.1.0, < 5.0.0",
4039
"pyparsing >= 3.0.0, < 4.0.0",
4140
"websocket-client >= 1.0.0, < 2.0.0",
42-
"pyyaml >= 6.0, < 7.0",
43-
"Pillow >=9.0.0, <11.0.0",
4441
"cuid >= 0.4, < 0.5",
4542
"urllib3 >= 1.26, < 3",
46-
"ffmpeg-python >= 0.2.0, < 0.3.0",
4743
"gql[requests,websockets] >= 3.5.0b5, < 4.0.0",
4844
"filelock >= 3.0.0, < 4.0.0",
4945
"pip-system-certs >= 4.0.0, < 5.0.0; platform_system=='Windows'",
5046
"pyrate-limiter >= 3, < 4",
51-
"shapely >= 1.8, < 3",
52-
"pyproj == 3.6.1",
53-
"kili-formats == 0.1.8"
47+
"kili-formats == 0.2.0"
5448
]
5549
urls = { homepage = "https://github.com/kili-technology/kili-python-sdk" }
5650

@@ -89,12 +83,57 @@ dev = [
8983
# dead code detection
9084
"vulture==2.11",
9185
"dead==1.5.2",
92-
# other optional dependencies
86+
# optional dependencies
87+
"kili-formats[all] == 0.2.0",
9388
"opencv-python >= 4.0.0, < 5.0.0",
9489
"azure-storage-blob >= 12.0.0, < 13.0.0",
90+
# optional dependencies gis
91+
"pyproj >= 2.6.1, < 3; python_version < '3.9'",
92+
"pyproj == 3.6.1; python_version >= '3.9'",
93+
"shapely >= 1.8, < 3",
94+
# optional dependencies - cli
95+
"tabulate >= 0.9.0, < 0.10.0",
96+
# optional dependencies - yolo
97+
"pyyaml >= 6.0, < 7.0",
98+
# optional dependencies - image
99+
"Pillow >=9.0.0, <11.0.0"
100+
]
101+
all = [
102+
# aggregate all optional deps without dev
103+
"azure-storage-blob >= 12.0.0, < 13.0.0",
104+
"kili-formats[all] == 0.2.0",
105+
"opencv-python >= 4.0.0, < 5.0.0",
106+
"Pillow >=9.0.0, <11.0.0",
107+
"pyproj == 3.6.1; python_version >= '3.9'",
108+
"pyproj >= 2.6.1, < 3; python_version < '3.9'",
109+
"pyyaml >= 6.0, < 7.0",
110+
"shapely >= 1.8, < 3",
111+
"tabulate >= 0.9.0, < 0.10.0"
95112
]
96-
image-utils = ["opencv-python >= 4.0.0, < 5.0.0"]
97113
azure = ["azure-storage-blob >= 12.0.0, < 13.0.0"]
114+
cli = [
115+
"tabulate >= 0.9.0, < 0.10.0"
116+
]
117+
coco = [
118+
"kili-formats[coco] == 0.2.0"
119+
]
120+
gis = [
121+
"pyproj >= 2.6.1, < 3; python_version < '3.9'",
122+
"pyproj == 3.6.1; python_version >= '3.9'",
123+
"shapely >= 1.8, < 3"
124+
]
125+
image = [
126+
"Pillow >=9.0.0, <11.0.0",
127+
"kili-formats[image] == 0.2.0"
128+
]
129+
image-utils = ["opencv-python >= 4.0.0, < 5.0.0"]
130+
131+
video = [
132+
"kili-formats[video] == 0.2.0"
133+
]
134+
yolo = [
135+
"pyyaml >= 6.0, < 7.0"
136+
]
98137

99138
[tool.pyright]
100139
exclude = ["**/__pycache__", ".github/scripts/upload_test_stats_datadog.py"]

src/kili/entrypoints/cli/project/create.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
from typing import Optional
55

66
import click
7-
from tabulate import tabulate
87

98
from kili.domain.project import InputTypeEnum, ProjectId
109
from kili.entrypoints.cli.common_args import Options
@@ -63,6 +62,10 @@ def create_project(
6362
To build a Kili project interface, please visit: \n
6463
https://docs.kili-technology.com/docs/customizing-the-interface-through-json-settings
6564
"""
65+
try:
66+
from tabulate import tabulate # pylint: disable=import-outside-toplevel
67+
except ImportError as e:
68+
raise ImportError("Install with `pip install kili[cli]` to use this feature.") from e
6669
kili = get_kili_client(api_key=api_key, api_endpoint=endpoint)
6770

6871
if ((interface is not None) + (project_id_src is not None)) > 1:

src/kili/entrypoints/cli/project/describe.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
from typing import Optional
44

55
import click
6-
from tabulate import tabulate
76

87
from kili.domain.project import ProjectId
98
from kili.entrypoints.cli.common_args import Arguments, Options
@@ -27,6 +26,10 @@ def describe_project(api_key: Optional[str], endpoint: Optional[str], project_id
2726
kili project describe --project-id <project_id>
2827
```
2928
"""
29+
try:
30+
from tabulate import tabulate # pylint: disable=import-outside-toplevel
31+
except ImportError as e:
32+
raise ImportError("Install with `pip install kili[cli]` to use this feature.") from e
3033
kili = get_kili_client(api_key=api_key, api_endpoint=endpoint)
3134
query_fields = [
3235
"title",

src/kili/entrypoints/cli/project/list_.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
import click
66
import numpy as np
77
import pandas as pd
8-
from tabulate import tabulate
98

109
from kili.adapters.kili_api_gateway.helpers.queries import QueryOptions
1110
from kili.domain.project import ProjectFilters
@@ -33,6 +32,10 @@ def list_projects(api_key: Optional[str], endpoint: Optional[str], tablefmt: str
3332
kili project list --max 10 --stdout-format pretty
3433
```
3534
"""
35+
try:
36+
from tabulate import tabulate # pylint: disable=import-outside-toplevel
37+
except ImportError as e:
38+
raise ImportError("Install with `pip install kili[cli]` to use this feature.") from e
3639
kili = get_kili_client(api_key=api_key, api_endpoint=endpoint)
3740
projects = list(
3841
kili.kili_api_gateway.list_projects(

src/kili/entrypoints/cli/project/member/list_.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44

55
import click
66
import pandas as pd
7-
from tabulate import tabulate
87

98
from kili.adapters.kili_api_gateway.helpers.queries import QueryOptions
109
from kili.core.graphql.operations.project_user.queries import (
@@ -31,6 +30,10 @@ def list_members(api_key: Optional[str], endpoint: Optional[str], project_id: st
3130
kili project member list <project_id> --stdout-format pretty
3231
```
3332
"""
33+
try:
34+
from tabulate import tabulate # pylint: disable=import-outside-toplevel
35+
except ImportError as e:
36+
raise ImportError("Install with `pip install kili[cli]` to use this feature.") from e
3437
kili = get_kili_client(api_key=api_key, api_endpoint=endpoint)
3538
members_list = list(
3639
ProjectUserQuery(kili.graphql_client, kili.http_client)(

src/kili/services/asset_import/image.py

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@
33
import os
44
from typing import List
55

6-
from PIL import Image, UnidentifiedImageError
7-
86
from kili.core.constants import mime_extensions_that_need_post_processing
97
from kili.core.helpers import get_mime_type
108
from kili.domain.project import InputType
@@ -13,8 +11,6 @@
1311
from .constants import LARGE_IMAGE_THRESHOLD_SIZE, MAX_WIDTH_OR_HEIGHT_NON_TILED
1412
from .types import AssetLike
1513

16-
Image.MAX_IMAGE_PIXELS = None
17-
1814

1915
class ImageDataImporter(BaseAbstractAssetImporter):
2016
"""Class for importing assets into an IMAGE or GEOSPATIAL project."""
@@ -53,6 +49,13 @@ def import_assets(self, assets: List[AssetLike], input_type: InputType):
5349
@staticmethod
5450
def get_is_large_image(image_path: str) -> bool:
5551
"""Define if an image is too large and so on has to be tiled."""
52+
try:
53+
from PIL import Image # pylint: disable=import-outside-toplevel
54+
55+
Image.MAX_IMAGE_PIXELS = None
56+
except ImportError as e:
57+
raise ImportError("Install with `pip install kili[image]` to use this feature.") from e
58+
5659
if os.path.getsize(image_path) >= LARGE_IMAGE_THRESHOLD_SIZE:
5760
return True
5861

@@ -63,6 +66,10 @@ def get_is_large_image(image_path: str) -> bool:
6366
@staticmethod
6467
def split_asset_by_upload_type(assets: List[AssetLike], is_hosted: bool):
6568
"""Split assets into two groups, assets to to imported synchronously or asynchronously."""
69+
try:
70+
from PIL import UnidentifiedImageError # pylint: disable=import-outside-toplevel
71+
except ImportError as e:
72+
raise ImportError("Install with `pip install kili[image]` to use this feature.") from e
6673
if is_hosted:
6774
return assets, []
6875
sync_assets, async_assets = [], []

src/kili/services/export/format/coco/__init__.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,10 +51,12 @@ def images_folder(self) -> Path:
5151
def process_and_save(self, assets: List[Dict], output_filename: Path):
5252
"""Extract formatted annotations from labels."""
5353
clean_assets = self.preprocess_assets(assets)
54-
55-
self._save_assets_export(
56-
clean_assets, self.export_root_folder, annotation_modifier=self.annotation_modifier
57-
)
54+
try:
55+
self._save_assets_export(
56+
clean_assets, self.export_root_folder, annotation_modifier=self.annotation_modifier
57+
)
58+
except ImportError as e:
59+
raise ImportError("Install with `pip install kili[coco]` to use this feature.") from e
5860
self.create_readme_kili_file(self.export_root_folder)
5961
self.make_archive(self.export_root_folder, output_filename)
6062

src/kili/services/export/format/kili/__init__.py

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -88,12 +88,17 @@ def _cut_video_assets(self, assets: List[Dict]) -> List[Dict]:
8888
if nbr_frames == 0:
8989
continue
9090
leading_zeros = len(str(nbr_frames))
91-
asset["jsonContent"] = cut_video(
92-
video_path=asset["content"],
93-
asset=asset,
94-
leading_zeros=leading_zeros,
95-
output_dir=self.images_folder,
96-
)
91+
try:
92+
asset["jsonContent"] = cut_video(
93+
video_path=asset["content"],
94+
asset=asset,
95+
leading_zeros=leading_zeros,
96+
output_dir=self.images_folder,
97+
)
98+
except ImportError as e:
99+
raise ImportError(
100+
"Install with `pip install kili[video]` to use this feature."
101+
) from e
97102
return assets
98103

99104
def process_and_save(self, assets: List[Dict], output_filename: Path) -> None:

src/kili/services/export/format/voc/__init__.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -93,9 +93,14 @@ def _process_asset(
9393

9494
# video with shouldUseNativeVideo set to True (no frames available)
9595
elif Path(asset["content"]).is_file():
96-
width, height = get_video_dimensions(asset)
97-
cut_video(asset["content"], asset, leading_zeros, Path(asset["content"]).parent)
98-
frame_ext = ".jpg"
96+
try:
97+
width, height = get_video_dimensions(asset)
98+
cut_video(asset["content"], asset, leading_zeros, Path(asset["content"]).parent)
99+
frame_ext = ".jpg"
100+
except ImportError as e:
101+
raise ImportError(
102+
"Install with `pip install kili[video]` to use this feature."
103+
) from e
99104

100105
else:
101106
raise FileNotFoundError(f"Could not find frames or video for asset {asset}")

src/kili/services/export/format/yolo/__init__.py

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -281,12 +281,15 @@ def _process_asset(
281281

282282
# If the asset is a video, we need to cut it into frames
283283
if project_input_type == "VIDEO" and asset["jsonContent"] == "" and with_assets:
284-
asset["jsonContent"] = cut_video(
285-
video_path=asset["content"],
286-
asset=asset,
287-
leading_zeros=leading_zeros,
288-
output_dir=images_folder,
289-
)
284+
try:
285+
asset["jsonContent"] = cut_video(
286+
video_path=asset["content"],
287+
asset=asset,
288+
leading_zeros=leading_zeros,
289+
output_dir=images_folder,
290+
)
291+
except ImportError as e:
292+
raise ImportError("Install with `pip install kili[video]` to use this feature.") from e
290293

291294
content_frames = []
292295
if isinstance(asset["jsonContent"], list):

0 commit comments

Comments
 (0)