phable-cli 0.1.10__tar.gz → 0.1.11__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.
- {phable_cli-0.1.10 → phable_cli-0.1.11}/PKG-INFO +1 -1
- {phable_cli-0.1.10 → phable_cli-0.1.11}/phable/cli/assign.py +6 -2
- {phable_cli-0.1.10 → phable_cli-0.1.11}/phable/cli/list.py +4 -4
- {phable_cli-0.1.10 → phable_cli-0.1.11}/phable/cli/report.py +3 -3
- {phable_cli-0.1.10 → phable_cli-0.1.11}/phable/cli/show.py +2 -2
- phable_cli-0.1.11/phable/display.py +127 -0
- {phable_cli-0.1.10 → phable_cli-0.1.11}/phable/phabricator.py +0 -3
- {phable_cli-0.1.10 → phable_cli-0.1.11}/pyproject.toml +1 -1
- phable_cli-0.1.10/phable/display.py +0 -68
- {phable_cli-0.1.10 → phable_cli-0.1.11}/LICENSE +0 -0
- {phable_cli-0.1.10 → phable_cli-0.1.11}/README.md +0 -0
- {phable_cli-0.1.10 → phable_cli-0.1.11}/phable/cache.py +0 -0
- {phable_cli-0.1.10 → phable_cli-0.1.11}/phable/cli/__init__.py +0 -0
- {phable_cli-0.1.10 → phable_cli-0.1.11}/phable/cli/cache.py +0 -0
- {phable_cli-0.1.10 → phable_cli-0.1.11}/phable/cli/comment.py +0 -0
- {phable_cli-0.1.10 → phable_cli-0.1.11}/phable/cli/config.py +0 -0
- {phable_cli-0.1.10 → phable_cli-0.1.11}/phable/cli/create.py +0 -0
- {phable_cli-0.1.10 → phable_cli-0.1.11}/phable/cli/main.py +0 -0
- {phable_cli-0.1.10 → phable_cli-0.1.11}/phable/cli/move.py +0 -0
- {phable_cli-0.1.10 → phable_cli-0.1.11}/phable/cli/subscribe.py +0 -0
- {phable_cli-0.1.10 → phable_cli-0.1.11}/phable/cli/utils.py +0 -0
- {phable_cli-0.1.10 → phable_cli-0.1.11}/phable/config.py +0 -0
- {phable_cli-0.1.10 → phable_cli-0.1.11}/phable/tests/conftest.py +0 -0
- {phable_cli-0.1.10 → phable_cli-0.1.11}/phable/tests/fixtures/simple_task.json +0 -0
- {phable_cli-0.1.10 → phable_cli-0.1.11}/phable/tests/phabricator_test.py +0 -0
- {phable_cli-0.1.10 → phable_cli-0.1.11}/phable/utils.py +0 -0
|
@@ -25,8 +25,12 @@ def assign_task(
|
|
|
25
25
|
|
|
26
26
|
\b
|
|
27
27
|
Examples:
|
|
28
|
-
|
|
29
|
-
|
|
28
|
+
\b
|
|
29
|
+
# self assign task
|
|
30
|
+
$ phable assign T123456
|
|
31
|
+
\b
|
|
32
|
+
# asign to username
|
|
33
|
+
$ phable assign T123456 --usernamme brouberol
|
|
30
34
|
|
|
31
35
|
"""
|
|
32
36
|
if not username:
|
|
@@ -3,7 +3,7 @@ from typing import Optional
|
|
|
3
3
|
|
|
4
4
|
from phable.phabricator import PhabricatorClient
|
|
5
5
|
from phable.config import config
|
|
6
|
-
from phable.display import display_tasks
|
|
6
|
+
from phable.display import display_tasks, TaskFormat
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
@click.command(name="list")
|
|
@@ -30,7 +30,7 @@ from phable.display import display_tasks
|
|
|
30
30
|
@click.option(
|
|
31
31
|
"--format",
|
|
32
32
|
required=False,
|
|
33
|
-
type=click.Choice(
|
|
33
|
+
type=click.Choice(TaskFormat, case_sensitive=False),
|
|
34
34
|
default="plain",
|
|
35
35
|
help="The output format of the task list",
|
|
36
36
|
)
|
|
@@ -42,7 +42,7 @@ def list_tasks(
|
|
|
42
42
|
columns: list[str],
|
|
43
43
|
owner: Optional[str] = None,
|
|
44
44
|
milestone: bool = False,
|
|
45
|
-
format:
|
|
45
|
+
format: TaskFormat = TaskFormat.PLAIN,
|
|
46
46
|
):
|
|
47
47
|
"""Lists and filter tasks
|
|
48
48
|
|
|
@@ -78,4 +78,4 @@ def list_tasks(
|
|
|
78
78
|
column_phids=column_phids, owner_phid=owner_user, project_phid=project_phid
|
|
79
79
|
)
|
|
80
80
|
tasks = [client.enrich_task(task) for task in tasks]
|
|
81
|
-
display_tasks(tasks=tasks, format=format
|
|
81
|
+
display_tasks(tasks=tasks, format=format)
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import click
|
|
2
2
|
from phable.config import config
|
|
3
3
|
from phable.phabricator import PhabricatorClient
|
|
4
|
-
from phable.display import display_tasks
|
|
4
|
+
from phable.display import display_tasks, TaskFormat
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
@click.command(name="report-done-tasks")
|
|
@@ -15,7 +15,7 @@ from phable.display import display_tasks
|
|
|
15
15
|
)
|
|
16
16
|
@click.option(
|
|
17
17
|
"--format",
|
|
18
|
-
type=click.Choice(
|
|
18
|
+
type=click.Choice(TaskFormat, case_sensitive=False),
|
|
19
19
|
default="plain",
|
|
20
20
|
help="Output format",
|
|
21
21
|
)
|
|
@@ -51,7 +51,7 @@ def report_done_tasks(
|
|
|
51
51
|
column_destination_phid = client.find_column_in_project(
|
|
52
52
|
target_project_phid, destination
|
|
53
53
|
)
|
|
54
|
-
tasks = client.
|
|
54
|
+
tasks = client.find_tasks(column_phids=[column_source_phid])
|
|
55
55
|
|
|
56
56
|
enriched_tasks = []
|
|
57
57
|
for task in tasks:
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import click
|
|
2
2
|
from phable.utils import Task
|
|
3
3
|
from phable.phabricator import PhabricatorClient
|
|
4
|
-
from phable.display import display_task
|
|
4
|
+
from phable.display import display_task, TaskFormat
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
@click.command(name="show")
|
|
8
8
|
@click.option(
|
|
9
9
|
"--format",
|
|
10
|
-
type=click.Choice(
|
|
10
|
+
type=click.Choice(TaskFormat, case_sensitive=False),
|
|
11
11
|
default="plain",
|
|
12
12
|
help="Output format",
|
|
13
13
|
)
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import json
|
|
2
|
+
from collections.abc import Callable
|
|
3
|
+
from enum import StrEnum, auto
|
|
4
|
+
|
|
5
|
+
from .utils import Task
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class TaskFormat(StrEnum):
|
|
9
|
+
PLAIN = auto()
|
|
10
|
+
JSON = auto()
|
|
11
|
+
HTML = auto()
|
|
12
|
+
MARKDOWN = auto()
|
|
13
|
+
WIKITEXT = auto()
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def display_tasks(
|
|
17
|
+
tasks: list[dict],
|
|
18
|
+
format: TaskFormat,
|
|
19
|
+
) -> None:
|
|
20
|
+
if len(tasks) == 1:
|
|
21
|
+
display_task(tasks[0], format=format)
|
|
22
|
+
get_printer(format).print_list(tasks)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def display_task(task: dict, format: TaskFormat) -> None:
|
|
26
|
+
get_printer(format).print(task)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class TaskPrinter:
|
|
30
|
+
def __init__(self, printer: Callable):
|
|
31
|
+
self._printer = printer
|
|
32
|
+
|
|
33
|
+
def print(self, task: dict) -> None:
|
|
34
|
+
pass
|
|
35
|
+
|
|
36
|
+
def print_list(self, tasks: list[dict]) -> None:
|
|
37
|
+
pass
|
|
38
|
+
|
|
39
|
+
def title(self, task: dict) -> str:
|
|
40
|
+
return f"{Task.from_int(task['id'])} {task['fields']['name']}"
|
|
41
|
+
|
|
42
|
+
def status(self, task: dict) -> str:
|
|
43
|
+
return f"({task['fields']['status']['name']})"
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
class JsonTaskPrinter(TaskPrinter):
|
|
47
|
+
def print(self, task: dict) -> None:
|
|
48
|
+
self._printer(json.dumps(task, indent=2))
|
|
49
|
+
|
|
50
|
+
def print_list(self, tasks: list[dict]) -> None:
|
|
51
|
+
self._printer(json.dumps(tasks, indent=2))
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
class MarkdownTaskPrinter(TaskPrinter):
|
|
55
|
+
def print(self, task: dict) -> None:
|
|
56
|
+
self._printer(f"* [{self.title(task)}]({task['url']}) {self.status(task)}")
|
|
57
|
+
|
|
58
|
+
def print_list(self, tasks: list[dict]) -> None:
|
|
59
|
+
for task in tasks:
|
|
60
|
+
self.print(task)
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
class WikitextTaskPrinter(TaskPrinter):
|
|
64
|
+
def print(self, task: dict) -> None:
|
|
65
|
+
self._printer(f"* [{task['url']} {self.title(task)}] {self.status(task)}")
|
|
66
|
+
|
|
67
|
+
def print_list(self, tasks: list[dict]) -> None:
|
|
68
|
+
for task in tasks:
|
|
69
|
+
self.print(task)
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
class HtmlTaskPrinter(TaskPrinter):
|
|
73
|
+
def print(self, task: dict) -> None:
|
|
74
|
+
self._printer(
|
|
75
|
+
f"<a href={task['url']}>{self.title(task)}</a> {self.status(task)}"
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
def print_list(self, tasks: list[dict]) -> None:
|
|
79
|
+
for task in tasks:
|
|
80
|
+
self._printer(
|
|
81
|
+
f"<li><a href={task['url']}>{self.title(task)}</a> {self.status(task)}</li>"
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
class PlainTaskPrinter(TaskPrinter):
|
|
86
|
+
def print(self, task: dict) -> None:
|
|
87
|
+
parent_str = self.title(task.get("parent")) if task.get("parent") else ""
|
|
88
|
+
print(f"URL: {task['url']}")
|
|
89
|
+
print(f"Task: {Task.from_int(task['id'])}")
|
|
90
|
+
print(f"Title: {task['fields']['name']}")
|
|
91
|
+
if task.get("author"):
|
|
92
|
+
print(f"Author: {task['author']['fields']['username']}")
|
|
93
|
+
if task.get("owner"):
|
|
94
|
+
print(f"Owner: {task['owner']}")
|
|
95
|
+
if task.get("tags"):
|
|
96
|
+
print(f"Tags: {', '.join(task['tags'])}")
|
|
97
|
+
print(f"Status: {task['fields']['status']['name']}")
|
|
98
|
+
print(f"Priority: {task['fields']['priority']['name']}")
|
|
99
|
+
print(f"Description: {task['fields']['description']['raw']}")
|
|
100
|
+
print(f"Parent: {parent_str}")
|
|
101
|
+
print("Subtasks:")
|
|
102
|
+
if task.get("subtasks"):
|
|
103
|
+
for subtask in task["subtasks"]:
|
|
104
|
+
status = f"{'[x]' if subtask['fields']['status']['value'] == 'resolved' else '[ ]'}"
|
|
105
|
+
print(
|
|
106
|
+
f"{status} - {Task.from_int(subtask['id'])} - @{subtask['owner']:<10} - {subtask['fields']['name']}"
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
def print_list(self, tasks: list[dict]) -> None:
|
|
110
|
+
for task in tasks:
|
|
111
|
+
self.print(task)
|
|
112
|
+
self._printer("=" * 50)
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
def get_printer(format: TaskFormat) -> TaskPrinter:
|
|
116
|
+
if format == TaskFormat.PLAIN:
|
|
117
|
+
return PlainTaskPrinter(print)
|
|
118
|
+
elif format == TaskFormat.JSON:
|
|
119
|
+
return JsonTaskPrinter(print)
|
|
120
|
+
elif format == TaskFormat.HTML:
|
|
121
|
+
return HtmlTaskPrinter(print)
|
|
122
|
+
elif format == TaskFormat.MARKDOWN:
|
|
123
|
+
return MarkdownTaskPrinter(print)
|
|
124
|
+
elif format == TaskFormat.WIKITEXT:
|
|
125
|
+
return WikitextTaskPrinter(print)
|
|
126
|
+
else:
|
|
127
|
+
raise ValueError(f"Unknown format: {format}")
|
|
@@ -163,9 +163,6 @@ class PhabricatorClient:
|
|
|
163
163
|
parent = self.find_parent_task(subtask_id=task["id"])
|
|
164
164
|
task["parent"] = parent
|
|
165
165
|
|
|
166
|
-
def find_tasks_in_column(self, column_phid: str) -> list[dict[str, Any]]:
|
|
167
|
-
return self.find_tasks(column_phid=column_phid)
|
|
168
|
-
|
|
169
166
|
def find_tasks(
|
|
170
167
|
self,
|
|
171
168
|
column_phids: Optional[list[str]] = None,
|
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
import json
|
|
2
|
-
from typing import Literal, TypeAlias
|
|
3
|
-
|
|
4
|
-
from .utils import Task
|
|
5
|
-
|
|
6
|
-
TaskFormat: TypeAlias = Literal["plain", "json", "html", "markdown"]
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
def display_task(task: dict, format: TaskFormat, prefix: str = "", end: str = "\n"):
|
|
10
|
-
title = f"{Task.from_int(task['id'])} {task['fields']['name']} ({task['fields']['status']['name']})"
|
|
11
|
-
|
|
12
|
-
if format == "json":
|
|
13
|
-
print(json.dumps(task, indent=2))
|
|
14
|
-
elif format == "html":
|
|
15
|
-
print(
|
|
16
|
-
f"{prefix}<a href={task['url']}>{title}</a>",
|
|
17
|
-
end=end,
|
|
18
|
-
)
|
|
19
|
-
elif format == "markdown":
|
|
20
|
-
print(
|
|
21
|
-
f"{prefix}[{title}]({task['url']})",
|
|
22
|
-
end=end,
|
|
23
|
-
)
|
|
24
|
-
else:
|
|
25
|
-
parent_str = (
|
|
26
|
-
f"{Task.from_int(task['parent']['id'])} {task['parent']['fields']['name']}"
|
|
27
|
-
if task.get("parent")
|
|
28
|
-
else ""
|
|
29
|
-
)
|
|
30
|
-
print(f"URL: {task['url']}")
|
|
31
|
-
print(f"Task: {Task.from_int(task['id'])}")
|
|
32
|
-
print(f"Title: {task['fields']['name']}")
|
|
33
|
-
if task.get("author"):
|
|
34
|
-
print(f"Author: {task['author']['fields']['username']}")
|
|
35
|
-
if task.get("owner"):
|
|
36
|
-
print(f"Owner: {task['owner']}")
|
|
37
|
-
if task.get("tags"):
|
|
38
|
-
print(f"Tags: {', '.join(task['tags'])}")
|
|
39
|
-
print(f"Status: {task['fields']['status']['name']}")
|
|
40
|
-
print(f"Priority: {task['fields']['priority']['name']}")
|
|
41
|
-
print(f"Description: {task['fields']['description']['raw']}")
|
|
42
|
-
print(f"Parent: {parent_str}")
|
|
43
|
-
print("Subtasks:")
|
|
44
|
-
if task.get("subtasks"):
|
|
45
|
-
for subtask in task["subtasks"]:
|
|
46
|
-
status = f"{'[x]' if subtask['fields']['status']['value'] == 'resolved' else '[ ]'}"
|
|
47
|
-
print(
|
|
48
|
-
f"{status} - {Task.from_int(subtask['id'])} - @{subtask['owner']:<10} - {subtask['fields']['name']}"
|
|
49
|
-
)
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
def display_tasks(
|
|
53
|
-
tasks: list[dict],
|
|
54
|
-
format: TaskFormat,
|
|
55
|
-
separator: str = "=" * 50,
|
|
56
|
-
):
|
|
57
|
-
if len(tasks) == 1:
|
|
58
|
-
return display_task(tasks[0], format=format)
|
|
59
|
-
|
|
60
|
-
if format == "json":
|
|
61
|
-
print(json.dumps(tasks, indent=2))
|
|
62
|
-
elif format == "markdown":
|
|
63
|
-
for task in tasks:
|
|
64
|
-
display_task(task, format=format, prefix="* ")
|
|
65
|
-
else:
|
|
66
|
-
for task in tasks:
|
|
67
|
-
display_task(task, format=format, prefix="<li>", end="")
|
|
68
|
-
print(separator)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|