annofabcli 1.99.0__tar.gz → 100.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {annofabcli-1.99.0 → annofabcli-100.2}/PKG-INFO +1 -1
- annofabcli-100.2/annofabcli/__version__.py +1 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/annotation/change_annotation_attributes.py +2 -2
- annofabcli-100.2/annofabcli/annotation_specs/add_attribute_restriction.py +158 -0
- annofabcli-1.99.0/annofabcli/annotation_specs/list_attribute_restriction.py → annofabcli-100.2/annofabcli/annotation_specs/attribute_restriction.py +44 -154
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/annotation_specs/list_annotation_specs_attribute.py +51 -33
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/annotation_specs/list_annotation_specs_choice.py +42 -17
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/annotation_specs/list_annotation_specs_label.py +26 -93
- annofabcli-100.2/annofabcli/annotation_specs/list_annotation_specs_label_attribute.py +220 -0
- annofabcli-100.2/annofabcli/annotation_specs/list_attribute_restriction.py +149 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/annotation_specs/subcommand_annotation_specs.py +4 -0
- annofabcli-100.2/annofabcli/common/annofab/annotation_specs.py +25 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/common/download.py +1 -1
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/common/exceptions.py +2 -2
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/common/facade.py +2 -2
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/common/image.py +2 -2
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/input_data/delete_input_data.py +6 -7
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/job/delete_job.py +4 -4
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/organization_member/list_organization_member.py +2 -3
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/project_member/change_project_members.py +2 -3
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/project_member/drop_project_members.py +8 -8
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/project_member/invite_project_members.py +5 -6
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/project_member/list_users.py +4 -4
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/task/complete_tasks.py +2 -2
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/task/reject_tasks.py +76 -100
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/task/update_metadata_of_task.py +1 -1
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/task_history/list_task_history.py +1 -1
- {annofabcli-1.99.0 → annofabcli-100.2}/pyproject.toml +1 -1
- annofabcli-1.99.0/annofabcli/__version__.py +0 -1
- {annofabcli-1.99.0 → annofabcli-100.2}/LICENSE +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/README.md +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/__init__.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/__main__.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/annotation/__init__.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/annotation/annotation_query.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/annotation/change_annotation_properties.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/annotation/copy_annotation.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/annotation/delete_annotation.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/annotation/download_annotation_zip.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/annotation/dump_annotation.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/annotation/import_annotation.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/annotation/list_annotation.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/annotation/list_annotation_count.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/annotation/merge_segmentation.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/annotation/remove_segmentation_overlap.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/annotation/restore_annotation.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/annotation/subcommand_annotation.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/annotation_specs/__init__.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/annotation_specs/export_annotation_specs.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/annotation_specs/get_annotation_specs_with_attribute_id_replaced.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/annotation_specs/get_annotation_specs_with_choice_id_replaced.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/annotation_specs/get_annotation_specs_with_label_id_replaced.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/annotation_specs/list_annotation_specs_history.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/annotation_specs/list_label_color.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/annotation_specs/put_label_color.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/comment/__init__.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/comment/delete_comment.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/comment/download_comment_json.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/comment/list_all_comment.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/comment/list_comment.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/comment/put_comment.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/comment/put_comment_simply.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/comment/put_inspection_comment.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/comment/put_inspection_comment_simply.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/comment/put_onhold_comment.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/comment/put_onhold_comment_simply.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/comment/subcommand_comment.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/comment/utils.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/common/__init__.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/common/annofab/__init__.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/common/annofab/project.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/common/bokeh.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/common/cli.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/common/dataclasses.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/common/enums.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/common/pandas.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/common/type_util.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/common/typing.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/common/utils.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/common/visualize.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/data/logging.yaml +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/experimental/__init__.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/experimental/list_out_of_range_annotation_for_movie.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/experimental/subcommand_experimental.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/filesystem/__init__.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/filesystem/draw_annotation.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/filesystem/filter_annotation.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/filesystem/mask_user_info.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/filesystem/merge_annotation.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/filesystem/subcommand_filesystem.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/input_data/__init__.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/input_data/change_input_data_name.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/input_data/copy_input_data.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/input_data/delete_metadata_key_of_input_data.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/input_data/download_input_data_json.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/input_data/list_all_input_data.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/input_data/list_all_input_data_merged_task.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/input_data/list_input_data.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/input_data/put_input_data.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/input_data/put_input_data_with_zip.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/input_data/subcommand_input_data.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/input_data/update_metadata_of_input_data.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/input_data/utils.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/instruction/__init__.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/instruction/copy_instruction.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/instruction/download_instruction.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/instruction/list_instruction_history.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/instruction/subcommand_instruction.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/instruction/upload_instruction.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/job/__init__.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/job/list_job.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/job/list_last_job.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/job/subcommand_job.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/job/wait_job.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/my_account/__init__.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/my_account/get_my_account.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/my_account/subcommand_my_account.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/organization/__init__.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/organization/list_organization.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/organization/subcommand_organization.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/organization_member/__init__.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/organization_member/change_organization_member.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/organization_member/delete_organization_member.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/organization_member/invite_organization_member.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/organization_member/subcommand_organization_member.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/project/__init__.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/project/change_project_status.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/project/copy_project.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/project/diff_projects.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/project/list_project.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/project/put_project.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/project/subcommand_project.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/project_member/__init__.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/project_member/copy_project_members.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/project_member/put_project_members.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/project_member/subcommand_project_member.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/py.typed +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/stat_visualization/__init__.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/stat_visualization/mask_visualization_dir.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/stat_visualization/merge_visualization_dir.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/stat_visualization/subcommand_stat_visualization.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/stat_visualization/summarize_whole_performance_csv.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/stat_visualization/write_graph.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/stat_visualization/write_performance_rating_csv.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/statistics/__init__.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/statistics/histogram.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/statistics/linegraph.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/statistics/list_annotation_attribute.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/statistics/list_annotation_attribute_filled_count.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/statistics/list_annotation_count.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/statistics/list_annotation_duration.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/statistics/list_video_duration.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/statistics/list_worktime.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/statistics/scatter.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/statistics/subcommand_statistics.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/statistics/summarize_task_count.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/statistics/summarize_task_count_by_task_id_group.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/statistics/summarize_task_count_by_user.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/statistics/visualization/__init__.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/statistics/visualization/dataframe/__init__.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/statistics/visualization/dataframe/actual_worktime.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/statistics/visualization/dataframe/annotation_count.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/statistics/visualization/dataframe/cumulative_productivity.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/statistics/visualization/dataframe/custom_production_volume.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/statistics/visualization/dataframe/input_data_count.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/statistics/visualization/dataframe/inspection_comment_count.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/statistics/visualization/dataframe/productivity_per_date.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/statistics/visualization/dataframe/project_performance.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/statistics/visualization/dataframe/task.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/statistics/visualization/dataframe/task_history.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/statistics/visualization/dataframe/task_worktime_by_phase_user.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/statistics/visualization/dataframe/user.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/statistics/visualization/dataframe/user_performance.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/statistics/visualization/dataframe/whole_performance.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/statistics/visualization/dataframe/whole_productivity_per_date.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/statistics/visualization/dataframe/worktime_per_date.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/statistics/visualization/filtering_query.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/statistics/visualization/model.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/statistics/visualization/project_dir.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/statistics/visualization/visualization_source_files.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/statistics/visualize_annotation_count.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/statistics/visualize_annotation_duration.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/statistics/visualize_statistics.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/statistics/visualize_video_duration.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/supplementary/__init__.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/supplementary/delete_supplementary_data.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/supplementary/list_supplementary_data.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/supplementary/put_supplementary_data.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/supplementary/subcommand_supplementary.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/task/__init__.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/task/cancel_acceptance.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/task/change_operator.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/task/change_status_to_break.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/task/change_status_to_on_hold.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/task/copy_tasks.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/task/delete_metadata_key_of_task.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/task/delete_tasks.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/task/download_task_json.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/task/list_all_tasks.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/task/list_all_tasks_added_task_history.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/task/list_tasks.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/task/list_tasks_added_task_history.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/task/put_tasks.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/task/put_tasks_by_count.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/task/subcommand_task.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/task_history/__init__.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/task_history/download_task_history_json.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/task_history/list_all_task_history.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/task_history/subcommand_task_history.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/task_history_event/__init__.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/task_history_event/download_task_history_event_json.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/task_history_event/list_all_task_history_event.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/task_history_event/list_worktime.py +0 -0
- {annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/task_history_event/subcommand_task_history_event.py +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "100.2" # `poetry-dynamic-versioning`を使ってGitHubのバージョンタグを取得している。変更不要
|
{annofabcli-1.99.0 → annofabcli-100.2}/annofabcli/annotation/change_annotation_attributes.py
RENAMED
|
@@ -138,12 +138,12 @@ class ChangeAnnotationAttributesMain(CommandLineWithConfirm):
|
|
|
138
138
|
|
|
139
139
|
task: Task = Task.from_dict(dict_task)
|
|
140
140
|
if task.status == TaskStatus.WORKING:
|
|
141
|
-
logger.warning(f"task_id={task_id}: タスクが作業中状態のため、スキップします。")
|
|
141
|
+
logger.warning(f"task_id='{task_id}': タスクが作業中状態のため、スキップします。")
|
|
142
142
|
return False
|
|
143
143
|
|
|
144
144
|
if not self.is_force: # noqa: SIM102
|
|
145
145
|
if task.status == TaskStatus.COMPLETE:
|
|
146
|
-
logger.warning(f"task_id={task_id}: タスクが完了状態のため、スキップします。")
|
|
146
|
+
logger.warning(f"task_id='{task_id}': タスクが完了状態のため、スキップします。")
|
|
147
147
|
return False
|
|
148
148
|
|
|
149
149
|
annotation_list = self.get_annotation_list_for_task(task_id, annotation_query)
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import argparse
|
|
4
|
+
import copy
|
|
5
|
+
import json
|
|
6
|
+
import logging
|
|
7
|
+
import sys
|
|
8
|
+
from typing import Any, Optional
|
|
9
|
+
|
|
10
|
+
import annofabapi
|
|
11
|
+
|
|
12
|
+
import annofabcli
|
|
13
|
+
import annofabcli.common.cli
|
|
14
|
+
from annofabcli.annotation_specs.attribute_restriction import AttributeRestrictionMessage, OutputFormat
|
|
15
|
+
from annofabcli.common.cli import (
|
|
16
|
+
COMMAND_LINE_ERROR_STATUS_CODE,
|
|
17
|
+
CommandLine,
|
|
18
|
+
CommandLineWithConfirm,
|
|
19
|
+
build_annofabapi_resource_and_login,
|
|
20
|
+
get_json_from_args,
|
|
21
|
+
)
|
|
22
|
+
from annofabcli.common.facade import AnnofabApiFacade
|
|
23
|
+
|
|
24
|
+
logger = logging.getLogger(__name__)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def create_comment_from_restriction_text(restriction_text_list: list[str]) -> str:
|
|
28
|
+
"""
|
|
29
|
+
属性制約のテキストから、アノテーション仕様変更時のコメントを生成する
|
|
30
|
+
"""
|
|
31
|
+
return "以下の属性制約を追加しました。\n" + "\n".join(restriction_text_list)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class AddAttributeRestrictionMain(CommandLineWithConfirm):
|
|
35
|
+
def __init__(
|
|
36
|
+
self,
|
|
37
|
+
service: annofabapi.Resource,
|
|
38
|
+
*,
|
|
39
|
+
project_id: str,
|
|
40
|
+
all_yes: bool,
|
|
41
|
+
) -> None:
|
|
42
|
+
self.service = service
|
|
43
|
+
CommandLineWithConfirm.__init__(self, all_yes)
|
|
44
|
+
self.project_id = project_id
|
|
45
|
+
|
|
46
|
+
def add_restrictions(self, restrictions: list[dict[str, Any]], comment: Optional[str] = None) -> bool:
|
|
47
|
+
old_annotation_specs, _ = self.service.api.get_annotation_specs(self.project_id, query_params={"v": "3"})
|
|
48
|
+
old_restrictions = old_annotation_specs["restrictions"]
|
|
49
|
+
|
|
50
|
+
msg_obj = AttributeRestrictionMessage(
|
|
51
|
+
labels=old_annotation_specs["labels"],
|
|
52
|
+
additionals=old_annotation_specs["additionals"],
|
|
53
|
+
output_format=OutputFormat.TEXT,
|
|
54
|
+
raise_if_not_found=True,
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
new_restrictions = []
|
|
58
|
+
new_restriction_text_list = []
|
|
59
|
+
for index, restriction in enumerate(restrictions):
|
|
60
|
+
try:
|
|
61
|
+
restriction_text = msg_obj.get_restriction_text(restriction["additional_data_definition_id"], restriction["condition"])
|
|
62
|
+
except ValueError as e:
|
|
63
|
+
logger.warning(
|
|
64
|
+
f"{index + 1}件目 :: 次の属性制約は存在しないIDが含まれていたため、アノテーション仕様に追加しません。 :: "
|
|
65
|
+
f"restriction=`{restriction}`, error_message=`{e!s}`"
|
|
66
|
+
)
|
|
67
|
+
continue
|
|
68
|
+
|
|
69
|
+
if restriction in old_restrictions:
|
|
70
|
+
logger.warning(f"{index + 1}件目 :: 次の属性制約は既に存在するため、アノテーション仕様に追加しません。 :: `{restriction_text}`")
|
|
71
|
+
continue
|
|
72
|
+
|
|
73
|
+
if not self.confirm_processing(f"次の属性制約を追加しますか? :: `{restriction_text}`"):
|
|
74
|
+
continue
|
|
75
|
+
|
|
76
|
+
logger.debug(f"{index + 1}件目 :: 次の属性制約を追加します。 :: `{restriction_text}`")
|
|
77
|
+
new_restrictions.append(restriction)
|
|
78
|
+
new_restriction_text_list.append(restriction_text)
|
|
79
|
+
|
|
80
|
+
if len(new_restrictions) == 0:
|
|
81
|
+
logger.info("追加する属性制約はないため、アノテーション仕様を変更しません。")
|
|
82
|
+
return False
|
|
83
|
+
|
|
84
|
+
if not self.confirm_processing(f"{len(new_restrictions)} 件の属性制約を追加して、アノテーション仕様を変更します。よろしいですか? "):
|
|
85
|
+
return False
|
|
86
|
+
|
|
87
|
+
request_body = copy.deepcopy(old_annotation_specs)
|
|
88
|
+
request_body["restrictions"].extend(restrictions)
|
|
89
|
+
if comment is None:
|
|
90
|
+
comment = create_comment_from_restriction_text(new_restriction_text_list)
|
|
91
|
+
request_body["comment"] = comment
|
|
92
|
+
request_body["last_updated_datetime"] = old_annotation_specs["updated_datetime"]
|
|
93
|
+
self.service.api.put_annotation_specs(self.project_id, query_params={"v": "3"}, request_body=request_body)
|
|
94
|
+
logger.info(f"{len(new_restrictions)} 件の属性制約をアノテーション仕様に追加しました。")
|
|
95
|
+
return True
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
class AddAttributeRestriction(CommandLine):
|
|
99
|
+
COMMON_MESSAGE = "annofabcli annotation_specs add_restriction: error:"
|
|
100
|
+
|
|
101
|
+
def get_history_id_from_before_index(self, project_id: str, before: int) -> Optional[str]:
|
|
102
|
+
histories, _ = self.service.api.get_annotation_specs_histories(project_id)
|
|
103
|
+
if before + 1 > len(histories):
|
|
104
|
+
logger.warning(f"アノテーション仕様の履歴は{len(histories)}個のため、最新より{before}個前のアノテーション仕様は見つかりませんでした。")
|
|
105
|
+
return None
|
|
106
|
+
history = histories[-(before + 1)]
|
|
107
|
+
return history["history_id"]
|
|
108
|
+
|
|
109
|
+
def main(self) -> None:
|
|
110
|
+
args = self.args
|
|
111
|
+
|
|
112
|
+
restrictions = get_json_from_args(args.json)
|
|
113
|
+
if not isinstance(restrictions, list):
|
|
114
|
+
print(f"{self.COMMON_MESSAGE}: error: JSON形式が不正です。オブジェクトの配列を指定してください。", file=sys.stderr) # noqa: T201
|
|
115
|
+
sys.exit(COMMAND_LINE_ERROR_STATUS_CODE)
|
|
116
|
+
|
|
117
|
+
obj = AddAttributeRestrictionMain(self.service, project_id=args.project_id, all_yes=args.yes)
|
|
118
|
+
obj.add_restrictions(restrictions, comment=args.comment)
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
def parse_args(parser: argparse.ArgumentParser) -> None:
|
|
122
|
+
parser.add_argument("-p", "--project_id", help="対象のプロジェクトのproject_idを指定します。", required=True)
|
|
123
|
+
|
|
124
|
+
sample_json = [
|
|
125
|
+
{
|
|
126
|
+
"additional_data_definition_id": "a1",
|
|
127
|
+
"condition": {"value": "true", "_type": "Equals"},
|
|
128
|
+
}
|
|
129
|
+
]
|
|
130
|
+
parser.add_argument(
|
|
131
|
+
"--json",
|
|
132
|
+
type=str,
|
|
133
|
+
required=True,
|
|
134
|
+
help="追加する属性の制約情報のJSONを指定します。"
|
|
135
|
+
"JSON形式は ... を参照してください。\n"
|
|
136
|
+
f"(例) ``{json.dumps(sample_json)}``\n"
|
|
137
|
+
"``file://`` を先頭に付けるとjsonファイルを指定できます。",
|
|
138
|
+
)
|
|
139
|
+
|
|
140
|
+
parser.add_argument("--comment", type=str, help="アノテーション仕様の変更時に指定できるコメント。未指定の場合、自動でコメントが生成されます。")
|
|
141
|
+
|
|
142
|
+
parser.set_defaults(subcommand_func=main)
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
def main(args: argparse.Namespace) -> None:
|
|
146
|
+
service = build_annofabapi_resource_and_login(args)
|
|
147
|
+
facade = AnnofabApiFacade(service)
|
|
148
|
+
AddAttributeRestriction(service, facade, args).main()
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
def add_parser(subparsers: Optional[argparse._SubParsersAction] = None) -> argparse.ArgumentParser:
|
|
152
|
+
subcommand_name = "add_attribute_restriction"
|
|
153
|
+
|
|
154
|
+
subcommand_help = "アノテーション仕様に属性の制約を追加します。"
|
|
155
|
+
description = subcommand_help + "アノテーション仕様画面では設定できない「属性間の制約」を追加するときに有用です。"
|
|
156
|
+
parser = annofabcli.common.cli.add_parser(subparsers, subcommand_name, subcommand_help, description=description)
|
|
157
|
+
parse_args(parser)
|
|
158
|
+
return parser
|
|
@@ -1,31 +1,16 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
import argparse
|
|
4
|
-
import json
|
|
5
1
|
import logging
|
|
6
|
-
import sys
|
|
7
2
|
from collections.abc import Collection
|
|
8
3
|
from enum import Enum
|
|
9
|
-
from pathlib import Path
|
|
10
4
|
from typing import Any, Optional
|
|
11
5
|
|
|
12
6
|
from more_itertools import first_true
|
|
13
7
|
|
|
14
|
-
import annofabcli
|
|
15
|
-
import annofabcli.common.cli
|
|
16
|
-
from annofabcli.common.cli import (
|
|
17
|
-
COMMAND_LINE_ERROR_STATUS_CODE,
|
|
18
|
-
ArgumentParser,
|
|
19
|
-
CommandLine,
|
|
20
|
-
build_annofabapi_resource_and_login,
|
|
21
|
-
get_list_from_args,
|
|
22
|
-
)
|
|
23
8
|
from annofabcli.common.facade import AnnofabApiFacade
|
|
24
9
|
|
|
25
10
|
logger = logging.getLogger(__name__)
|
|
26
11
|
|
|
27
12
|
|
|
28
|
-
class
|
|
13
|
+
class OutputFormat(Enum):
|
|
29
14
|
"""
|
|
30
15
|
表示するフォーマット ``--format`` で指定できる値
|
|
31
16
|
|
|
@@ -38,13 +23,17 @@ class FormatArgument(Enum):
|
|
|
38
23
|
DETAILED_TEXT = "detailed_text"
|
|
39
24
|
|
|
40
25
|
|
|
41
|
-
class
|
|
26
|
+
class AttributeRestrictionMessage:
|
|
42
27
|
"""
|
|
43
|
-
|
|
28
|
+
アノテーション仕様の属性制約情報から、自然言語で書かれたメッセージを生成する
|
|
44
29
|
|
|
45
30
|
Args:
|
|
46
31
|
labels: アノテーション仕様のラベル情報
|
|
47
32
|
additionals: アノテーション仕様の属性情報
|
|
33
|
+
raise_if_not_found: 属性やラベルが見つからなかった場合に例外を発生させるかどうか
|
|
34
|
+
format: 属性制約の表示フォーマット
|
|
35
|
+
- `text`: 属性IDを隠したシンプルなテキスト
|
|
36
|
+
- `detailed_text`: 属性IDなどの詳細情報を表示したテキスト
|
|
48
37
|
|
|
49
38
|
"""
|
|
50
39
|
|
|
@@ -52,20 +41,29 @@ class ListAttributeRestrictionMain:
|
|
|
52
41
|
self,
|
|
53
42
|
labels: list[dict[str, Any]],
|
|
54
43
|
additionals: list[dict[str, Any]],
|
|
55
|
-
|
|
44
|
+
*,
|
|
45
|
+
raise_if_not_found: bool = False,
|
|
46
|
+
output_format: OutputFormat = OutputFormat.DETAILED_TEXT, # pylint: disable=redefined-builtin
|
|
56
47
|
) -> None:
|
|
57
48
|
self.attribute_dict = {e["additional_data_definition_id"]: e for e in additionals}
|
|
58
49
|
self.label_dict = {e["label_id"]: e for e in labels}
|
|
59
|
-
self.
|
|
50
|
+
self.output_format = output_format
|
|
51
|
+
self.raise_if_not_found = raise_if_not_found
|
|
60
52
|
|
|
61
53
|
def get_labels_text(self, label_ids: Collection[str]) -> str:
|
|
62
54
|
label_message_list = []
|
|
63
55
|
for label_id in label_ids:
|
|
64
56
|
label = self.label_dict.get(label_id)
|
|
65
|
-
|
|
57
|
+
if label is not None:
|
|
58
|
+
label_name = AnnofabApiFacade.get_label_name_en(label)
|
|
59
|
+
else:
|
|
60
|
+
logger.warning(f"ラベルIDが'{label_id}'であるラベルは存在しません。")
|
|
61
|
+
if self.raise_if_not_found:
|
|
62
|
+
raise ValueError(f"ラベルIDが'{label_id}'であるラベルは存在しません。")
|
|
63
|
+
label_name = ""
|
|
66
64
|
|
|
67
65
|
label_message = f"'{label_name}'"
|
|
68
|
-
if self.
|
|
66
|
+
if self.output_format == OutputFormat.DETAILED_TEXT:
|
|
69
67
|
label_message = f"{label_message} (id='{label_id}')"
|
|
70
68
|
label_message_list.append(label_message)
|
|
71
69
|
|
|
@@ -89,11 +87,19 @@ class ListAttributeRestrictionMain:
|
|
|
89
87
|
if choice is not None:
|
|
90
88
|
choice_name = AnnofabApiFacade.get_choice_name_en(choice)
|
|
91
89
|
tmp = f"'{value}'"
|
|
92
|
-
if self.
|
|
90
|
+
if self.output_format == OutputFormat.DETAILED_TEXT:
|
|
93
91
|
tmp = f"{tmp} (name='{choice_name}')"
|
|
94
92
|
return tmp
|
|
95
93
|
|
|
96
94
|
else:
|
|
95
|
+
message = (
|
|
96
|
+
f"選択肢IDが'{value}'である選択肢は存在しません。 :: "
|
|
97
|
+
f"属性名='{AnnofabApiFacade.get_additional_data_definition_name_en(attribute)}', "
|
|
98
|
+
f"属性ID='{attribute['additional_data_definition_id']}'"
|
|
99
|
+
)
|
|
100
|
+
logger.warning(message)
|
|
101
|
+
if self.raise_if_not_found:
|
|
102
|
+
raise ValueError(message)
|
|
97
103
|
return f"'{value}'"
|
|
98
104
|
else:
|
|
99
105
|
return f"'{value}'"
|
|
@@ -120,12 +126,15 @@ class ListAttributeRestrictionMain:
|
|
|
120
126
|
attribute = self.attribute_dict.get(attribute_id)
|
|
121
127
|
if attribute is not None:
|
|
122
128
|
subject = f"'{AnnofabApiFacade.get_additional_data_definition_name_en(attribute)}'"
|
|
123
|
-
if self.
|
|
129
|
+
if self.output_format == OutputFormat.DETAILED_TEXT:
|
|
124
130
|
subject = f"{subject} (id='{attribute_id}', type='{attribute['type']}')"
|
|
125
131
|
else:
|
|
126
|
-
logger.warning(f"属性IDが'{attribute_id}'
|
|
132
|
+
logger.warning(f"属性IDが'{attribute_id}'である属性は存在しません。")
|
|
133
|
+
if self.raise_if_not_found:
|
|
134
|
+
raise ValueError(f"属性IDが'{attribute_id}'である属性は存在しません。")
|
|
135
|
+
|
|
127
136
|
subject = "''"
|
|
128
|
-
if self.
|
|
137
|
+
if self.output_format == OutputFormat.DETAILED_TEXT:
|
|
129
138
|
subject = f"{subject} (id='{attribute_id}')"
|
|
130
139
|
|
|
131
140
|
if str_type == "CanInput":
|
|
@@ -152,7 +161,7 @@ class ListAttributeRestrictionMain:
|
|
|
152
161
|
verb = "DOES NOT MATCH"
|
|
153
162
|
str_object = f"'{condition['value']}'"
|
|
154
163
|
else:
|
|
155
|
-
raise
|
|
164
|
+
raise ValueError(f"condition._type='{str_type}'はサポートしていません。")
|
|
156
165
|
|
|
157
166
|
tmp = f"{subject} {verb}"
|
|
158
167
|
if str_object != "":
|
|
@@ -212,6 +221,14 @@ class ListAttributeRestrictionMain:
|
|
|
212
221
|
target_attribute_names: Optional[Collection[str]] = None,
|
|
213
222
|
target_label_names: Optional[Collection[str]] = None,
|
|
214
223
|
) -> list[str]:
|
|
224
|
+
"""
|
|
225
|
+
複数の属性制約から自然言語で記載されたメッセージのlistを返します。
|
|
226
|
+
|
|
227
|
+
Args:
|
|
228
|
+
restrictions: 属性制約のリスト
|
|
229
|
+
target_attribute_names: 取得対象のラベル名(英語)のlist
|
|
230
|
+
target_label_names: 取得対象の属性名(英語)のlist
|
|
231
|
+
"""
|
|
215
232
|
if target_attribute_names is not None or target_label_names is not None:
|
|
216
233
|
target_attribute_ids = self.get_target_attribute_ids(target_attribute_names=target_attribute_names, target_label_names=target_label_names)
|
|
217
234
|
return [
|
|
@@ -221,130 +238,3 @@ class ListAttributeRestrictionMain:
|
|
|
221
238
|
]
|
|
222
239
|
else:
|
|
223
240
|
return [self.get_restriction_text(e["additional_data_definition_id"], e["condition"]) for e in restrictions]
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
class ListAttributeRestriction(CommandLine):
|
|
227
|
-
COMMON_MESSAGE = "annofabcli annotation_specs list_restriction: error:"
|
|
228
|
-
|
|
229
|
-
def get_history_id_from_before_index(self, project_id: str, before: int) -> Optional[str]:
|
|
230
|
-
histories, _ = self.service.api.get_annotation_specs_histories(project_id)
|
|
231
|
-
if before + 1 > len(histories):
|
|
232
|
-
logger.warning(f"アノテーション仕様の履歴は{len(histories)}個のため、最新より{before}個前のアノテーション仕様は見つかりませんでした。")
|
|
233
|
-
return None
|
|
234
|
-
history = histories[-(before + 1)]
|
|
235
|
-
return history["history_id"]
|
|
236
|
-
|
|
237
|
-
def main(self) -> None:
|
|
238
|
-
args = self.args
|
|
239
|
-
|
|
240
|
-
if args.project_id is not None:
|
|
241
|
-
history_id = None
|
|
242
|
-
if args.history_id is not None:
|
|
243
|
-
history_id = args.history_id
|
|
244
|
-
|
|
245
|
-
if args.before is not None:
|
|
246
|
-
history_id = self.get_history_id_from_before_index(args.project_id, args.before)
|
|
247
|
-
if history_id is None:
|
|
248
|
-
print( # noqa: T201
|
|
249
|
-
f"{self.COMMON_MESSAGE} argument --before: 最新より{args.before}個前のアノテーション仕様は見つかりませんでした。",
|
|
250
|
-
file=sys.stderr,
|
|
251
|
-
)
|
|
252
|
-
sys.exit(COMMAND_LINE_ERROR_STATUS_CODE)
|
|
253
|
-
|
|
254
|
-
query_params = {"v": "3"}
|
|
255
|
-
if history_id is not None:
|
|
256
|
-
query_params["history_id"] = history_id
|
|
257
|
-
|
|
258
|
-
annotation_specs, _ = self.service.api.get_annotation_specs(args.project_id, query_params=query_params)
|
|
259
|
-
elif args.annotation_json_path is not None:
|
|
260
|
-
with args.annotation_json_path.open() as f:
|
|
261
|
-
annotation_specs = json.load(f)
|
|
262
|
-
|
|
263
|
-
else:
|
|
264
|
-
raise RuntimeError("'--project_id'か'--annotation_specs_json'のどちらかを指定する必要があります。")
|
|
265
|
-
|
|
266
|
-
main_obj = ListAttributeRestrictionMain(
|
|
267
|
-
labels=annotation_specs["labels"],
|
|
268
|
-
additionals=annotation_specs["additionals"],
|
|
269
|
-
format=FormatArgument(args.format),
|
|
270
|
-
)
|
|
271
|
-
target_attribute_names = get_list_from_args(args.attribute_name) if args.attribute_name is not None else None
|
|
272
|
-
target_label_names = get_list_from_args(args.label_name) if args.label_name is not None else None
|
|
273
|
-
restriction_text_list = main_obj.get_restriction_text_list(
|
|
274
|
-
annotation_specs["restrictions"],
|
|
275
|
-
target_attribute_names=target_attribute_names,
|
|
276
|
-
target_label_names=target_label_names,
|
|
277
|
-
)
|
|
278
|
-
|
|
279
|
-
annofabcli.common.utils.output_string("\n".join(restriction_text_list), args.output)
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
def parse_args(parser: argparse.ArgumentParser) -> None:
|
|
283
|
-
argument_parser = ArgumentParser(parser)
|
|
284
|
-
|
|
285
|
-
required_group = parser.add_mutually_exclusive_group(required=True)
|
|
286
|
-
required_group.add_argument(
|
|
287
|
-
"-p", "--project_id", help="対象のプロジェクトのproject_idを指定します。APIで取得したアノテーション仕様情報を元に出力します。"
|
|
288
|
-
)
|
|
289
|
-
required_group.add_argument(
|
|
290
|
-
"--annotation_specs_json",
|
|
291
|
-
type=Path,
|
|
292
|
-
help="指定したアノテーション仕様のJSONファイルを指定します。"
|
|
293
|
-
"JSONファイルに記載された情報を元に出力します。ただしアノテーション仕様の ``format_version`` は ``3`` である必要があります。",
|
|
294
|
-
)
|
|
295
|
-
|
|
296
|
-
# 過去のアノテーション仕様を参照するためのオプション
|
|
297
|
-
old_annotation_specs_group = parser.add_mutually_exclusive_group()
|
|
298
|
-
old_annotation_specs_group.add_argument(
|
|
299
|
-
"--history_id",
|
|
300
|
-
type=str,
|
|
301
|
-
help=(
|
|
302
|
-
"出力したいアノテーション仕様のhistory_idを指定してください。 "
|
|
303
|
-
"history_idは ``annotation_specs list_history`` コマンドで確認できます。 "
|
|
304
|
-
"指定しない場合は、最新のアノテーション仕様が出力されます。 "
|
|
305
|
-
),
|
|
306
|
-
)
|
|
307
|
-
|
|
308
|
-
old_annotation_specs_group.add_argument(
|
|
309
|
-
"--before",
|
|
310
|
-
type=int,
|
|
311
|
-
help=(
|
|
312
|
-
"出力したい過去のアノテーション仕様が、最新よりいくつ前のアノテーション仕様であるかを指定してください。 "
|
|
313
|
-
"たとえば ``1`` を指定した場合、最新より1個前のアノテーション仕様を出力します。 "
|
|
314
|
-
"指定しない場合は、最新のアノテーション仕様が出力されます。 "
|
|
315
|
-
),
|
|
316
|
-
)
|
|
317
|
-
|
|
318
|
-
parser.add_argument("--attribute_name", type=str, nargs="+", help="指定した属性名(英語)の属性の制約を出力します。")
|
|
319
|
-
parser.add_argument("--label_name", type=str, nargs="+", help="指定したラベル名(英語)のラベルに紐づく属性の制約を出力します。")
|
|
320
|
-
argument_parser.add_output()
|
|
321
|
-
|
|
322
|
-
parser.add_argument(
|
|
323
|
-
"-f",
|
|
324
|
-
"--format",
|
|
325
|
-
type=str,
|
|
326
|
-
choices=[e.value for e in FormatArgument],
|
|
327
|
-
default=FormatArgument.TEXT.value,
|
|
328
|
-
help=f"出力フォーマット\n"
|
|
329
|
-
"\n"
|
|
330
|
-
f"* {FormatArgument.TEXT.value}: 英語名のみ出力する形式\n"
|
|
331
|
-
f"* {FormatArgument.DETAILED_TEXT.value}: 属性IDや属性種類などの詳細情報を出力する形式\n",
|
|
332
|
-
)
|
|
333
|
-
|
|
334
|
-
parser.set_defaults(subcommand_func=main)
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
def main(args: argparse.Namespace) -> None:
|
|
338
|
-
service = build_annofabapi_resource_and_login(args)
|
|
339
|
-
facade = AnnofabApiFacade(service)
|
|
340
|
-
ListAttributeRestriction(service, facade, args).main()
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
def add_parser(subparsers: Optional[argparse._SubParsersAction] = None) -> argparse.ArgumentParser:
|
|
344
|
-
subcommand_name = "list_attribute_restriction"
|
|
345
|
-
|
|
346
|
-
subcommand_help = "アノテーション仕様の属性の制約情報を出力します。"
|
|
347
|
-
|
|
348
|
-
parser = annofabcli.common.cli.add_parser(subparsers, subcommand_name, subcommand_help)
|
|
349
|
-
parse_args(parser)
|
|
350
|
-
return parser
|
|
@@ -16,6 +16,7 @@ from dataclasses_json import DataClassJsonMixin
|
|
|
16
16
|
|
|
17
17
|
import annofabcli
|
|
18
18
|
import annofabcli.common.cli
|
|
19
|
+
from annofabcli.common.annofab.annotation_specs import keybind_to_text
|
|
19
20
|
from annofabcli.common.cli import (
|
|
20
21
|
COMMAND_LINE_ERROR_STATUS_CODE,
|
|
21
22
|
ArgumentParser,
|
|
@@ -24,15 +25,16 @@ from annofabcli.common.cli import (
|
|
|
24
25
|
)
|
|
25
26
|
from annofabcli.common.enums import FormatArgument
|
|
26
27
|
from annofabcli.common.facade import AnnofabApiFacade
|
|
27
|
-
from annofabcli.common.utils import print_csv
|
|
28
|
+
from annofabcli.common.utils import print_according_to_format, print_csv
|
|
28
29
|
|
|
29
30
|
logger = logging.getLogger(__name__)
|
|
30
31
|
|
|
31
32
|
|
|
32
33
|
@dataclass
|
|
33
|
-
class
|
|
34
|
+
class FlattenAttribute(DataClassJsonMixin):
|
|
34
35
|
"""
|
|
35
|
-
|
|
36
|
+
ネストされていないフラットな属性情報を格納するクラスです。
|
|
37
|
+
選択肢の一覧などは格納できません。
|
|
36
38
|
"""
|
|
37
39
|
|
|
38
40
|
attribute_id: str
|
|
@@ -45,7 +47,7 @@ class AttributeForCsv(DataClassJsonMixin):
|
|
|
45
47
|
attribute_name_en: Optional[str]
|
|
46
48
|
attribute_name_ja: Optional[str]
|
|
47
49
|
attribute_name_vi: Optional[str]
|
|
48
|
-
|
|
50
|
+
attribute_type: str
|
|
49
51
|
"""属性の種類"""
|
|
50
52
|
default: Optional[Union[str, bool, int]]
|
|
51
53
|
"""デフォルト値"""
|
|
@@ -60,6 +62,7 @@ class AttributeForCsv(DataClassJsonMixin):
|
|
|
60
62
|
"""制約の個数"""
|
|
61
63
|
reference_label_count: int
|
|
62
64
|
"""参照されているラベルの個数"""
|
|
65
|
+
keybind: Optional[str]
|
|
63
66
|
|
|
64
67
|
|
|
65
68
|
def create_relationship_between_attribute_and_label(labels_v3: list[dict[str, Any]]) -> dict[str, set[str]]:
|
|
@@ -78,11 +81,11 @@ def create_relationship_between_attribute_and_label(labels_v3: list[dict[str, An
|
|
|
78
81
|
return result
|
|
79
82
|
|
|
80
83
|
|
|
81
|
-
def
|
|
84
|
+
def create_flatten_attribute_list_from_additionals(
|
|
82
85
|
additionals_v3: list[dict[str, Any]], labels_v3: list[dict[str, Any]], restrictions: list[dict[str, Any]]
|
|
83
|
-
) ->
|
|
86
|
+
) -> list[FlattenAttribute]:
|
|
84
87
|
"""
|
|
85
|
-
APIから取得した属性情報(v3
|
|
88
|
+
APIから取得した属性情報(v3版)から、属性情報の一覧を生成します。
|
|
86
89
|
|
|
87
90
|
Args:
|
|
88
91
|
additionals_v3: APIから取得した属性情報(v3版)
|
|
@@ -98,52 +101,60 @@ def create_df_from_additionals(
|
|
|
98
101
|
# keyが属性ID、valueが属性に紐づくラベルのIDのsetであるdict
|
|
99
102
|
dict_label_ids = create_relationship_between_attribute_and_label(labels_v3)
|
|
100
103
|
|
|
101
|
-
def dict_additional_to_dataclass(additional: dict[str, Any]) ->
|
|
104
|
+
def dict_additional_to_dataclass(additional: dict[str, Any]) -> FlattenAttribute:
|
|
102
105
|
"""
|
|
103
106
|
辞書の属性情報をDataClassのラベル情報に変換します。
|
|
104
107
|
"""
|
|
105
108
|
attribute_id = additional["additional_data_definition_id"]
|
|
106
109
|
additional_name = additional["name"]
|
|
107
|
-
return
|
|
110
|
+
return FlattenAttribute(
|
|
108
111
|
attribute_id=attribute_id,
|
|
109
112
|
attribute_name_en=get_message_with_lang(additional_name, lang=Lang.EN_US),
|
|
110
113
|
attribute_name_ja=get_message_with_lang(additional_name, lang=Lang.JA_JP),
|
|
111
114
|
attribute_name_vi=get_message_with_lang(additional_name, lang=Lang.VI_VN),
|
|
112
|
-
|
|
115
|
+
attribute_type=additional["type"],
|
|
113
116
|
default=additional["default"],
|
|
114
117
|
read_only=additional["read_only"],
|
|
115
118
|
choice_count=len(additional["choices"]),
|
|
116
119
|
restriction_count=dict_restriction_count[attribute_id],
|
|
117
120
|
reference_label_count=len(dict_label_ids[attribute_id]),
|
|
121
|
+
keybind=keybind_to_text(additional["keybind"]),
|
|
118
122
|
)
|
|
119
123
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
columns = [
|
|
123
|
-
"attribute_id",
|
|
124
|
-
"attribute_name_en",
|
|
125
|
-
"attribute_name_ja",
|
|
126
|
-
"attribute_name_vi",
|
|
127
|
-
"type",
|
|
128
|
-
"default",
|
|
129
|
-
"read_only",
|
|
130
|
-
"choice_count",
|
|
131
|
-
"restriction_count",
|
|
132
|
-
"reference_label_count",
|
|
133
|
-
]
|
|
134
|
-
|
|
135
|
-
df = pandas.DataFrame(new_labels, columns=columns)
|
|
136
|
-
return df
|
|
124
|
+
return [dict_additional_to_dataclass(e) for e in additionals_v3]
|
|
137
125
|
|
|
138
126
|
|
|
139
127
|
class PrintAnnotationSpecsAttribute(CommandLine):
|
|
140
128
|
COMMON_MESSAGE = "annofabcli annotation_specs list_attribute: error:"
|
|
141
129
|
|
|
142
|
-
def print_annotation_specs_attribute(
|
|
143
|
-
|
|
144
|
-
|
|
130
|
+
def print_annotation_specs_attribute(
|
|
131
|
+
self, annotation_specs_v3: dict[str, Any], output_format: FormatArgument, output: Optional[str] = None
|
|
132
|
+
) -> None:
|
|
133
|
+
attribute_list = create_flatten_attribute_list_from_additionals(
|
|
134
|
+
annotation_specs_v3["additionals"], annotation_specs_v3["labels"], annotation_specs_v3["restrictions"]
|
|
135
|
+
)
|
|
136
|
+
logger.info(f"{len(attribute_list)} 件の属性情報を出力します。")
|
|
137
|
+
if output_format == FormatArgument.CSV:
|
|
138
|
+
columns = [
|
|
139
|
+
"attribute_id",
|
|
140
|
+
"attribute_name_en",
|
|
141
|
+
"attribute_name_ja",
|
|
142
|
+
"attribute_name_vi",
|
|
143
|
+
"type",
|
|
144
|
+
"default",
|
|
145
|
+
"read_only",
|
|
146
|
+
"choice_count",
|
|
147
|
+
"restriction_count",
|
|
148
|
+
"reference_label_count",
|
|
149
|
+
"keybind",
|
|
150
|
+
]
|
|
151
|
+
|
|
152
|
+
df = pandas.DataFrame(attribute_list, columns=columns)
|
|
145
153
|
print_csv(df, output)
|
|
146
154
|
|
|
155
|
+
elif output_format in [FormatArgument.JSON, FormatArgument.PRETTY_JSON]:
|
|
156
|
+
print_according_to_format([e.to_dict() for e in attribute_list], format=output_format, output=output)
|
|
157
|
+
|
|
147
158
|
def get_history_id_from_before_index(self, project_id: str, before: int) -> Optional[str]:
|
|
148
159
|
histories, _ = self.service.api.get_annotation_specs_histories(project_id)
|
|
149
160
|
if before + 1 > len(histories):
|
|
@@ -177,7 +188,7 @@ class PrintAnnotationSpecsAttribute(CommandLine):
|
|
|
177
188
|
else:
|
|
178
189
|
raise RuntimeError("'--project_id'か'--annotation_specs_json'のどちらかを指定する必要があります。")
|
|
179
190
|
|
|
180
|
-
self.print_annotation_specs_attribute(annotation_specs,
|
|
191
|
+
self.print_annotation_specs_attribute(annotation_specs, output_format=FormatArgument(args.format), output=args.output)
|
|
181
192
|
|
|
182
193
|
|
|
183
194
|
def parse_args(parser: argparse.ArgumentParser) -> None:
|
|
@@ -216,7 +227,14 @@ def parse_args(parser: argparse.ArgumentParser) -> None:
|
|
|
216
227
|
),
|
|
217
228
|
)
|
|
218
229
|
|
|
219
|
-
parser.add_argument(
|
|
230
|
+
parser.add_argument(
|
|
231
|
+
"-f",
|
|
232
|
+
"--format",
|
|
233
|
+
type=str,
|
|
234
|
+
choices=[FormatArgument.CSV.value, FormatArgument.JSON.value, FormatArgument.PRETTY_JSON.value],
|
|
235
|
+
default=FormatArgument.CSV.value,
|
|
236
|
+
help="出力フォーマット ",
|
|
237
|
+
)
|
|
220
238
|
|
|
221
239
|
argument_parser.add_output()
|
|
222
240
|
|
|
@@ -232,7 +250,7 @@ def main(args: argparse.Namespace) -> None:
|
|
|
232
250
|
def add_parser(subparsers: Optional[argparse._SubParsersAction] = None) -> argparse.ArgumentParser:
|
|
233
251
|
subcommand_name = "list_attribute"
|
|
234
252
|
|
|
235
|
-
subcommand_help = "
|
|
253
|
+
subcommand_help = "アノテーション仕様の属性情報を出力します。"
|
|
236
254
|
|
|
237
255
|
parser = annofabcli.common.cli.add_parser(subparsers, subcommand_name, subcommand_help)
|
|
238
256
|
parse_args(parser)
|