Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
55 commits
Select commit Hold shift + click to select a range
a5e597a
SAClient config file relative path fix
Mar 14, 2023
823af7c
fix logs folder create issue
Mar 14, 2023
b86983f
changed DEBUG level in case of assignment failure filehandler logger …
Mar 15, 2023
98948dd
Merge pull request #577 from superannotateai/friday_fixes
nareksa Mar 15, 2023
c75482c
client init mixpanel traking
Mar 16, 2023
04dd1d7
client init mixpanel rename param sa_token
Mar 17, 2023
e5b06c9
fix mixpanel tests after sa_token param rename
Mar 17, 2023
dc5abec
Merge pull request #578 from superannotateai/1826_mixpanel
nareksa Mar 20, 2023
e0c24be
tests for async function
VaghinakDev Mar 21, 2023
a300522
Merge pull request #580 from superannotateai/test_async
nareksa Mar 21, 2023
5601d19
added set folder/project status functions
Mar 21, 2023
70c1e51
fix make_literal_validator
Mar 21, 2023
c92f4af
Nest asyncio fix
VaghinakDev Mar 21, 2023
c5bc910
Merge pull request #583 from superannotateai/literal_validator
nareksa Mar 21, 2023
8217015
added log message count case in set_status tests
Mar 21, 2023
12c64cf
added folder section in docs
Mar 21, 2023
01a3bac
Merge pull request #582 from superannotateai/1789_implementation
nareksa Mar 21, 2023
141e491
Merge branch 'friday' into 1852_implementation
VaghinakDev Mar 21, 2023
e354c83
Merge pull request #584 from superannotateai/1852_implementation
VaghinakDev Mar 21, 2023
50a2813
changed query function doc help url
Mar 22, 2023
addc7bc
Merge pull request #585 from superannotateai/1852_implementation
nareksa Mar 22, 2023
5183828
added OCR groupe type validation in class creation
Mar 22, 2023
581eaba
Merge pull request #581 from superannotateai/nest_async
VaghinakDev Mar 22, 2023
233c790
Merge branch 'friday' into 1821_implementation
VaghinakDev Mar 22, 2023
a255d59
fix OCR group type tests
Mar 22, 2023
b97358a
Merge pull request #586 from superannotateai/1821_implementation
VaghinakDev Mar 22, 2023
72183ee
added OCR type in docs
Mar 22, 2023
5714acb
Merge pull request #587 from superannotateai/OCR_docs
nareksa Mar 22, 2023
19cc32e
updated det/download annoations
VaghinakDev Mar 22, 2023
2c071df
Merge branch 'friday' into 1855_annotations
VaghinakDev Mar 22, 2023
51a1edb
Tests update
VaghinakDev Mar 22, 2023
e18dae2
Merge pull request #588 from superannotateai/1855_annotations
VaghinakDev Mar 23, 2023
1959625
Classes tests updates
VaghinakDev Mar 23, 2023
373ace7
Merge pull request #589 from superannotateai/classes_tests
VaghinakDev Mar 23, 2023
f741dbe
Update __init__.py
nareksa Mar 23, 2023
329f4e5
fix filehandler logger
Mar 24, 2023
25fa242
fix logs duplicating
Mar 24, 2023
9080ca1
Added tests for the async functions in thread
VaghinakDev Mar 27, 2023
189b8e0
Merge pull request #590 from superannotateai/1831_logs
nareksa Mar 27, 2023
e62942c
Merge pull request #591 from superannotateai/async_threads
nareksa Mar 27, 2023
c2308cc
Update sdk_interface.py
VaghinakDev Mar 27, 2023
a43c92f
Merge fix
VaghinakDev Mar 28, 2023
dd63d51
Fix async
VaghinakDev Mar 28, 2023
13cbfa6
Update __init__.py
VaghinakDev Mar 28, 2023
9a779ed
Update release.yml
VaghinakDev Mar 28, 2023
7ba0508
Update release.yml
VaghinakDev Mar 28, 2023
8cb6e9d
Update release.yml
VaghinakDev Mar 28, 2023
deb6c2d
fix search folder test
Mar 28, 2023
71adb21
Merge pull request #592 from superannotateai/test_fix
nareksa Mar 28, 2023
18296b2
Merge pull request #593 from superannotateai/friday
VaghinakDev Mar 30, 2023
7e144ad
Update __init__.py
VaghinakDev Mar 30, 2023
367588e
Update release.yml
VaghinakDev Mar 30, 2023
3c9cc12
Update __init__.py
VaghinakDev Mar 31, 2023
8a3b589
Update CHANGELOG.md
VaghinakDev Apr 2, 2023
82b48bd
Merge branch 'master' into develop
VaghinakDev Apr 2, 2023
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
10 changes: 5 additions & 5 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@ on:
jobs:
build-n-publish:
name: Build and publish Python 🐍 distributions 📦 to PyPI and TestPyPI
runs-on: ubuntu-18.04
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- name: Set up Python
uses: actions/setup-python@v1
uses: actions/setup-python@v4
with:
python-version: "3.7"
python-version: "3.8"
- name: Upgrade pip
run: >-
python -m
Expand All @@ -36,7 +36,7 @@ jobs:
.
- name: Publish distribution 📦 to PyPI
if: startsWith(github.ref, 'refs/tags')
uses: pypa/gh-action-pypi-publish@master
uses: pypa/gh-action-pypi-publish@release/v1
with:
password: ${{ secrets.pypi_password }}
verbose: true
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# Changelog
All release highlights of this project will be documented in this file.
## 4.4.11 - April 2, 2023
### Added
- `SAClient.set_project_status()` method.
- `SAClient.set_folder_status()` method.
### Updated
- `SAClient.create_annotation_class()` added OCR type attribute group support in the vector projects.
- `SAClient.create_annotation_classes_from_classes_json()` added OCR type attribute group support in the vector projects.
## 4.4.10 - March 12, 2023
### Updated
- Configuration file creation flow
Expand Down
1 change: 1 addition & 0 deletions docs/source/api_reference/api_client.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ Contents
:maxdepth: 8

api_project
api_folder
api_item
api_annotation
api_annotation_class
Expand Down
11 changes: 11 additions & 0 deletions docs/source/api_reference/api_folder.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
=======
Folders
=======

.. automethod:: superannotate.SAClient.search_folders
.. automethod:: superannotate.SAClient.assign_folder
.. automethod:: superannotate.SAClient.unassign_folder
.. automethod:: superannotate.SAClient.get_folder_by_id
.. automethod:: superannotate.SAClient.get_folder_metadata
.. automethod:: superannotate.SAClient.create_folder
.. automethod:: superannotate.SAClient.delete_folders
4 changes: 2 additions & 2 deletions docs/source/api_reference/api_image.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
==========
======
Images
==========
======


.. _ref_search_images:
Expand Down
18 changes: 6 additions & 12 deletions docs/source/api_reference/api_project.rst
Original file line number Diff line number Diff line change
@@ -1,25 +1,19 @@
==========
========
Projects
==========
========
.. _ref_projects:
.. _ref_search_projects:
.. automethod:: superannotate.SAClient.search_projects
.. automethod:: superannotate.SAClient.create_project
.. automethod:: superannotate.SAClient.search_projects
.. automethod:: superannotate.SAClient.create_project_from_metadata
.. automethod:: superannotate.SAClient.clone_project
.. automethod:: superannotate.SAClient.delete_project
.. automethod:: superannotate.SAClient.rename_project
.. automethod:: superannotate.SAClient.delete_project
.. _ref_get_project_metadata:
.. automethod:: superannotate.SAClient.get_project_by_id
.. automethod:: superannotate.SAClient.set_project_status
.. automethod:: superannotate.SAClient.get_project_metadata
.. automethod:: superannotate.SAClient.get_project_image_count
.. automethod:: superannotate.SAClient.search_folders
.. automethod:: superannotate.SAClient.assign_folder
.. automethod:: superannotate.SAClient.unassign_folder
.. automethod:: superannotate.SAClient.get_folder_by_id
.. automethod:: superannotate.SAClient.get_folder_metadata
.. automethod:: superannotate.SAClient.create_folder
.. automethod:: superannotate.SAClient.delete_folders
.. automethod:: superannotate.SAClient.upload_images_to_project
.. automethod:: superannotate.SAClient.attach_items_from_integrated_storage
.. automethod:: superannotate.SAClient.upload_image_to_project
Expand All @@ -30,5 +24,5 @@ Projects
.. automethod:: superannotate.SAClient.add_contributors_to_project
.. automethod:: superannotate.SAClient.get_project_settings
.. automethod:: superannotate.SAClient.set_project_default_image_quality_in_editor
.. automethod:: superannotate.SAClient.get_project_workflow
.. automethod:: superannotate.SAClient.set_project_workflow
.. automethod:: superannotate.SAClient.get_project_workflow
4 changes: 2 additions & 2 deletions docs/source/api_reference/api_team.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
==========
====
Team
==========
====


.. automethod:: superannotate.SAClient.get_team_metadata
Expand Down
1 change: 0 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ mixpanel==4.8.3
pydantic>=1.10.4
setuptools>=57.4.0
email-validator>=1.0.3
nest-asyncio==1.5.4
jsonschema==3.2.0
pandas>=1.1.4
aiofiles==0.8.0
Expand Down
3 changes: 2 additions & 1 deletion src/superannotate/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
import sys
import typing

__version__ = "4.4.10"
__version__ = "4.4.11"


sys.path.append(os.path.split(os.path.realpath(__file__))[0])

Expand Down
18 changes: 13 additions & 5 deletions src/superannotate/lib/app/interface/base_interface.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import functools
import json
import os
import platform
import sys
import typing
from inspect import signature
Expand Down Expand Up @@ -33,7 +34,7 @@ def __init__(self, token: TokenStr = None, config_path: str = None):
if token:
config = ConfigEntity(SA_TOKEN=token)
elif config_path:
config_path = Path(config_path)
config_path = Path(config_path).expanduser()
if not Path(config_path).is_file() or not os.access(
config_path, os.R_OK
):
Expand Down Expand Up @@ -124,10 +125,10 @@ def _retrieve_configs_from_env() -> typing.Union[ConfigEntity, None]:
class Tracker:
def get_mp_instance(self) -> Mixpanel:
client = self.get_client()
mp_token = "ca95ed96f80e8ec3be791e2d3097cf51"
if client:
if client.host != constants.BACKEND_URL:
mp_token = "e741d4863e7e05b1a45833d01865ef0d"
if client.controller._config.API_URL == constants.BACKEND_URL: # noqa
mp_token = "ca95ed96f80e8ec3be791e2d3097cf51"
else:
mp_token = "e741d4863e7e05b1a45833d01865ef0d"
return Mixpanel(mp_token)

@staticmethod
Expand All @@ -137,6 +138,8 @@ def get_default_payload(team_name, user_id):
"Team": team_name,
"Team Owner": user_id,
"Version": __version__,
"Python version": platform.python_version(),
"Python interpreter type": platform.python_implementation(),
}

def __init__(self, function):
Expand Down Expand Up @@ -170,6 +173,10 @@ def default_parser(function_name: str, kwargs: dict) -> tuple:
for key, value in kwargs.items():
if key == "self":
continue
elif key == "token":
properties["sa_token"] = str(bool(value))
elif key == "config_path":
properties[key] = str(bool(value))
elif value is None:
properties[key] = value
elif key == "project":
Expand Down Expand Up @@ -241,5 +248,6 @@ def __new__(mcs, name, bases, attrs):
attr_value, FunctionType
) and not attr_value.__name__.startswith("_"):
attrs[attr_name] = Tracker(validate_arguments(attr_value))
attrs["__init__"] = Tracker(validate_arguments(attrs["__init__"]))
tmp = super().__new__(mcs, name, bases, attrs)
return tmp
64 changes: 53 additions & 11 deletions src/superannotate/lib/app/interface/sdk_interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import copy
import io
import json
import logging
import os
import sys
import warnings
Expand Down Expand Up @@ -63,15 +64,15 @@
from lib.core.types import Project
from lib.infrastructure.utils import extract_project_folder
from lib.infrastructure.validators import wrap_error
import logging


logger = logging.getLogger("sa")


NotEmptyStr = TypeVar("NotEmptyStr", bound=constr(strict=True, min_length=1))


PROJECT_STATUS = Literal["Undefined", "NotStarted", "InProgress", "Completed", "OnHold"]
PROJECT_STATUS = Literal["NotStarted", "InProgress", "Completed", "OnHold"]

PROJECT_TYPE = Literal[
"Vector", "Pixel", "Video", "Document", "Tiled", "Other", "PointCloud"
Expand All @@ -91,13 +92,7 @@

ANNOTATOR_ROLE = Literal["Admin", "Annotator", "QA"]

FOLDER_STATUS = Literal[
"Undefined",
"NotStarted",
"InProgress",
"Completed",
"OnHold",
]
FOLDER_STATUS = Literal["NotStarted", "InProgress", "Completed", "OnHold"]


class Setting(TypedDict):
Expand Down Expand Up @@ -782,6 +777,52 @@ def search_annotation_classes(
for i in response.data
]

def set_project_status(self, project: NotEmptyStr, status: PROJECT_STATUS):
"""Set project status

:param project: project name
:type project: str
:param status: status to set, should be one of. \n
♦ “NotStarted” \n
♦ “InProgress” \n
♦ “Completed” \n
♦ “OnHold” \n
:type status: str
"""
project = self.controller.get_project(name=project)
project.status = constants.ProjectStatus.get_value(status)
response = self.controller.projects.update(project)
if response.errors:
raise AppException(f"Failed to change {project.name} status.")
logger.info(f"Successfully updated {project.name} status to {status}")

def set_folder_status(
self, project: NotEmptyStr, folder: NotEmptyStr, status: FOLDER_STATUS
):
"""Set folder status

:param project: project name
:type project: str
:param folder: folder name
:type folder: str
:param status: status to set, should be one of. \n
♦ “NotStarted” \n
♦ “InProgress” \n
♦ “Completed” \n
♦ “OnHold” \n
:type status: str
"""
project, folder = self.controller.get_project_folder(
project_name=project, folder_name=folder
)
folder.status = constants.FolderStatus.get_value(status)
response = self.controller.update(project, folder)
if response.errors:
raise AppException(f"Failed to change {project.name}/{folder.name} status.")
logger.info(
f"Successfully updated {project.name}/{folder.name} status to {status}"
)

def set_project_default_image_quality_in_editor(
self,
project: Union[NotEmptyStr, dict],
Expand Down Expand Up @@ -1360,7 +1401,8 @@ def create_annotation_class(
:type color: str

:param attribute_groups: list of attribute group dicts.
The values for the "group_type" key are "radio"|"checklist"|"text"|"numeric".
The values for the "group_type" key are "radio"|"checklist"|"text"|"numeric"|"ocr".
"ocr "group_type" key is only available for Vector projects.
Mandatory keys for each attribute group are

- "name"
Expand Down Expand Up @@ -2340,7 +2382,7 @@ def query(
subset: Optional[NotEmptyStr] = None,
):
"""Return items that satisfy the given query.
Query syntax should be in SuperAnnotate query language(https://doc.superannotate.com/docs/query-search-1).
Query syntax should be in SuperAnnotate query language(https://doc.superannotate.com/docs/explore-overview).

:param project: project name or folder path (e.g., “project1/folder1”)
:type project: str
Expand Down
32 changes: 15 additions & 17 deletions src/superannotate/lib/core/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
from lib.core.enums import UploadState
from lib.core.enums import UserRole


CONFIG = Config()
BACKEND_URL = "https://api.superannotate.com"
HOME_PATH = expanduser("~/.superannotate")
Expand All @@ -33,33 +32,32 @@


def setup_logging(level=DEFAULT_LOGGING_LEVEL, file_path=LOG_FILE_LOCATION):

logger = logging.getLogger("sa")
for handler in logger.handlers[:]: # remove all old handlers
logger.removeHandler(handler)
logger.propagate = True
logger.propagate = False
logger.setLevel(level)
stream_handler = logging.StreamHandler()
formatter = Formatter("SA-PYTHON-SDK - %(levelname)s - %(message)s")
stream_handler.setFormatter(formatter)
logger.addHandler(stream_handler)
try:
os.makedirs(file_path, exist_ok=True)
log_file_path = os.path.join(file_path, "sa.log")
open(log_file_path, "w").close()
if os.access(log_file_path, os.W_OK):
file_handler = RotatingFileHandler(
log_file_path,
maxBytes=5 * 1024 * 1024,
backupCount=5,
mode="a",
)
file_formatter = Formatter(
"SA-PYTHON-SDK - %(levelname)s - %(asctime)s - %(message)s"
)
file_handler.setFormatter(file_formatter)
logger.addHandler(file_handler)
file_handler = RotatingFileHandler(
log_file_path,
maxBytes=5 * 1024 * 1024,
backupCount=5,
mode="a",
)
file_formatter = Formatter(
"SA-PYTHON-SDK - %(levelname)s - %(asctime)s - %(message)s"
)
file_handler.setFormatter(file_formatter)
logger.addHandler(file_handler)

except OSError as e:
logging.error(e)
logger.debug(e)


DEFAULT_IMAGE_EXTENSIONS = ["jpg", "jpeg", "png", "tif", "tiff", "webp", "bmp"]
Expand Down
3 changes: 3 additions & 0 deletions src/superannotate/lib/core/entities/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,9 @@ def __copy__(self):
upload_state=self.upload_state,
)

def __eq__(self, other):
return self.id == other.id


class MLModelEntity(TimedBaseModel):
id: Optional[int]
Expand Down
3 changes: 1 addition & 2 deletions src/superannotate/lib/core/serviceproviders.py
Original file line number Diff line number Diff line change
Expand Up @@ -332,10 +332,9 @@ async def list_small_annotations(
raise NotImplementedError

@abstractmethod
def sort_items_by_size(
def get_upload_chunks(
self,
project: entities.ProjectEntity,
folder: entities.FolderEntity,
item_ids: List[int],
) -> Dict[str, List]:
raise NotImplementedError
Expand Down
Loading