Exemplo n.º 1
0
def export_task(task_id, dst_format, server_url=None, save_images=False):
    try:
        db_task = Task.objects.get(pk=task_id)

        cache_dir = get_export_cache_dir(db_task)

        exporter = EXPORT_FORMATS[dst_format]
        output_base = '%s_%s' % ('dataset' if save_images else 'annotations',
                                 make_file_name(to_snake_case(dst_format)))
        output_path = '%s.%s' % (output_base, exporter.EXT)
        output_path = osp.join(cache_dir, output_path)

        task_time = timezone.localtime(db_task.updated_date).timestamp()
        if not (osp.exists(output_path) and \
                task_time <= osp.getmtime(output_path)):
            os.makedirs(cache_dir, exist_ok=True)
            with tempfile.TemporaryDirectory(dir=cache_dir) as temp_dir:
                temp_file = osp.join(temp_dir, 'result')
                task.export_task(task_id,
                                 temp_file,
                                 dst_format,
                                 server_url=server_url,
                                 save_images=save_images)
                os.replace(temp_file, output_path)

            archive_ctime = osp.getctime(output_path)
            scheduler = django_rq.get_scheduler()
            cleaning_job = scheduler.enqueue_in(time_delta=CACHE_TTL,
                                                func=clear_export_cache,
                                                task_id=task_id,
                                                file_path=output_path,
                                                file_ctime=archive_ctime)
            slogger.task[task_id].info(
                "The task '{}' is exported as '{}' at '{}' "
                "and available for downloading for the next {}. "
                "Export cache cleaning job is enqueued, id '{}'".format(
                    db_task.name, dst_format, output_path, CACHE_TTL,
                    cleaning_job.id))

        return output_path
    except Exception:
        log_exception(slogger.task[task_id])
        raise
Exemplo n.º 2
0
    def push(self, user, scheme, host, db_task, last_save):
        # Update local repository
        self._pull()

        os.makedirs(os.path.join(self._cwd,
                                 os.path.dirname(self._annotation_file)),
                    exist_ok=True)
        # Remove old annotation file if it exists
        if os.path.exists(self._annotation_file):
            os.remove(self._annotation_file)

        # Initialize LFS if need
        if self._lfs:
            updated = False
            lfs_settings = [
                "*.xml\tfilter=lfs diff=lfs merge=lfs -text\n",
                "*.zip\tfilter=lfs diff=lfs merge=lfs -text\n"
            ]
            if not os.path.isfile(os.path.join(self._cwd, ".gitattributes")):
                with open(os.path.join(self._cwd, ".gitattributes"),
                          "w") as gitattributes:
                    gitattributes.writelines(lfs_settings)
                    updated = True
            else:
                with open(os.path.join(self._cwd, ".gitattributes"),
                          "r+") as gitattributes:
                    lines = gitattributes.readlines()
                    for setting in lfs_settings:
                        if setting not in lines:
                            updated = True
                            lines.append(setting)
                    gitattributes.seek(0)
                    gitattributes.writelines(lines)
                    gitattributes.truncate()

            if updated:
                self._rep.git.add(['.gitattributes'])

        # Dump an annotation
        timestamp = datetime.datetime.now().strftime("%Y_%m_%d_%H_%M_%S")
        dump_name = os.path.join(
            db_task.get_task_dirname(),
            "git_annotation_{}_{}.zip".format(self._format, timestamp))

        export_task(
            task_id=self._tid,
            dst_file=dump_name,
            format_name=self._format,
            server_url=scheme + host,
            save_images=False,
        )

        ext = os.path.splitext(self._path)[1]
        if ext == '.zip':
            shutil.move(dump_name, self._annotation_file)
        elif ext == '.xml':
            with zipfile.ZipFile(dump_name) as archive:
                for f in archive.namelist():
                    if f.endswith('.xml'):
                        with open(self._annotation_file, 'wb') as output:
                            output.write(archive.read(f))
                        break
            os.remove(dump_name)
        else:
            raise Exception("Got unknown annotation file type")

        self._rep.git.add(self._annotation_file)

        # Merge diffs
        summary_diff = {"update": 0, "create": 0, "delete": 0}

        old_diffs_dir = os.path.join(os.path.dirname(self._diffs_dir),
                                     'repos_diffs')
        if (os.path.isdir(old_diffs_dir)):
            _read_old_diffs(old_diffs_dir, summary_diff)

        for diff_name in list(
                map(lambda x: os.path.join(self._diffs_dir, x),
                    os.listdir(self._diffs_dir))):
            with open(diff_name, 'r') as f:
                diff = json.loads(f.read())
                for key in diff:
                    summary_diff[key] += diff[key]

        message = "CVAT Annotation updated by {}. \n".format(
            self._user["name"])
        message += 'Task URL: {}://{}/dashboard?id={}\n'.format(
            scheme, host, db_task.id)
        if db_task.bug_tracker:
            message += 'Bug Tracker URL: {}\n'.format(db_task.bug_tracker)
        message += "Created: {}, updated: {}, deleted: {}\n".format(
            summary_diff["create"], summary_diff["update"],
            summary_diff["delete"])
        message += "Annotation time: {} hours\n".format(
            math.ceil((last_save - self._sync_date).total_seconds() / 3600))
        message += "Total annotation time: {} hours".format(
            math.ceil(
                (last_save - db_task.created_date).total_seconds() / 3600))

        self._rep.index.commit(message)
        self._rep.git.push("origin", self._branch_name, "--force")

        shutil.rmtree(old_diffs_dir, True)
        shutil.rmtree(self._diffs_dir, True)