Skip to content

Commit

Permalink
Merge branch 'opencv:develop' into develop
Browse files Browse the repository at this point in the history
  • Loading branch information
tahamukhtar20 committed Mar 30, 2024
2 parents d62d37a + 02889ee commit 8f352a8
Show file tree
Hide file tree
Showing 29 changed files with 696 additions and 491 deletions.
66 changes: 66 additions & 0 deletions .github/workflows/docs.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
name: Docs
on:
push:
branches:
- 'master'
- 'develop'
pull_request:
types: [ready_for_review, opened, synchronize, reopened]

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
generate_github_pages:
permissions:
contents: write
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
submodules: recursive
fetch-depth: 0

- name: Generate CVAT SDK
run: |
pip3 install --user -r cvat-sdk/gen/requirements.txt
./cvat-sdk/gen/generate.sh
- name: Setup Hugo
run: |
wget https://github.com/gohugoio/hugo/releases/download/v0.110.0/hugo_extended_0.110.0_Linux-64bit.tar.gz
(mkdir hugo_extended_0.110.0_Linux-64bit && tar -xf hugo_extended_0.110.0_Linux-64bit.tar.gz -C hugo_extended_0.110.0_Linux-64bit)
wget https://github.com/gohugoio/hugo/releases/download/v0.83.0/hugo_extended_0.83.0_Linux-64bit.tar.gz
(mkdir hugo_extended_0.83.0_Linux-64bit && tar -xf hugo_extended_0.83.0_Linux-64bit.tar.gz -C hugo_extended_0.83.0_Linux-64bit)
mkdir hugo
cp hugo_extended_0.110.0_Linux-64bit/hugo hugo/hugo-0.110
cp hugo_extended_0.83.0_Linux-64bit/hugo hugo/hugo-0.83
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: '18.x'

- name: Install npm packages
working-directory: ./site
run: |
npm ci
- name: Build docs
run: |
pip install -r site/requirements.txt
python site/process_sdk_docs.py
PATH="$PWD/hugo:$PATH" python site/build_docs.py
env:
HUGO_ENV: production

- name: Deploy
if: github.ref == 'refs/heads/develop'
uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./public
force_orphan: true
55 changes: 1 addition & 54 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -385,62 +385,9 @@ jobs:
name: cypress_screenshots_${{ matrix.specs }}
path: ${{ github.workspace }}/tests/cypress/screenshots

generate_github_pages:
needs: [rest_api_testing, unit_testing, e2e_testing]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
submodules: recursive
fetch-depth: 0

- name: Download CVAT SDK
uses: actions/download-artifact@v3
with:
name: cvat_sdk
path: /tmp/cvat_sdk/

- name: Setup Hugo
run: |
wget https://github.com/gohugoio/hugo/releases/download/v0.110.0/hugo_extended_0.110.0_Linux-64bit.tar.gz
(mkdir hugo_extended_0.110.0_Linux-64bit && tar -xf hugo_extended_0.110.0_Linux-64bit.tar.gz -C hugo_extended_0.110.0_Linux-64bit)
wget https://github.com/gohugoio/hugo/releases/download/v0.83.0/hugo_extended_0.83.0_Linux-64bit.tar.gz
(mkdir hugo_extended_0.83.0_Linux-64bit && tar -xf hugo_extended_0.83.0_Linux-64bit.tar.gz -C hugo_extended_0.83.0_Linux-64bit)
mkdir hugo
cp hugo_extended_0.110.0_Linux-64bit/hugo hugo/hugo-0.110
cp hugo_extended_0.83.0_Linux-64bit/hugo hugo/hugo-0.83
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: '18.x'

- name: Install npm packages
working-directory: ./site
run: |
npm ci
- name: Build docs
run: |
pip install -r site/requirements.txt
python site/process_sdk_docs.py --input-dir /tmp/cvat_sdk/docs/ --site-root site/
PATH="$PWD/hugo:$PATH" python site/build_docs.py
env:
HUGO_ENV: production

- name: Deploy
if: github.ref == 'refs/heads/develop'
uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./public
force_orphan: true

publish_dev_images:
if: github.ref == 'refs/heads/develop'
needs: [rest_api_testing, unit_testing, e2e_testing, generate_github_pages]
needs: [rest_api_testing, unit_testing, e2e_testing]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
### Fixed

- Made quality report update job scheduling more efficient
(<https://github.com/opencv/cvat/pull/7596>)
5 changes: 5 additions & 0 deletions changelog.d/20240315_183623_avaicode.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
### Fixed

- Changed interpolation behavior in `annotation.py`, now correctly keep the last frame
- Insert last frame if it is key to the track, fixes data corruption when tracks crossing more than 1 jobs
(<https://github.com/opencv/cvat/pull/7615>)
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
### Fixed

- Sending `/events` request from logged-out user (<https://github.com/opencv/cvat/pull/7608>)
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.1",
"version": "15.0.2",
"type": "module",
"description": "Part of Computer Vision Tool which presents an interface for client-side integration",
"main": "src/api.ts",
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 @@ -160,7 +160,7 @@ export default interface CVATCore {
enabled: boolean;
onEmptyMaskOccurrence: () => void | null;
};
onOrganizationChange: typeof config.onOrganizationChange;
onOrganizationChange: (newOrgId: number | null) => void | null;
globalObjectsCounter: typeof config.globalObjectsCounter;
},
client: {
Expand Down
2 changes: 2 additions & 0 deletions cvat-core/src/logger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,8 @@ Object.defineProperties(Logger.prototype.save, {
// potentially new events may be generated during saving
// that is why we add this.collection
this.collection = [...collectionToSend, ...this.collection];

throw error;
} finally {
this.saving = false;
}
Expand Down
15 changes: 11 additions & 4 deletions cvat-ui/src/components/cvat-app.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// Copyright (C) 2020-2022 Intel Corporation
// Copyright (C) 2022-2023 CVAT.ai Corporation
// Copyright (C) 2022-2024 CVAT.ai Corporation
//
// SPDX-License-Identifier: MIT

Expand Down Expand Up @@ -71,7 +71,7 @@ import showPlatformNotification, {
} from 'utils/platform-checker';
import '../styles.scss';
import appConfig from 'config';
import EventRecorder from 'utils/controls-logger';
import EventRecorder from 'utils/event-recorder';
import { authQuery } from 'utils/auth-query';
import EmailConfirmationPage from './email-confirmation-pages/email-confirmed';
import EmailVerificationSentPage from './email-confirmation-pages/email-verification-sent';
Expand Down Expand Up @@ -149,7 +149,6 @@ class CVATApplication extends React.PureComponent<CVATAppProps & RouteComponentP
});

core.logger.configure(() => window.document.hasFocus, userActivityCallback);
EventRecorder.initSave();

core.config.onOrganizationChange = (newOrgId: number | null) => {
if (newOrgId === null) {
Expand Down Expand Up @@ -254,7 +253,7 @@ class CVATApplication extends React.PureComponent<CVATAppProps & RouteComponentP
}
}

public componentDidUpdate(): void {
public componentDidUpdate(prevProps: CVATAppProps): void {
const {
verifyAuthorized,
loadFormats,
Expand Down Expand Up @@ -302,6 +301,14 @@ class CVATApplication extends React.PureComponent<CVATAppProps & RouteComponentP
return;
}

if (user !== prevProps.user) {
if (user) {
EventRecorder.initSave();
} else {
EventRecorder.cancelSave();
}
}

if (!userAgreementsInitialized && !userAgreementsFetching) {
loadUserAgreements();
return;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (C) 2023 CVAT.ai Corporation
// Copyright (C) 2023-2024 CVAT.ai Corporation
//
// SPDX-License-Identifier: MIT

Expand All @@ -15,6 +15,7 @@ const parentClassFilter = ['ant-btn'];

class EventRecorder {
#savingTimeout: number | null;

public constructor() {
this.#savingTimeout = null;
core.logger.log(EventScope.loadTool, {
Expand Down Expand Up @@ -52,13 +53,29 @@ class EventRecorder {
public initSave(): void {
if (this.#savingTimeout) return;
this.#savingTimeout = window.setTimeout(() => {
core.logger.save().finally(() => {
const scheduleSave = (): void => {
this.#savingTimeout = null;
this.initSave();
});
};
core.logger.save()
.then(scheduleSave)
.catch((error) => {
if (error?.code === 401) {
this.cancelSave();
} else {
scheduleSave();
}
});
}, CONTROLS_LOGS_INTERVAL);
}

public cancelSave(): void {
if (this.#savingTimeout) {
window.clearTimeout(this.#savingTimeout);
this.#savingTimeout = null;
}
}

private filterClassName(cls: string): string {
if (typeof cls === 'string') {
return cls.split(' ').filter((_cls: string) => _cls.startsWith('cvat')).join(' ');
Expand Down
36 changes: 9 additions & 27 deletions cvat/apps/analytics_report/report/create.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
JobObjects,
)
from cvat.apps.engine.models import Job, Project, Task
from cvat.utils.background_jobs import schedule_job_with_throttling


def get_empty_report():
Expand Down Expand Up @@ -75,12 +76,6 @@ def _make_queue_job_id_base(self, obj) -> str:
def _make_custom_analytics_check_job_id(self) -> str:
return uuid4().hex

def _make_queue_job_id(self, obj, start_time: timezone.datetime) -> str:
return f"{self._make_queue_job_id_base(obj)}-{start_time.timestamp()}"

def _make_autoupdate_blocker_key(self, obj) -> str:
return f"cvat:analytics:autoupdate-blocker:{self._make_queue_job_id_base(obj)}"

@classmethod
def _get_last_report_time(cls, obj):
try:
Expand Down Expand Up @@ -121,27 +116,14 @@ def schedule_analytics_report_autoupdate_job(self, *, job=None, task=None, proje
target_obj = project
cvat_project_id = project.id

with django_rq.get_connection(settings.CVAT_QUEUES.ANALYTICS_REPORTS.value) as connection:
# The blocker key is used to avoid scheduling a report update job
# for every single change. The first time this method is called
# for a given object, we schedule the job and create a blocker
# that expires at the same time as the job is supposed to start.
# Until the blocker expires, we don't schedule any more jobs.
blocker_key = self._make_autoupdate_blocker_key(target_obj)
if connection.exists(blocker_key):
return

queue_job_id = self._make_queue_job_id(target_obj, next_job_time)

self._get_scheduler().enqueue_at(
next_job_time,
self._check_analytics_report,
cvat_task_id=cvat_task_id,
cvat_project_id=cvat_project_id,
job_id=queue_job_id,
)

connection.set(blocker_key, queue_job_id, exat=next_job_time)
schedule_job_with_throttling(
settings.CVAT_QUEUES.ANALYTICS_REPORTS.value,
self._make_queue_job_id_base(target_obj),
next_job_time,
self._check_analytics_report,
cvat_task_id=cvat_task_id,
cvat_project_id=cvat_project_id,
)

def schedule_analytics_check_job(self, *, job=None, task=None, project=None, user_id):
rq_id = self._make_custom_analytics_check_job_id()
Expand Down
4 changes: 2 additions & 2 deletions cvat/apps/analytics_report/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ def get_queryset(self):

@extend_schema(
operation_id="analytics_create_report",
summary="Creates a analytics report asynchronously and allows to check request status",
summary="Create an analytics report",
parameters=[
OpenApiParameter(
"rq_id",
Expand Down Expand Up @@ -144,7 +144,7 @@ def create(self, request, *args, **kwargs):
return Response(serializer.data, status=status.HTTP_201_CREATED)

@extend_schema(
summary="Method returns analytics report",
summary="Get an analytics report",
methods=["GET"],
operation_id="analytics_get_reports",
description="Receive analytics report",
Expand Down
7 changes: 5 additions & 2 deletions cvat/apps/dataset_manager/annotation.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,13 +107,16 @@ def filter_track_shapes(shapes):

if len(segment_shapes) < len(track['shapes']):
interpolated_shapes = TrackManager.get_interpolated_shapes(
track, start, stop, dimension)
track, start, stop + 1, dimension)
scoped_shapes = filter_track_shapes(interpolated_shapes)

if scoped_shapes:
last_key = sorted(track['shapes'], key=lambda s: s['frame'])[-1]['frame']
if not scoped_shapes[0]['keyframe']:
segment_shapes.insert(0, scoped_shapes[0])
if scoped_shapes[-1]['keyframe'] and \
if last_key >= stop and scoped_shapes[-1]['points'] != segment_shapes[-1]['points']:
segment_shapes.append(scoped_shapes[-1])
elif scoped_shapes[-1]['keyframe'] and \
scoped_shapes[-1]['outside']:
segment_shapes.append(scoped_shapes[-1])
elif stop + 1 < len(interpolated_shapes) and \
Expand Down
Loading

0 comments on commit 8f352a8

Please sign in to comment.