Skip to content

Commit e32fa24

Browse files
authored
Merge pull request #851 from superannotateai/develop
Develop
2 parents 74ae4ba + ae0896b commit e32fa24

54 files changed

Lines changed: 1591 additions & 819 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.pre-commit-config.yaml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ repos:
2020
name: Style Guide Enforcement (flake8)
2121
args:
2222
- '--max-line-length=120'
23-
- --ignore=D100,D203,D405,W503,E203,E501,F841,E126,E712,E123,E131,F821,E121,W605,E402
23+
- --ignore=D100,D203,D405,W503,E203,E501,F841,E126,E712,E123,E131,F821,E121,W605,E402,E704
2424
- repo: 'https://github.com/asottile/pyupgrade'
2525
rev: v3.21.2
2626
hooks:
@@ -62,7 +62,9 @@ repos:
6262
# args:
6363
# - '--disable=R0903,C0111,C0301,W0703,R0914,R0801,R0913,E0401,W0511,C0413,R0902,C0103,W0201,C0209,W1203,W0707,C0415,W0611'
6464
# - repo: 'https://github.com/asottile/dead'
65-
# rev: v1.3.0
65+
# rev: v2.1.0
6666
# hooks:
6767
# - id: dead
68+
# args: [--exclude, docs/source/conf.py|src/superannotate/lib/app/interface/sdk_interface.py|src/superannotate/lib/app/interface/cli_interface.py]
69+
6870
exclude: src/lib/app/analytics | src/lib/app/input_converters

CHANGELOG.rst

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,21 @@ History
66

77
All release highlights of this project will be documented in this file.
88

9+
4.5.5 - May 31, 2026
10+
______________________
11+
12+
**Added**
13+
14+
- ``SAClient.query.count()`` Returns the number of items that match a query.
15+
- ``SAClient.grant_project_user_permissions()`` Grants project-level user permissions.
16+
- ``SAClient.revoke_project_user_permissions()`` Revokes project-level user permissions.
17+
18+
**Updated**
19+
20+
- ``SAClient.list_users()`` Now returns user permissions.
21+
- ``SAClient.create_project()`` Now supports the `MaxIdleDuration` setting.
22+
23+
924
4.5.4 - April 23, 2026
1025
______________________
1126

docs/source/api_reference/api_project.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,3 +31,5 @@ Projects
3131
.. automethod:: superannotate.SAClient.list_categories
3232
.. automethod:: superannotate.SAClient.remove_categories
3333
.. automethod:: superannotate.SAClient.remove_users_from_project
34+
.. automethod:: superannotate.SAClient.grant_project_user_permissions
35+
.. automethod:: superannotate.SAClient.revoke_project_user_permissions

docs/source/conf.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
# -- Project information -----------------------------------------------------
77

88
project = "SuperAnnotate Python SDK"
9-
copyright = "2021, SuperAnnotate AI"
9+
copyright = "2026, SuperAnnotate AI"
1010
author = "SuperAnnotate AI"
1111

1212
# The full version, including alpha/beta/rc tags

pytest.ini

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@ minversion = 3.7
33
log_cli=true
44
python_files = test_*.py
55
;pytest_plugins = ['pytest_profiling']
6-
;addopts = -n 6 --dist loadscope
6+
addopts = -n 6 --dist loadscope

src/superannotate/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import os
33
import sys
44

5-
__version__ = "4.5.4"
5+
__version__ = "4.5.5"
66

77

88
os.environ.update({"sa_version": __version__})

src/superannotate/lib/app/analytics/aggregators.py

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -384,9 +384,7 @@ def aggregate_image_annotations_as_df(self, annotations_paths: list[str]):
384384
annotation_json = None
385385
with open(annotation_path) as fp:
386386
annotation_json = json.load(fp)
387-
parts = Path(annotation_path).name.split(self._annotation_suffix)
388387
row_data = self.__fill_image_metadata(row_data, annotation_json["metadata"])
389-
annotation_instance_id = 0
390388

391389
# include comments
392390
for annotation in annotation_json["comments"]:
@@ -433,10 +431,8 @@ def aggregate_image_annotations_as_df(self, annotations_paths: list[str]):
433431
if Path(annotation_path).parent != Path(self.project_root):
434432
folder_name = Path(annotation_path).parent.name
435433
instance_row.folderName = folder_name
436-
num_added = 0
437434
if not attributes:
438435
rows.append(instance_row)
439-
num_added = 1
440436
else:
441437
for attribute in attributes:
442438
attribute_row = copy.copy(instance_row)
@@ -469,10 +465,6 @@ def aggregate_image_annotations_as_df(self, annotations_paths: list[str]):
469465
attribute_row.attributeName = attribute_name
470466

471467
rows.append(attribute_row)
472-
num_added += 1
473-
474-
if num_added > 0:
475-
annotation_instance_id += 1
476468

477469
df = pd.DataFrame([row.__dict__ for row in rows], dtype=object)
478470
df = df.astype({"probability": float})

src/superannotate/lib/app/analytics/common.py

Lines changed: 0 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
from pathlib import Path
44

55
import pandas as pd
6-
import plotly.express as px
76
from lib.core.exceptions import AppException
87

98
logger = logging.getLogger("sa")
@@ -558,50 +557,3 @@ def consensus(df, item_name, annot_type):
558557
instance_id += 1
559558

560559
return image_data
561-
562-
563-
def consensus_plot(consensus_df, *_, **__):
564-
plot_data = consensus_df.copy()
565-
566-
# annotator-wise boxplot
567-
annot_box_fig = px.box(
568-
plot_data,
569-
x="creatorEmail",
570-
y="score",
571-
points="all",
572-
color="creatorEmail",
573-
color_discrete_sequence=px.colors.qualitative.Dark24,
574-
)
575-
annot_box_fig.show()
576-
577-
# project-wise boxplot
578-
project_box_fig = px.box(
579-
plot_data,
580-
x="folderName",
581-
y="score",
582-
points="all",
583-
color="folderName",
584-
color_discrete_sequence=px.colors.qualitative.Dark24,
585-
)
586-
project_box_fig.show()
587-
588-
# scatter plot of score vs area
589-
fig = px.scatter(
590-
plot_data,
591-
x="area",
592-
y="score",
593-
color="className",
594-
symbol="creatorEmail",
595-
facet_col="folderName",
596-
color_discrete_sequence=px.colors.qualitative.Dark24,
597-
hover_data={
598-
"className": False,
599-
"itemName": True,
600-
"folderName": False,
601-
"area": False,
602-
"score": False,
603-
},
604-
)
605-
fig.for_each_annotation(lambda a: a.update(text=a.text.split("=")[-1]))
606-
fig.for_each_trace(lambda t: t.update(name=t.name.split("=")[-1]))
607-
fig.show()

src/superannotate/lib/app/input_converters/conversion.py

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -94,16 +94,6 @@ def _passes_type_sanity(params_info):
9494
)
9595

9696

97-
def _passes_list_members_type_sanity(lists_info):
98-
for _list in lists_info:
99-
for _list_member in _list[0]:
100-
if not isinstance(_list_member, _list[2]):
101-
raise AppException(
102-
"'%s' should be list of '%s', but contains '%s'"
103-
% (_list[1], _list[2], type(_list_member))
104-
)
105-
106-
10797
def _passes_value_sanity(values_info):
10898
for value in values_info:
10999
if value[0] not in value[2]:

src/superannotate/lib/app/input_converters/converters/coco_converters/coco_to_sa_pixel.py

Lines changed: 0 additions & 19 deletions
This file was deleted.

0 commit comments

Comments
 (0)