Skip to content

Commit

Permalink
Merge pull request #7811 from cvat-ai/release-2.12.1
Browse files Browse the repository at this point in the history
Release v2.12.1
  • Loading branch information
cvat-bot[bot] authored Apr 29, 2024
2 parents 616cd7e + 229a041 commit 6990168
Show file tree
Hide file tree
Showing 116 changed files with 3,928 additions and 2,459 deletions.
1 change: 0 additions & 1 deletion .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,6 @@
"env": {
"CVAT_SERVERLESS": "1",
"ALLOWED_HOSTS": "*",
"IAM_OPA_BUNDLE": "1",
"DJANGO_LOG_SERVER_HOST": "localhost",
"DJANGO_LOG_SERVER_PORT": "8282"
},
Expand Down
23 changes: 23 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,29 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

<!-- scriv-insert-here -->

<a id='changelog-2.12.1'></a>
## \[2.12.1\] - 2024-04-26

### Fixed

- Formats with the custom `track_id` attribute should import `outside` track shapes properly (e.g. `COCO`, `COCO Keypoints`, `Datumaro`, `PASCAL VOC`)
(<https://github.com/opencv/cvat/pull/7669>)

- Inefficient resources fetching in admin panel leading to 504 Gateway Timeout
(<https://github.com/cvat-ai/cvat/pull/7767>)

- Optimized memory usage when retrieving annotations by disabling internal Django QuerySet caching
(<https://github.com/cvat-ai/cvat/pull/7748>)

- Annotations are not shown on the `0` frame sometimes
(<https://github.com/cvat-ai/cvat/pull/7796>)

- Extra requests in PolicyEnforcer when at least one policy is rejected, others are not checked
(<https://github.com/cvat-ai/cvat/pull/7803>)

- Project's `updated_date` was not updated after changing annotations in jobs
(<https://github.com/cvat-ai/cvat/pull/7808>)

<a id='changelog-2.12.0'></a>
## \[2.12.0\] - 2024-04-15

Expand Down
2 changes: 1 addition & 1 deletion Dockerfile.ci
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ RUN apt-get update && \
&& \
curl https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add - && \
echo 'deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main' | tee /etc/apt/sources.list.d/google-chrome.list && \
curl https://deb.nodesource.com/setup_16.x | bash - && \
curl https://deb.nodesource.com/setup_20.x | bash - && \
DEBIAN_FRONTEND=noninteractive apt-get --no-install-recommends install -yq \
google-chrome-stable \
nodejs \
Expand Down
15 changes: 13 additions & 2 deletions cvat-canvas/src/typescript/canvasModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -554,6 +554,14 @@ export class CanvasModelImpl extends MasterImpl implements CanvasModel {
}

this.data.imageID = frameData.number;

// We set objects immideately to avoid outdated data in case if setup() is called
// multiple times before the frameData.data() promise is resolved.
// If promise is rejected we restore previous objects
const prevZLayer = this.data.zLayer;
const prevObjects = this.data.objects;
this.data.zLayer = zLayer;
this.data.objects = objectStates;
frameData
.data((): void => {
this.data.image = null;
Expand Down Expand Up @@ -596,8 +604,6 @@ export class CanvasModelImpl extends MasterImpl implements CanvasModel {
}

this.notify(UpdateReasons.IMAGE_CHANGED);
this.data.zLayer = zLayer;
this.data.objects = objectStates;
this.notify(UpdateReasons.OBJECTS_UPDATED);
})
.catch((exception: unknown): void => {
Expand All @@ -608,6 +614,11 @@ export class CanvasModelImpl extends MasterImpl implements CanvasModel {
} else {
this.data.exception = new Error('Unknown error occured when fetching image data');
}
// Restore only relevant data in case if setup() is called multiple times
if (this.data.objects === objectStates && this.data.zLayer === zLayer) {
this.data.objects = prevObjects;
this.data.zLayer = prevZLayer;
}
this.notify(UpdateReasons.DATA_FAILED);
}
});
Expand Down
2 changes: 1 addition & 1 deletion cvat-canvas/src/typescript/canvasView.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ export class CanvasViewImpl implements CanvasView, Listener {
return this.controller.mode;
}

private onMessage = (messages: CanvasHint[] | null, topic: string) => {
private onMessage = (messages: CanvasHint[] | null, topic: string): void => {
this.canvas.dispatchEvent(
new CustomEvent('canvas.message', {
bubbles: false,
Expand Down
6 changes: 3 additions & 3 deletions cvat-canvas/src/typescript/objectSelector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,15 +91,15 @@ export class ObjectSelectorImpl implements ObjectSelector {
return filtered;
}

private onMouseDown = (event: MouseEvent) => {
private onMouseDown = (event: MouseEvent): void => {
const point = translateToSVG((this.canvas.node as any) as SVGSVGElement, [event.clientX, event.clientY]);
this.mouseDownPosition = { x: point[0], y: point[1] };
this.selectionRect = this.canvas.rect().addClass('cvat_canvas_selection_box');
this.selectionRect.attr({ 'stroke-width': consts.BASE_STROKE_WIDTH / this.geometry.scale });
this.selectionRect.attr({ ...this.mouseDownPosition });
};

private onMouseUp = (event: MouseEvent) => {
private onMouseUp = (event: MouseEvent): void => {
if (this.selectionRect) {
this.selectionRect.remove();
this.selectionRect = null;
Expand Down Expand Up @@ -138,7 +138,7 @@ export class ObjectSelectorImpl implements ObjectSelector {
}
};

private onMouseMove = (event: MouseEvent) => {
private onMouseMove = (event: MouseEvent): void => {
if (this.selectionRect) {
const box = this.getSelectionBox(event);
this.selectionRect.attr({
Expand Down
2 changes: 1 addition & 1 deletion cvat-cli/requirements/base.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
cvat-sdk~=2.12.0
cvat-sdk~=2.12.1
Pillow>=10.3.0
setuptools>=65.5.1 # not directly required, pinned by Snyk to avoid a vulnerability
2 changes: 1 addition & 1 deletion cvat-cli/src/cvat_cli/version.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
VERSION = "2.12.0"
VERSION = "2.12.1"
2 changes: 1 addition & 1 deletion cvat-core/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "cvat-core",
"version": "15.0.2",
"version": "15.0.3",
"type": "module",
"description": "Part of Computer Vision Tool which presents an interface for client-side integration",
"main": "src/api.ts",
Expand Down
10 changes: 5 additions & 5 deletions cvat-core/src/annotations-objects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2075,7 +2075,7 @@ export class SkeletonShape extends Shape {
return new ObjectState(this.get(frame));
}

const updateElements = (affectedElements, action, property: 'points' | 'occluded' | 'hidden' | 'lock') => {
const updateElements = (affectedElements, action, property: 'points' | 'occluded' | 'hidden' | 'lock'): void => {
const undoSkeletonProperties = this.elements.map((element) => element[property]);
const undoSource = this.source;
const redoSource = this.readOnlyFields.includes('source') ? this.source : computeNewSource(this.source);
Expand Down Expand Up @@ -2540,7 +2540,7 @@ class PolyTrack extends Track {
return updatedMatching;
}

function reduceInterpolation(interpolatedPoints, matching, leftPoints, rightPoints) {
function reduceInterpolation(interpolatedPoints, matching, leftPoints, rightPoints): void {
function averagePoint(points: Point2D[]): Point2D {
let sumX = 0;
let sumY = 0;
Expand All @@ -2559,7 +2559,7 @@ class PolyTrack extends Track {
return Math.sqrt((point1.x - point2.x) ** 2 + (point1.y - point2.y) ** 2);
}

function minimizeSegment(baseLength: number, N: number, startInterpolated, stopInterpolated) {
function minimizeSegment(baseLength: number, N: number, startInterpolated, stopInterpolated): void {
const threshold = baseLength / (2 * N);
const minimized = [interpolatedPoints[startInterpolated]];
let latestPushed = startInterpolated;
Expand Down Expand Up @@ -2596,7 +2596,7 @@ class PolyTrack extends Track {
interpolatedIndexes[i] = matching[i].map(() => accumulated++);
}

function leftSegment(start, stop) {
function leftSegment(start, stop): void {
const startInterpolated = interpolatedIndexes[start][0];
const stopInterpolated = interpolatedIndexes[stop][0];

Expand All @@ -2611,7 +2611,7 @@ class PolyTrack extends Track {
reduced.push(...minimizeSegment(baseLength, N, startInterpolated, stopInterpolated));
}

function rightSegment(leftPoint) {
function rightSegment(leftPoint): void {
const start = matching[leftPoint][0];
const [stop] = matching[leftPoint].slice(-1);
const startInterpolated = interpolatedIndexes[leftPoint][0];
Expand Down
4 changes: 2 additions & 2 deletions cvat-core/src/api-implementation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,8 +108,8 @@ export default function implementAPI(cvat: CVATCore): CVATCore {
implementationMixin(cvat.server.resetPassword, async (newPassword1, newPassword2, uid, token) => {
await serverProxy.server.resetPassword(newPassword1, newPassword2, uid, token);
});
implementationMixin(cvat.server.authorized, async () => {
const result = await serverProxy.server.authorized();
implementationMixin(cvat.server.authenticated, async () => {
const result = await serverProxy.server.authenticated();
return result;
});
implementationMixin(cvat.server.healthCheck, async (
Expand Down
4 changes: 2 additions & 2 deletions cvat-core/src/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,8 @@ function build(): CVATCore {
);
return result;
},
async authorized() {
const result = await PluginRegistry.apiWrapper(cvat.server.authorized);
async authenticated() {
const result = await PluginRegistry.apiWrapper(cvat.server.authenticated);
return result;
},
async healthCheck(maxRetries = 1, checkPeriod = 3000, requestTimeout = 5000, progressCallback = undefined) {
Expand Down
2 changes: 1 addition & 1 deletion cvat-core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ export default interface CVATCore {
changePassword: any;
requestPasswordReset: any;
resetPassword: any;
authorized: any;
authenticated: any;
healthCheck: any;
request: any;
setAuthData: any;
Expand Down
30 changes: 26 additions & 4 deletions cvat-core/src/lambda-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,36 @@
import serverProxy from './server-proxy';
import { ArgumentError } from './exceptions';
import MLModel from './ml-model';
import { RQStatus } from './enums';
import { RQStatus, ShapeType } from './enums';

export interface ModelProvider {
name: string;
icon: string;
attributes: Record<string, string>;
}

export interface InteractorResults {
mask: number[][];
points?: [number, number][];
bounds?: [number, number, number, number]
}

export interface DetectedShape {
type: ShapeType;
rotation?: number;
attributes: { name: string; value: string }[];
label: string;
outside?: boolean;
points?: number[];
mask?: number[];
elements: DetectedShape[];
}

export interface TrackerResults {
states: any[];
shapes: number[][];
}

class LambdaManager {
private cachedList: MLModel[];
private listening: Record<number, {
Expand Down Expand Up @@ -43,7 +65,7 @@ class LambdaManager {
return { models, count: lambdaFunctions.length };
}

async run(taskID: number, model: MLModel, args: any) {
async run(taskID: number, model: MLModel, args: any): Promise<string> {
if (!Number.isInteger(taskID) || taskID < 0) {
throw new ArgumentError(`Argument taskID must be a positive integer. Got "${taskID}"`);
}
Expand All @@ -68,7 +90,7 @@ class LambdaManager {
return result.id;
}

async call(taskID, model, args) {
async call(taskID, model, args): Promise<TrackerResults | InteractorResults | DetectedShape[]> {
if (!Number.isInteger(taskID) || taskID < 0) {
throw new ArgumentError(`Argument taskID must be a positive integer. Got "${taskID}"`);
}
Expand All @@ -81,7 +103,7 @@ class LambdaManager {
return result;
}

async requests() {
async requests(): Promise<any[]> {
const lambdaRequests = await serverProxy.lambda.requests();
return lambdaRequests
.filter((request) => [RQStatus.QUEUED, RQStatus.STARTED].includes(request.status));
Expand Down
4 changes: 2 additions & 2 deletions cvat-core/src/server-proxy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -557,7 +557,7 @@ async function getSelf(): Promise<SerializedUser> {
return response.data;
}

async function authorized(): Promise<boolean> {
async function authenticated(): Promise<boolean> {
try {
// In CVAT app we use two types of authentication
// At first we check if authentication token is present
Expand Down Expand Up @@ -2423,7 +2423,7 @@ export default Object.freeze({
changePassword,
requestPasswordReset,
resetPassword,
authorized,
authenticated,
healthCheck,
register,
request: serverRequest,
Expand Down
2 changes: 1 addition & 1 deletion cvat-sdk/gen/generate.sh
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ set -e

GENERATOR_VERSION="v6.0.1"

VERSION="2.12.0"
VERSION="2.12.1"
LIB_NAME="cvat_sdk"
LAYER1_LIB_NAME="${LIB_NAME}/api_client"
DST_DIR="$(cd "$(dirname -- "$0")/.." && pwd)"
Expand Down
4 changes: 2 additions & 2 deletions cvat-sdk/gen/templates/openapi-generator/api_doc.mustache
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,9 @@ The second value is the raw response, which can be useful to get response parame
status code, headers, or raw response data. Read more about invocation parameters
and returned values [here](https://docs.cvat.ai/docs/api_sdk/sdk/lowlevel-api/#sending-requests).

### Authorization
### Authentication

{{^authMethods}}No authorization required{{/authMethods}}{{#authMethods}}{{{name}}}{{^-last}}, {{/-last}}{{/authMethods}}
{{^authMethods}}No authentication required{{/authMethods}}{{#authMethods}}{{{name}}}{{^-last}}, {{/-last}}{{/authMethods}}

### HTTP request headers

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ class Configuration:

API Key Authentication Example.

You can authorize with API token after doing the basic auth the following way:
You can authenticate with API token after doing the basic auth the following way:

conf = {{{packageName}}}.Configuration(
...
Expand Down
2 changes: 1 addition & 1 deletion cvat-ui/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "cvat-ui",
"version": "1.63.6",
"version": "1.63.7",
"description": "CVAT single-page application",
"main": "src/index.tsx",
"scripts": {
Expand Down
24 changes: 12 additions & 12 deletions cvat-ui/src/actions/auth-actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ import { getCore, User } from 'cvat-core-wrapper';
const cvat = getCore();

export enum AuthActionTypes {
AUTHORIZED_REQUEST = 'AUTHORIZED_REQUEST',
AUTHORIZED_SUCCESS = 'AUTHORIZED_SUCCESS',
AUTHORIZED_FAILED = 'AUTHORIZED_FAILED',
AUTHENTICATED_REQUEST = 'AUTHENTICATED_REQUEST',
AUTHENTICATED_SUCCESS = 'AUTHENTICATED_SUCCESS',
AUTHENTICATED_FAILED = 'AUTHENTICATED_FAILED',
LOGIN = 'LOGIN',
LOGIN_SUCCESS = 'LOGIN_SUCCESS',
LOGIN_FAILED = 'LOGIN_FAILED',
Expand All @@ -35,9 +35,9 @@ export enum AuthActionTypes {
}

export const authActions = {
authorizeRequest: () => createAction(AuthActionTypes.AUTHORIZED_REQUEST),
authorizeSuccess: (user: User | null) => createAction(AuthActionTypes.AUTHORIZED_SUCCESS, { user }),
authorizeFailed: (error: any) => createAction(AuthActionTypes.AUTHORIZED_FAILED, { error }),
authenticatedRequest: () => createAction(AuthActionTypes.AUTHENTICATED_REQUEST),
authenticatedSuccess: (user: User | null) => createAction(AuthActionTypes.AUTHENTICATED_SUCCESS, { user }),
authenticatedFailed: (error: any) => createAction(AuthActionTypes.AUTHENTICATED_FAILED, { error }),
login: () => createAction(AuthActionTypes.LOGIN),
loginSuccess: (user: User) => createAction(AuthActionTypes.LOGIN_SUCCESS, { user }),
loginFailed: (error: any, hasEmailVerificationBeenSent = false) => (
Expand Down Expand Up @@ -120,18 +120,18 @@ export const logoutAsync = (): ThunkAction => async (dispatch) => {
}
};

export const authorizedAsync = (): ThunkAction => async (dispatch) => {
export const authenticatedAsync = (): ThunkAction => async (dispatch) => {
try {
dispatch(authActions.authorizeRequest());
const result = await cvat.server.authorized();
dispatch(authActions.authenticatedRequest());
const result = await cvat.server.authenticated();
if (result) {
const userInstance = (await cvat.users.get({ self: true }))[0];
dispatch(authActions.authorizeSuccess(userInstance));
dispatch(authActions.authenticatedSuccess(userInstance));
} else {
dispatch(authActions.authorizeSuccess(null));
dispatch(authActions.authenticatedSuccess(null));
}
} catch (error) {
dispatch(authActions.authorizeFailed(error));
dispatch(authActions.authenticatedFailed(error));
}
};

Expand Down
Loading

0 comments on commit 6990168

Please sign in to comment.