Skip to content

Commit

Permalink
Merge pull request #168 from kurusugawa-computer/add-task-progress
Browse files Browse the repository at this point in the history
タスク進捗状況、フェーズ別累積作業時間をCSVで出力するコマンドを追加
  • Loading branch information
yuji38kwmt authored Jan 27, 2020
2 parents 4617bd3 + ea139ed commit 2b1d389
Show file tree
Hide file tree
Showing 8 changed files with 222 additions and 8 deletions.
18 changes: 18 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,8 @@ $ docker run -it -e ANNOFAB_USER_ID=XXXX -e ANNOFAB_PASSWORD=YYYYY annofab-cli a
|project_member| invite | 複数のプロジェクトに、ユーザを招待します。 |オーナ|
|project_member| list | プロジェクトメンバ一覧を出力します。 |-|
|project_member| put | CSVに記載されたユーザを、プロジェクトメンバとして登録します。|オーナ|
|statistics| list_cumulative_labor_time | タスク進捗状況を出力します。 |-|
|statistics| list_task_progress | タスクフェーズ別の累積作業時間を出力します。 |-|
|statistics| visualize | 統計情報を可視化します。 |オーナ|
|supplementary| list | 補助情報を出力します。 |オーナ|
|task| cancel_acceptance | 受け入れ完了タスクを、受け入れ取り消し状態にします。 |オーナ|
Expand Down Expand Up @@ -939,6 +941,22 @@ $ annofabcli project_member put --project_id prj1 --csv members.csv
$ annofabcli project_member put --project_id prj1 --csv members.csv --delete
```
### statistics list_cumulative_labor_time
タスクフェーズ別の累積作業時間をCSV形式で出力します。
```
$ annofabcli statistics list_cumulative_labor_time --project_id prj1 --output stat.csv
```
### statistics list_task_progress
タスク進捗状況をCSV形式で出力します。
```
$ annofabcli statistics list_task_progress --project_id prj1 --output stat.csv
```
### statistics visualize
統計情報を可視化します。
Expand Down
2 changes: 1 addition & 1 deletion annofabcli/__version__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = "1.19.0"
__version__ = "1.20.0"
4 changes: 2 additions & 2 deletions annofabcli/common/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -480,8 +480,8 @@ def validate_project(
プロジェクト or 組織に対して、必要な権限が付与されているかを確認する。
Args:
project_id: 
project_member_roles: プロジェクトメンバロールの一覧
organization_member_roles: 組織メンバロールの一覧
project_member_roles: プロジェクトメンバロールの一覧. Noneの場合はチェックしない。
organization_member_roles: 組織メンバロールの一覧。Noneの場合はチェックしない。
Raises:
AuthorizationError: 自分自身のRoleがいずれかのRoleにも合致しなければ、AuthorizationErrorが発生する。
Expand Down
23 changes: 18 additions & 5 deletions annofabcli/common/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,23 +102,33 @@ def progress_msg(index: int, size: int):
return str_format.format(index, size)


def output_string(target: str, output: Optional[str] = None):
def output_string(target: str, output: Optional[str] = None) -> None:
"""
ファイルパスが指定されていればファイルに、指定しなければ標準出力に出力する
文字列を出力する
Args:
target:
output:
target: 出力対象の文字列
output: 出力先。Noneなら標準出力に出力する。
"""
if output is None:
print(target)
else:
Path(output).parent.mkdir(parents=True, exist_ok=True)
with open(output, mode="w", encoding="utf_8_sig") as f:
f.write(target)
logger.info(f"{output} に出力しました。")


def print_json(target: Any, is_pretty: bool = False, output: Optional[str] = None):
def print_json(target: Any, is_pretty: bool = False, output: Optional[str] = None) -> None:
"""
JSONを出力する。
Args:
target: 出力対象のJSON
is_pretty: 人が見やすいJSONを出力するか
output: 出力先。Noneなら標準出力に出力する。
"""
if is_pretty:
output_string(json.dumps(target, indent=2, ensure_ascii=False), output)
else:
Expand All @@ -136,6 +146,9 @@ def print_csv(df: pandas.DataFrame, output: Optional[str] = None, to_csv_kwargs:
else:
df.to_csv(path_or_buf, **to_csv_kwargs)

if output is not None:
logger.info(f"{output} に出力しました。")


def print_id_list(id_list: List[Any], output: Optional[str]):
s = "\n".join(id_list)
Expand Down
84 changes: 84 additions & 0 deletions annofabcli/statistics/list_cumulative_labor_time.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
"""
アノテーション仕様を出力する
"""

import argparse
import logging
from typing import Any, Dict, List

import pandas

import annofabcli
import annofabcli.common.cli
from annofabcli import AnnofabApiFacade
from annofabcli.common.cli import AbstractCommandLineInterface, ArgumentParser, build_annofabapi_resource_and_login
from annofabcli.common.utils import isoduration_to_hour

logger = logging.getLogger(__name__)


class TaskProgress(AbstractCommandLineInterface):
"""
タスクフェーズ別の累積作業時間を出力する。
"""

def get_task_phase_statistics(self, project_id: str) -> List[Dict[str, Any]]:
"""
フェーズごとの累積作業時間をCSVに出力するための dict 配列を作成する。
Args:
project_id:
Returns:
フェーズごとの累積作業時間に対応するdict配列
"""
task_phase_statistics, _ = self.service.api.get_task_phase_statistics(project_id)
row_list: List[Dict[str, Any]] = []
for stat_by_date in task_phase_statistics:
date = stat_by_date["date"]
phase_stat_list = stat_by_date["phases"]
for phase_stat in phase_stat_list:
phase_stat["date"] = date
phase_stat["worktime_hour"] = isoduration_to_hour(phase_stat["worktime"])
row_list.extend(phase_stat_list)
return row_list

def list_cumulative_labor_time(self, project_id: str) -> None:
super().validate_project(project_id, project_member_roles=None)

phase_stat_list = self.get_task_phase_statistics(project_id)
df = pandas.DataFrame(phase_stat_list)
# 出力対象の列を指定する
target_df = df[["date", "phase", "worktime_hour"]]
annofabcli.utils.print_csv(target_df, output=self.output, to_csv_kwargs=self.csv_format)

def main(self):
args = self.args

project_id = args.project_id
self.list_cumulative_labor_time(project_id)


def parse_args(parser: argparse.ArgumentParser):
argument_parser = ArgumentParser(parser)

argument_parser.add_project_id()
argument_parser.add_csv_format()
argument_parser.add_output()

parser.set_defaults(subcommand_func=main)


def main(args):
service = build_annofabapi_resource_and_login(args)
facade = AnnofabApiFacade(service)
TaskProgress(service, facade, args).main()


def add_parser(subparsers: argparse._SubParsersAction):
subcommand_name = "list_cumulative_labor_time"
subcommand_help = "タスクフェーズ別の累積作業時間を出力する。"
description = "タスクフェーズ別の累積作業時間をCSV形式で出力する。"
parser = annofabcli.common.cli.add_parser(subparsers, subcommand_name, subcommand_help, description=description)
parse_args(parser)
83 changes: 83 additions & 0 deletions annofabcli/statistics/list_task_progress.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
"""
アノテーション仕様を出力する
"""

import argparse
import logging
from typing import Any, Dict, List

import pandas

import annofabcli
import annofabcli.common.cli
from annofabcli import AnnofabApiFacade
from annofabcli.common.cli import AbstractCommandLineInterface, ArgumentParser, build_annofabapi_resource_and_login

logger = logging.getLogger(__name__)


class TaskProgress(AbstractCommandLineInterface):
"""
タスクの進捗状況を出力する。
"""

def get_task_statistics(self, project_id: str) -> List[Dict[str, Any]]:
"""
タスクの進捗状況をCSVに出力するための dict 配列を作成する。
Args:
project_id:
Returns:
タスクの進捗状況に対応するdict配列
"""
task_statistics, _ = self.service.api.get_task_statistics(project_id)
row_list: List[Dict[str, Any]] = []
for stat_by_date in task_statistics:
date = stat_by_date["date"]
task_stat_list = stat_by_date["tasks"]
for task_stat in task_stat_list:
task_stat["date"] = date
row_list.extend(task_stat_list)
return row_list

def list_task_progress(self, project_id: str) -> None:
super().validate_project(project_id, project_member_roles=None)

task_stat_list = self.get_task_statistics(project_id)
df = pandas.DataFrame(task_stat_list)
# 出力対象の列を指定する
target_df = df[["date", "phase", "status", "count"]]

annofabcli.utils.print_csv(target_df, output=self.output, to_csv_kwargs=self.csv_format)

def main(self):
args = self.args

project_id = args.project_id
self.list_task_progress(project_id)


def parse_args(parser: argparse.ArgumentParser):
argument_parser = ArgumentParser(parser)

argument_parser.add_project_id()
argument_parser.add_csv_format()
argument_parser.add_output()

parser.set_defaults(subcommand_func=main)


def main(args):
service = build_annofabapi_resource_and_login(args)
facade = AnnofabApiFacade(service)
TaskProgress(service, facade, args).main()


def add_parser(subparsers: argparse._SubParsersAction):
subcommand_name = "list_task_progress"
subcommand_help = "タスク進捗情報を出力する"
description = "タスク進捗状況をCSV形式で出力する。"
parser = annofabcli.common.cli.add_parser(subparsers, subcommand_name, subcommand_help, description=description)
parse_args(parser)
4 changes: 4 additions & 0 deletions annofabcli/statistics/subcommand_statistics.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

import annofabcli
import annofabcli.common.cli
import annofabcli.statistics.list_cumulative_labor_time
import annofabcli.statistics.list_task_progress
import annofabcli.statistics.visualize_statistics


Expand All @@ -10,6 +12,8 @@ def parse_args(parser: argparse.ArgumentParser):
subparsers = parser.add_subparsers(dest="subcommand_name")

# サブコマンドの定義
annofabcli.statistics.list_cumulative_labor_time.add_parser(subparsers)
annofabcli.statistics.list_task_progress.add_parser(subparsers)
annofabcli.statistics.visualize_statistics.add_parser(subparsers)


Expand Down
12 changes: 12 additions & 0 deletions tests/test_main.py
Original file line number Diff line number Diff line change
Expand Up @@ -444,6 +444,18 @@ def test_visualize(self):
]
)

def test_list_task_progress(self):
out_file = str(out_path / "task-progress.csv")
main(
["statistics", "list_task_progress", "--project_id", project_id, "--output", out_file,]
)

def test_list_cumulative_labor_time(self):
out_file = str(out_path / "cumulative-labor-time.csv")
main(
["statistics", "list_cumulative_labor_time", "--project_id", project_id, "--output", out_file,]
)


class TestSupplementary:
def test_list_project_member(self):
Expand Down

0 comments on commit 2b1d389

Please sign in to comment.