Skip to content
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
21 changes: 21 additions & 0 deletions src/superannotate/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
import os
import sys

import requests
import superannotate.lib.core as constances
from packaging.version import parse
from superannotate.lib.app.analytics.class_analytics import attribute_distribution
from superannotate.lib.app.analytics.class_analytics import class_distribution
from superannotate.lib.app.annotation_helpers import add_annotation_bbox_to_json
Expand Down Expand Up @@ -298,9 +301,27 @@

__author__ = "Superannotate"


WORKING_DIR = os.path.split(os.path.realpath(__file__))[0]
sys.path.append(WORKING_DIR)
logging.getLogger("botocore").setLevel(logging.CRITICAL)
logging.config.fileConfig(
os.path.join(WORKING_DIR, "logging.conf"), disable_existing_loggers=False
)

local_version = parse(__version__)
if local_version.is_prerelease:
logging.info(constances.PACKAGE_VERSION_INFO_MESSAGE.format(__version__))
req = requests.get('https://pypi.python.org/pypi/superannotate/json')
if req.ok:
releases = req.json().get('releases', [])
pip_version = parse('0')
for release in releases:
ver = parse(release)
if not ver.is_prerelease or local_version.is_prerelease:
pip_version = max(pip_version, ver)
if pip_version.major > local_version.major:
logging.warning(constances.PACKAGE_VERSION_MAJOR_UPGRADE.format(local_version, pip_version))
elif pip_version > local_version:
logging.warning(constances.PACKAGE_VERSION_UPGRADE.format(local_version, pip_version)
)
23 changes: 17 additions & 6 deletions src/superannotate/lib/app/interface/sdk_interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -2315,8 +2315,11 @@ def attach_image_urls_to_project(
constances.ProjectType.VIDEO.value,
constances.ProjectType.DOCUMENT.value,
]:
raise AppException(LIMITED_FUNCTIONS[project["project"].project_type])

raise AppException(
constances.INVALID_PROJECT_TYPE_TO_PROCESS.format(
constances.ProjectType.get_name(project["project"].project_type)
)
)
images_to_upload, duplicate_images = get_paths_and_duplicated_from_csv(attachments)
use_case = controller.interactive_attach_urls(
project_name=project_name,
Expand Down Expand Up @@ -2374,8 +2377,12 @@ def attach_video_urls_to_project(
project = controller.get_project_metadata(project_name).data
project_folder_name = project_name + (f"/{folder_name}" if folder_name else "")

if not project["project"].project_type == constances.ProjectType.VIDEO.value:
raise AppException(LIMITED_FUNCTIONS[project["project"].project_type])
if project["project"].project_type != constances.ProjectType.VIDEO.value:
raise AppException(
constances.INVALID_PROJECT_TYPE_TO_PROCESS.format(
constances.ProjectType.get_name(project["project"].project_type)
)
)

images_to_upload, duplicate_images = get_paths_and_duplicated_from_csv(attachments)
use_case = controller.interactive_attach_urls(
Expand Down Expand Up @@ -3585,8 +3592,12 @@ def attach_document_urls_to_project(
project = controller.get_project_metadata(project_name).data
project_folder_name = project_name + (f"/{folder_name}" if folder_name else "")

if not project["project"].project_type == constances.ProjectType.DOCUMENT.value:
raise AppException(LIMITED_FUNCTIONS[project["project"].project_type])
if project["project"].project_type != constances.ProjectType.DOCUMENT.value:
raise AppException(
constances.INVALID_PROJECT_TYPE_TO_PROCESS.format(
constances.ProjectType.get_name(project["project"].project_type)
)
)

images_to_upload, duplicate_images = get_paths_and_duplicated_from_csv(attachments)

Expand Down
2 changes: 1 addition & 1 deletion src/superannotate/lib/app/mixp/config.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
TOKEN = "ca95ed96f80e8ec3be791e2d3097cf51"
TOKEN = "e741d4863e7e05b1a45833d01865ef0d"
2 changes: 1 addition & 1 deletion src/superannotate/lib/app/mixp/utils/parsers.py
Original file line number Diff line number Diff line change
Expand Up @@ -358,7 +358,7 @@ def search_annotation_classes(*args, **kwargs):
"event_name": "search_annotation_classes",
"properties": {
"project_name": get_project_name(project),
"name_prefix": name_prefix,
"Prefix": bool(name_prefix),
},
}

Expand Down
10 changes: 10 additions & 0 deletions src/superannotate/lib/core/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@
ATTACHING_UPLOAD_STATE_ERROR = "You cannot attach URLs in this type of project. Please attach it in an external storage project."
UPLOADING_UPLOAD_STATE_ERROR = "You cannot upload files in this type of project. Please upload it in an basic storage project."

INVALID_PROJECT_TYPE_TO_PROCESS = "The function does not support projects of type {}."
DEPRECATED_VIDEO_PROJECTS_MESSAGE = (
"The function does not support projects containing videos attached with URLs"
)
Expand Down Expand Up @@ -101,6 +102,15 @@
)
MOVE_PROJECT_LIMIT_ERROR_MESSAGE = "The number of items you want to move exceeds the limit of 500 000 items per project."

PACKAGE_VERSION_INFO_MESSAGE = "Development version {} of SuperAnnotate SDK is being used."

PACKAGE_VERSION_MAJOR_UPGRADE = "There is a major upgrade of SuperAnnotate Python SDK available on PyPI. " \
"We recommend upgrading. Run 'pip install --upgrade superannotate' to " \
"upgrade from your version {} to {}."

PACKAGE_VERSION_UPGRADE = "There is a newer version of SuperAnnotate Python SDK available on PyPI." \
" Run 'pip install --upgrade superannotate' to" \
" upgrade from your version {} to {}"
__alL__ = (
ProjectType,
UserRole,
Expand Down
3 changes: 1 addition & 2 deletions src/superannotate/lib/core/usecases/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -763,8 +763,7 @@ def execute(self):
image_ids=image_ids,
)
if not res.ok:
self._response.errors = res.json().get("error")
return self._response
res.raise_for_status()

success_images = []
failed_images = []
Expand Down
26 changes: 21 additions & 5 deletions tests/integration/test_attach_document_urls.py
Original file line number Diff line number Diff line change
@@ -1,39 +1,55 @@
import os
from os.path import dirname
from os.path import join

import src.superannotate as sa
from src.superannotate import AppException
import src.superannotate.lib.core as constances
from tests.integration.base import BaseTestCase


class TestDocumentUrls(BaseTestCase):
PROJECT_NAME = "document attach urls"
PATH_TO_URLS = "data_set/csv_files/text_urls.csv"
PATH_TO_50K_URLS = "data_set/501_urls.csv"
PATH_TO_URLS = "csv_files/text_urls.csv"
PATH_TO_50K_URLS = "501_urls.csv"
PROJECT_DESCRIPTION = "desc"
PROJECT_TYPE = "Document"

@property
def csv_path(self):
return os.path.join(dirname(dirname(__file__)), "data_set")

def test_attach_documents_urls(self):
uploaded, could_not_upload, existing_images = sa.attach_document_urls_to_project(
self.PROJECT_NAME,
os.path.join(dirname(dirname(__file__)), self.PATH_TO_URLS),
join(self.csv_path, self.PATH_TO_URLS)
)
self.assertEqual(len(uploaded), 11)
self.assertEqual(len(could_not_upload), 0)
self.assertEqual(len(existing_images), 1)

uploaded, could_not_upload, existing_images = sa.attach_document_urls_to_project(
self.PROJECT_NAME,
os.path.join(dirname(dirname(__file__)), self.PATH_TO_URLS),
join(self.csv_path, self.PATH_TO_URLS),
)
self.assertEqual(len(uploaded), 2)
self.assertEqual(len(could_not_upload), 0)
self.assertEqual(len(existing_images), 10)

def test_attach_video_urls_to_vector_project(self):
try:
sa.create_project("1", "!", "vector")
with self.assertRaisesRegexp(AppException, constances.INVALID_PROJECT_TYPE_TO_PROCESS.format("Vector")):
sa.attach_document_urls_to_project("1", join(self.csv_path, self.PATH_TO_URLS),)
except AssertionError:
raise
except Exception:
sa.delete_project("1")

def test_limitation(self):
self.assertRaises(
Exception,
sa.attach_document_urls_to_project,
self.PROJECT_NAME,
os.path.join(dirname(dirname(__file__)), self.PATH_TO_50K_URLS)
join(self.csv_path, self.PATH_TO_50K_URLS)
)
18 changes: 15 additions & 3 deletions tests/integration/test_attach_video_urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
from os.path import dirname

import src.superannotate as sa
from src.superannotate import AppException
import src.superannotate.lib.core as constances
from tests.integration.base import BaseTestCase


Expand All @@ -19,7 +21,7 @@ def csv_path(self):

@property
def csv_path_without_name_column(self):
return os.path.join(dirname(dirname(__file__)), self.PATH_TO_URLS)
return os.path.join(dirname(dirname(__file__)), self.PATH_TO_URLS_WITHOUT_NAMES)

def test_attach_video_urls(self):
uploaded, could_not_upload, existing_images = sa.attach_video_urls_to_project(
Expand All @@ -30,14 +32,24 @@ def test_attach_video_urls(self):
self.assertEqual(len(could_not_upload), 0)
self.assertEqual(len(existing_images), 1)

def test_attach_video_urls_to_vector_project(self):
try:
sa.create_project("1", "!", "vector")
with self.assertRaisesRegexp(AppException, constances.INVALID_PROJECT_TYPE_TO_PROCESS.format("Vector")):
sa.attach_video_urls_to_project("1", self.csv_path)
except AssertionError:
raise
except Exception:
sa.delete_project("1")

def test_attach_video_urls_without_name_column(self):
uploaded, could_not_upload, existing_images = sa.attach_video_urls_to_project(
self.PROJECT_NAME,
self.csv_path_without_name_column
)
self.assertEqual(len(uploaded), 7)
self.assertEqual(len(uploaded), 8)
self.assertEqual(len(could_not_upload), 0)
self.assertEqual(len(existing_images), 1)
self.assertEqual(len(existing_images), 0)

def test_get_exports(self):
sa.attach_video_urls_to_project(
Expand Down
6 changes: 4 additions & 2 deletions tests/integration/test_depricated_functions_document.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import src.superannotate as sa
from src.superannotate import AppException
from src.superannotate.lib.core import LIMITED_FUNCTIONS
from src.superannotate.lib.core import INVALID_PROJECT_TYPE_TO_PROCESS
from src.superannotate.lib.core import ProjectType
from src.superannotate.lib.core import DEPRICATED_DOCUMENT_VIDEO_MESSAGE

Expand All @@ -21,6 +22,7 @@ class TestDeprecatedFunctionsDocument(TestCase):
PROJECT_DESCRIPTION_2 = "second project"
PROJECT_TYPE_2 = "Vector"
EXCEPTION_MESSAGE = LIMITED_FUNCTIONS[ProjectType.DOCUMENT.value]
EXCEPTION_MESSAGE_2 = INVALID_PROJECT_TYPE_TO_PROCESS
EXCEPTION_MESSAGE_DOCUMENT_VIDEO = DEPRICATED_DOCUMENT_VIDEO_MESSAGE

def setUp(self, *args, **kwargs):
Expand Down Expand Up @@ -106,7 +108,7 @@ def test_deprecated_functions(self):
os.path.join(dirname(dirname(__file__)), self.PATH_TO_URLS),
)
except AppException as e:
self.assertIn(self.EXCEPTION_MESSAGE, str(e))
self.assertIn(self.EXCEPTION_MESSAGE_2.format(self.PROJECT_TYPE), str(e))
try:
sa.clone_project(self.PROJECT_NAME_2, self.PROJECT_NAME)
except AppException as e:
Expand Down Expand Up @@ -194,7 +196,7 @@ def test_deprecated_functions(self):
os.path.join(dirname(dirname(__file__)), self.PATH_TO_URLS),
)
except AppException as e:
self.assertIn(self.EXCEPTION_MESSAGE, str(e))
self.assertIn(self.EXCEPTION_MESSAGE_2.format(self.PROJECT_TYPE), str(e))
try:
sa.benchmark(self.PROJECT_NAME, "some", ["some folder1"])
except AppException as e:
Expand Down
Loading