Skip to content

Commit

Permalink
Merge pull request #8591 from cvat-ai/release-2.21.2
Browse files Browse the repository at this point in the history
Release v2.21.2
  • Loading branch information
cvat-bot[bot] authored Oct 24, 2024
2 parents 4a7e8e0 + 2f282d5 commit 5022eaa
Show file tree
Hide file tree
Showing 82 changed files with 999 additions and 688 deletions.
16 changes: 16 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,22 @@
"env": {},
"console": "internalConsole"
},
{
"name": "server: sync periodic jobs",
"type": "debugpy",
"request": "launch",
"justMyCode": false,
"stopOnEntry": false,
"python": "${command:python.interpreterPath}",
"program": "${workspaceFolder}/manage.py",
"args": [
"syncperiodicjobs"
],
"django": true,
"cwd": "${workspaceFolder}",
"env": {},
"console": "internalConsole"
},
{
"name": "server: tests",
"type": "debugpy",
Expand Down
34 changes: 34 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,40 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

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

<a id='changelog-2.21.2'></a>
## \[2.21.2\] - 2024-10-24

### Added

- Access to /analytics can now be granted
(<https://github.com/cvat-ai/cvat/pull/8509>)

### Fixed

- Expired sessions are now cleared from the database daily
(<https://github.com/cvat-ai/cvat/pull/8552>)

- Fixed export/import errors for tracks with duplicated shapes.
Fixed a bug which caused shape duplication on track import.
(<https://github.com/cvat-ai/cvat/pull/8553>)

- Fix Grafana container restart policy
(<https://github.com/cvat-ai/cvat/pull/8577>)

- Fixed some interface tooltips having 'undefined' shortcuts
(<https://github.com/cvat-ai/cvat/pull/8578>)

- Memory consumption during preparation of image chunks
(<https://github.com/cvat-ai/cvat/pull/8581>)

- Fixed a bug where an export RQ job being retried may break scheduling
of new jobs
(<https://github.com/cvat-ai/cvat/pull/8584>)

- UI now allows the user to start automatic annotation again
if the previous request fails
(<https://github.com/cvat-ai/cvat/pull/8587>)

<a id='changelog-2.21.1'></a>
## \[2.21.1\] - 2024-10-18

Expand Down
3 changes: 2 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ RUN apt-get update && \
supervisor \
tzdata \
unrar \
wait-for-it \
&& ln -fs /usr/share/zoneinfo/${TZ} /etc/localtime && \
dpkg-reconfigure -f noninteractive tzdata && \
rm -rf /var/lib/apt/lists/* && \
Expand Down Expand Up @@ -192,7 +193,7 @@ RUN python -m pip uninstall -y pip
COPY cvat/nginx.conf /etc/nginx/nginx.conf
COPY --chown=${USER} components /tmp/components
COPY --chown=${USER} supervisord/ ${HOME}/supervisord
COPY --chown=${USER} wait-for-it.sh manage.py backend_entrypoint.sh wait_for_deps.sh ${HOME}/
COPY --chown=${USER} manage.py backend_entrypoint.sh wait_for_deps.sh ${HOME}/
COPY --chown=${USER} utils/ ${HOME}/utils
COPY --chown=${USER} cvat/ ${HOME}/cvat
COPY --chown=${USER} rqscheduler.py ${HOME}
Expand Down
5 changes: 4 additions & 1 deletion backend_entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ fail() {
}

wait_for_db() {
~/wait-for-it.sh "${CVAT_POSTGRES_HOST}:${CVAT_POSTGRES_PORT:-5432}" -t 0
wait-for-it "${CVAT_POSTGRES_HOST}:${CVAT_POSTGRES_PORT:-5432}" -t 0
}

cmd_bash() {
Expand All @@ -18,6 +18,9 @@ cmd_bash() {
cmd_init() {
wait_for_db
~/manage.py migrate

wait-for-it "${CVAT_REDIS_INMEM_HOST}:${CVAT_REDIS_INMEM_PORT:-6379}" -t 0
~/manage.py syncperiodicjobs
}

cmd_run() {
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.21.1
cvat-sdk~=2.21.2
Pillow>=10.3.0
setuptools>=70.0.0 # 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.21.1"
VERSION = "2.21.2"
2 changes: 1 addition & 1 deletion cvat-core/src/annotations-collection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1295,7 +1295,7 @@ export default class Collection {
const predicate = sign > 0 ? (frame) => frame <= frameTo : (frame) => frame >= frameTo;
const update = sign > 0 ? (frame) => frame + 1 : (frame) => frame - 1;

// if not looking for an emty frame nor frame with annotations, return the next frame
// if not looking for an empty frame nor frame with annotations, return the next frame
// check if deleted frames are allowed additionally
if (!annotationsFilters) {
let frame = frameFrom;
Expand Down
5 changes: 3 additions & 2 deletions cvat-core/src/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import QualityReport from './quality-report';
import QualityConflict from './quality-conflict';
import QualitySettings from './quality-settings';
import AnalyticsReport from './analytics-report';
import ValidationLayout from './validation-layout';
import { JobValidationLayout, TaskValidationLayout } from './validation-layout';
import { Request } from './request';

import * as enums from './enums';
Expand Down Expand Up @@ -427,7 +427,8 @@ function build(): CVATCore {
QualityReport,
Request,
FramesMetaData,
ValidationLayout,
JobValidationLayout,
TaskValidationLayout,
},
utils: {
mask2Rle,
Expand Down
2 changes: 1 addition & 1 deletion cvat-core/src/cloud-storage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,7 @@ Object.defineProperties(CloudStorage.prototype.save, {
}
// update
if (typeof this.id !== 'undefined') {
// provider_type and recource should not change;
// provider_type and resource should not change;
// send to the server only the values that have changed
const initialData: SerializedCloudStorage = {};
if (this.displayName) {
Expand Down
4 changes: 2 additions & 2 deletions cvat-core/src/frames.ts
Original file line number Diff line number Diff line change
Expand Up @@ -683,7 +683,7 @@ export function getContextImage(jobID: number, frame: number): Promise<Record<st
// it might raise multiple server requests for context images
// if the promise was pending before and several requests came for the same frame
// all these requests will stuck on "finally"
// and when the promise fullfilled, it will run all the microtasks
// and when the promise is fulfilled, it will run all the microtasks
// since they all have the same request id, all they will perform in executor()
frameData.activeContextRequest.finally(() => setTimeout(checkAndExecute));
} else {
Expand Down Expand Up @@ -775,7 +775,7 @@ export async function getFrame(
// - getContextImage
// - getCachedChunks
// And from this idea we should call refreshJobCacheIfOutdated from each one
// Hovewer, following from the order, these methods are usually called
// However, following from the order, these methods are usually called
// it may lead to even more confusing behaviour
//
// Usually user first receives frame, then user receives ranges and finally user receives context images
Expand Down
5 changes: 3 additions & 2 deletions cvat-core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ import QualityConflict from './quality-conflict';
import QualitySettings from './quality-settings';
import AnalyticsReport from './analytics-report';
import AnnotationGuide from './guide';
import ValidationLayout from './validation-layout';
import { JobValidationLayout, TaskValidationLayout } from './validation-layout';
import { Request } from './request';
import BaseSingleFrameAction, { listActions, registerAction, runActions } from './annotations-actions';
import {
Expand Down Expand Up @@ -216,7 +216,8 @@ export default interface CVATCore {
AnalyticsReport: typeof AnalyticsReport;
Request: typeof Request;
FramesMetaData: typeof FramesMetaData;
ValidationLayout: typeof ValidationLayout;
JobValidationLayout: typeof JobValidationLayout;
TaskValidationLayout: typeof TaskValidationLayout;
};
utils: {
mask2Rle: typeof mask2Rle;
Expand Down
2 changes: 1 addition & 1 deletion cvat-core/src/object-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ export function findAngleDiff(rightAngle: number, leftAngle: number): number {
angleDiff = ((angleDiff + 180) % 360) - 180;
if (Math.abs(angleDiff) >= 180) {
// if the main arc is bigger than 180, go another arc
// to find it, just substract absolute value from 360 and inverse sign
// to find it, just subtract absolute value from 360 and inverse sign
angleDiff = 360 - Math.abs(angleDiff) * Math.sign(angleDiff) * -1;
}
return angleDiff;
Expand Down
2 changes: 1 addition & 1 deletion cvat-core/src/requests-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ class RequestsManager {
const promise = new Promise<Request>((resolve, reject) => {
const timeoutCallback = async (): Promise<void> => {
// We make sure that no more than REQUESTS_COUNT requests are sent simultaneously
// If thats the case, we re-schedule the timeout
// If that's the case, we re-schedule the timeout
const timestamp = Date.now();
if (this.requestStack.length >= REQUESTS_COUNT) {
const timestampToCheck = this.requestStack[this.requestStack.length - 1];
Expand Down
6 changes: 3 additions & 3 deletions cvat-core/src/server-proxy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import {
SerializedInvitationData, SerializedCloudStorage, SerializedFramesMetaData, SerializedCollection,
SerializedQualitySettingsData, APIQualitySettingsFilter, SerializedQualityConflictData, APIQualityConflictsFilter,
SerializedQualityReportData, APIQualityReportsFilter, SerializedAnalyticsReport, APIAnalyticsReportFilter,
SerializedRequest, SerializedValidationLayout,
SerializedRequest, SerializedJobValidationLayout, SerializedTaskValidationLayout,
} from './server-response-types';
import { PaginatedResource } from './core-types';
import { Request } from './request';
Expand Down Expand Up @@ -102,7 +102,7 @@ function fetchAll(url, filter = {}): Promise<any> {
}
});

// removing possible dublicates
// removing possible duplicates
const obj = result.results.reduce((acc: Record<string, any>, item: any) => {
acc[item.id] = item;
return acc;
Expand Down Expand Up @@ -1384,7 +1384,7 @@ async function deleteJob(jobID: number): Promise<void> {

const validationLayout = (instance: 'tasks' | 'jobs') => async (
id: number,
): Promise<SerializedValidationLayout | null> => {
): Promise<SerializedJobValidationLayout | SerializedTaskValidationLayout> => {
const { backendAPI } = config;

try {
Expand Down
9 changes: 8 additions & 1 deletion cvat-core/src/server-response-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ export interface SerializedUser {
last_login?: string;
date_joined?: string;
email_verification_required: boolean;
has_analytics_access: boolean;
}

interface SerializedStorage {
Expand Down Expand Up @@ -524,8 +525,14 @@ export interface SerializedRequest {
owner?: any;
}

export interface SerializedValidationLayout {
export interface SerializedJobValidationLayout {
honeypot_count?: number;
honeypot_frames?: number[];
honeypot_real_frames?: number[];
}

export interface SerializedTaskValidationLayout extends SerializedJobValidationLayout {
mode: 'gt' | 'gt_pool' | null;
validation_frames?: number[];
disabled_frames?: number[];
}
19 changes: 11 additions & 8 deletions cvat-core/src/session-implementation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,10 @@ import {
decodePreview,
} from './frames';
import Issue from './issue';
import { SerializedLabel, SerializedTask, SerializedValidationLayout } from './server-response-types';
import {
SerializedLabel, SerializedTask, SerializedJobValidationLayout,
SerializedTaskValidationLayout,
} from './server-response-types';
import { checkInEnum, checkObjectType } from './common';
import {
getCollection, getSaver, clearAnnotations, getAnnotations,
Expand All @@ -37,7 +40,7 @@ import AnnotationGuide from './guide';
import requestsManager from './requests-manager';
import { Request } from './request';
import User from './user';
import ValidationLayout from './validation-layout';
import { JobValidationLayout, TaskValidationLayout } from './validation-layout';

// must be called with task/job context
async function deleteFrameWrapper(jobID, frame): Promise<void> {
Expand Down Expand Up @@ -171,7 +174,7 @@ export function implementJob(Job: typeof JobClass): typeof JobClass {
): ReturnType<typeof JobClass.prototype.validationLayout> {
const result = await serverProxy.jobs.validationLayout(this.id);
if (Object.keys(result).length) {
return new ValidationLayout(result as Required<SerializedValidationLayout>);
return new JobValidationLayout(result as SerializedJobValidationLayout);
}

return null;
Expand Down Expand Up @@ -374,7 +377,7 @@ export function implementJob(Job: typeof JobClass): typeof JobClass {
}

if ('annotationsFilters' in searchParameters && 'generalFilters' in searchParameters) {
throw new ArgumentError('Both annotations filters and general fiters could not be used together');
throw new ArgumentError('Both annotations filters and general filters could not be used together');
}

if (!Number.isInteger(frameFrom) || !Number.isInteger(frameTo)) {
Expand Down Expand Up @@ -641,9 +644,9 @@ export function implementTask(Task: typeof TaskClass): typeof TaskClass {
value: async function validationLayoutImplementation(
this: TaskClass,
): ReturnType<typeof TaskClass.prototype.validationLayout> {
const result = await serverProxy.tasks.validationLayout(this.id);
if (Object.keys(result).length) {
return new ValidationLayout(result as Required<SerializedValidationLayout>);
const result = await serverProxy.tasks.validationLayout(this.id) as SerializedTaskValidationLayout;
if (result.mode !== null) {
return new TaskValidationLayout(result);
}

return null;
Expand Down Expand Up @@ -1043,7 +1046,7 @@ export function implementTask(Task: typeof TaskClass): typeof TaskClass {
}

if ('annotationsFilters' in searchParameters && 'generalFilters' in searchParameters) {
throw new ArgumentError('Both annotations filters and general fiters could not be used together');
throw new ArgumentError('Both annotations filters and general filters could not be used together');
}

if (!Number.isInteger(frameFrom) || !Number.isInteger(frameTo)) {
Expand Down
6 changes: 3 additions & 3 deletions cvat-core/src/session.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import { Request } from './request';
import logger from './logger';
import Issue from './issue';
import ObjectState from './object-state';
import ValidationLayout from './validation-layout';
import { JobValidationLayout, TaskValidationLayout } from './validation-layout';

function buildDuplicatedAPI(prototype) {
Object.defineProperties(prototype, {
Expand Down Expand Up @@ -686,7 +686,7 @@ export class Job extends Session {
return result;
}

async validationLayout(): Promise<ValidationLayout | null> {
async validationLayout(): Promise<JobValidationLayout | null> {
const result = await PluginRegistry.apiWrapper.call(this, Job.prototype.validationLayout);
return result;
}
Expand Down Expand Up @@ -1186,7 +1186,7 @@ export class Task extends Session {
return result;
}

async validationLayout(): Promise<ValidationLayout | null> {
async validationLayout(): Promise<TaskValidationLayout | null> {
const result = await PluginRegistry.apiWrapper.call(this, Task.prototype.validationLayout);
return result;
}
Expand Down
8 changes: 7 additions & 1 deletion cvat-core/src/user.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// Copyright (C) 2019-2022 Intel Corporation
// Copyright (C) 2022 CVAT.ai Corporation
// Copyright (C) 2022-2024 CVAT.ai Corporation
//
// SPDX-License-Identifier: MIT

Expand All @@ -18,6 +18,7 @@ export default class User {
public readonly isSuperuser: boolean;
public readonly isActive: boolean;
public readonly isVerified: boolean;
public readonly hasAnalyticsAccess: boolean;

constructor(initialData: SerializedUser) {
const data = {
Expand All @@ -33,6 +34,7 @@ export default class User {
is_superuser: null,
is_active: null,
email_verification_required: null,
has_analytics_access: null,
};

for (const property in data) {
Expand Down Expand Up @@ -80,6 +82,9 @@ export default class User {
isVerified: {
get: () => !data.email_verification_required,
},
hasAnalyticsAccess: {
get: () => data.has_analytics_access,
},
}),
);
}
Expand All @@ -98,6 +103,7 @@ export default class User {
is_superuser: this.isSuperuser,
is_active: this.isActive,
email_verification_required: this.isVerified,
has_analytics_access: this.hasAnalyticsAccess,
};
}
}
Loading

0 comments on commit 5022eaa

Please sign in to comment.