Compare commits
No commits in common. "e7e286fbf3c7e7368e8462348986a57d096e100d" and "6594f515f3117225bf1d2e0307f01f28a6e1f5c2" have entirely different histories.
e7e286fbf3
...
6594f515f3
113
jiracli/cli.py
113
jiracli/cli.py
|
@ -2,7 +2,7 @@ import configparser
|
||||||
import functools
|
import functools
|
||||||
import os
|
import os
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from textwrap import dedent, indent, shorten, wrap
|
from textwrap import indent, shorten, wrap
|
||||||
from typing import Any, Callable, Dict
|
from typing import Any, Callable, Dict
|
||||||
|
|
||||||
import click
|
import click
|
||||||
|
@ -90,9 +90,8 @@ def version(client):
|
||||||
|
|
||||||
@main.command()
|
@main.command()
|
||||||
@click.option('--project', help='Project to filter for. Default: take from config [filters]/default_project')
|
@click.option('--project', help='Project to filter for. Default: take from config [filters]/default_project')
|
||||||
@click.option('--component', 'components', multiple=True, help='Filter for issues with *any* of the given components')
|
@click.option('--component', 'components', help='Filter for issues with *any* of the given components')
|
||||||
@click.option('--status', multiple=True, help='Filter for issues with *any* of the given statuses. '
|
@click.option('--status', multiple=True, help='Filter for issues with *any* of the given statuses')
|
||||||
'! at the beginning means NOT.')
|
|
||||||
@click.option('--label', 'labels', multiple=True, help='Filter for issues with all the given labels')
|
@click.option('--label', 'labels', multiple=True, help='Filter for issues with all the given labels')
|
||||||
@click.option('--text', 'texts', multiple=True, help='Filter for issues containing all the given strings')
|
@click.option('--text', 'texts', multiple=True, help='Filter for issues containing all the given strings')
|
||||||
@click.option('--flagged/--not-flagged', is_flag=True, default=None, help='Filter issues being flagged or not flagged')
|
@click.option('--flagged/--not-flagged', is_flag=True, default=None, help='Filter issues being flagged or not flagged')
|
||||||
|
@ -103,8 +102,10 @@ def version(client):
|
||||||
@pass_client
|
@pass_client
|
||||||
@pass_config
|
@pass_config
|
||||||
def issues(config, client, project, components, status, labels, texts, flagged, order, asc, jql):
|
def issues(config, client, project, components, status, labels, texts, flagged, order, asc, jql):
|
||||||
if not project and config.has_section('filters') and config.get('filters', 'default_project'):
|
filters_config = config['filters']
|
||||||
project = config['filters']['default_project']
|
|
||||||
|
if not project and filters_config and 'default_project' in filters_config:
|
||||||
|
project = filters_config['default_project']
|
||||||
project_jql = f"project = {project}"
|
project_jql = f"project = {project}"
|
||||||
|
|
||||||
# TODO add filtering by created since
|
# TODO add filtering by created since
|
||||||
|
@ -123,14 +124,9 @@ def issues(config, client, project, components, status, labels, texts, flagged,
|
||||||
filters.append(components_jql)
|
filters.append(components_jql)
|
||||||
|
|
||||||
if status:
|
if status:
|
||||||
status_list = ', '.join([f'"{s}"' for s in status if not s.startswith('!')])
|
status_list = ', '.join([f'"{s}"' for s in status])
|
||||||
if status_list:
|
|
||||||
status_jql = f"status IN ({status_list})"
|
status_jql = f"status IN ({status_list})"
|
||||||
filters.append(status_jql)
|
filters.append(status_jql)
|
||||||
status_list = ', '.join([f'"{s[1:]}"' for s in status if s.startswith('!')])
|
|
||||||
if status_list:
|
|
||||||
status_jql = f"status NOT IN ({status_list})"
|
|
||||||
filters.append(status_jql)
|
|
||||||
|
|
||||||
if labels:
|
if labels:
|
||||||
labels_jql = ' AND '.join([f'labels = "{label}"' for label in labels])
|
labels_jql = ' AND '.join([f'labels = "{label}"' for label in labels])
|
||||||
|
@ -272,34 +268,26 @@ def link():
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
def _format_links(client, issue):
|
|
||||||
lines = []
|
|
||||||
issuelinks = getattr(issue.fields, 'issuelinks', [])
|
|
||||||
if issuelinks:
|
|
||||||
lines.append("Issue Links")
|
|
||||||
# TODO group by type?
|
|
||||||
for issuelink in issuelinks:
|
|
||||||
other_issue = getattr(issuelink, 'inwardIssue', getattr(issuelink, 'outwardIssue', None))
|
|
||||||
summary = indent('\n'.join(wrap(other_issue.fields.summary, width=72)), prefix=' ' * 4)
|
|
||||||
lines.append(f" {issuelink.type} - {other_issue.key}\n{summary}")
|
|
||||||
|
|
||||||
remote_links = client.remote_links(issue.id)
|
|
||||||
if remote_links:
|
|
||||||
if lines:
|
|
||||||
lines.append('')
|
|
||||||
lines.append("Remote Links:")
|
|
||||||
for link in remote_links:
|
|
||||||
# TODO tabulate?
|
|
||||||
lines.append(f" {link.object.title} => {link.object.url}")
|
|
||||||
|
|
||||||
return '\n'.join(lines)
|
|
||||||
|
|
||||||
|
|
||||||
@link.command('list')
|
@link.command('list')
|
||||||
@pass_issue
|
@pass_issue
|
||||||
@pass_client
|
@pass_client
|
||||||
def link_list(client, issue):
|
def link_list(client, issue):
|
||||||
print(_format_links(client, issue))
|
|
||||||
|
issuelinks = getattr(issue.fields, 'issuelinks', [])
|
||||||
|
if issuelinks:
|
||||||
|
print("\nIssue Links")
|
||||||
|
# TODO group by type?
|
||||||
|
for issuelink in issuelinks:
|
||||||
|
other_issue = getattr(issuelink, 'inwardIssue', issuelink.outwardIssue)
|
||||||
|
summary = indent('\n'.join(wrap(other_issue.fields.summary, width=72)), prefix=' ' * 4)
|
||||||
|
print(f" {issuelink.type} - {other_issue.key}\n{summary}")
|
||||||
|
|
||||||
|
remote_links = client.remote_links(issue.id)
|
||||||
|
if remote_links:
|
||||||
|
print("\nRemote Links:")
|
||||||
|
for link in remote_links:
|
||||||
|
# TODO tabulate?
|
||||||
|
print(f" {link.object.title} => {link.object.url}")
|
||||||
|
|
||||||
|
|
||||||
def prompt(description: str, *, multiline_ok: bool = True, initial_content: str = '', empty_ok: bool = False) -> str:
|
def prompt(description: str, *, multiline_ok: bool = True, initial_content: str = '', empty_ok: bool = False) -> str:
|
||||||
|
@ -408,58 +396,11 @@ def label_edit(issue):
|
||||||
@pass_issue
|
@pass_issue
|
||||||
def debug(issue):
|
def debug(issue):
|
||||||
import IPython
|
import IPython
|
||||||
IPython.embed()
|
IPython.embed
|
||||||
|
|
||||||
|
|
||||||
@issue.command()
|
@issue.command()
|
||||||
@pass_issue
|
@pass_issue
|
||||||
@pass_client
|
def show(issue):
|
||||||
def show(client, issue):
|
|
||||||
"""Show a lot of information about the issue"""
|
"""Show a lot of information about the issue"""
|
||||||
print(f"{issue.key} on {issue.fields.status} as {issue.fields.issuetype} assigned to {issue.fields.assignee}")
|
raise NotImplementedError
|
||||||
if getattr(issue.fields, 'parent', None):
|
|
||||||
parent = issue.fields.parent
|
|
||||||
print(f" parent: {parent.key} on {parent.fields.status} as {parent.fields.issuetype}")
|
|
||||||
summary = indent('\n'.join(wrap(parent.fields.summary, width=72)), prefix=' ' * 4)
|
|
||||||
print(f"{summary}")
|
|
||||||
print(indent(dedent(f"""\
|
|
||||||
created: {issue.fields.created}
|
|
||||||
components: {', '.join(issue.fields.components)}
|
|
||||||
flagged: {getattr(issue.fields, 'flagged', False)}
|
|
||||||
labels: {', '.join(issue.fields.labels)}
|
|
||||||
priority: {issue.fields.priority}
|
|
||||||
reporter: {issue.fields.reporter}"""),
|
|
||||||
' ' * 2))
|
|
||||||
|
|
||||||
def _header(s):
|
|
||||||
# print(f"\n {s}\n {'+' * len(s)}")
|
|
||||||
print(f"\n +++ {s} +++")
|
|
||||||
|
|
||||||
summary = indent('\n'.join(wrap(issue.fields.summary, replace_whitespace=False)), prefix=' ' * 2)
|
|
||||||
_header('summary')
|
|
||||||
print(summary)
|
|
||||||
|
|
||||||
description = indent('\n'.join(wrap(issue.fields.description or '', replace_whitespace=False)), prefix=' ' * 2)
|
|
||||||
_header('description')
|
|
||||||
print(description)
|
|
||||||
|
|
||||||
_header('attachments')
|
|
||||||
for i, attachment in enumerate(issue.fields.attachment):
|
|
||||||
print(f" * {attachment.filename} by {attachment.author}")
|
|
||||||
print(f" {attachment.content}")
|
|
||||||
print(f" {attachment.mimeType} with {attachment.size} B")
|
|
||||||
|
|
||||||
_header('links')
|
|
||||||
links = _format_links(client, issue)
|
|
||||||
if links:
|
|
||||||
print(indent(links, prefix=' ' * 2))
|
|
||||||
|
|
||||||
_header('comments')
|
|
||||||
for i, comment in enumerate(issue.fields.comment.comments):
|
|
||||||
if i != 0:
|
|
||||||
print('')
|
|
||||||
print(f" {comment.created} - {comment.author}")
|
|
||||||
body = indent('\n'.join(wrap(comment.body, replace_whitespace=False)), ' ' * 4)
|
|
||||||
print(body)
|
|
||||||
|
|
||||||
print('')
|
|
||||||
|
|
Loading…
Reference in New Issue