Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for markdown format output #315

Merged
merged 8 commits into from
Sep 8, 2023
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -86,12 +86,13 @@ The default output is plain text of maximum width 79 characters.
This can be adjusted using the ``--width`` parameter. To disable
shortening altogether use ``--width=0``. The default width value
can be saved in the config file as well. Use ``--format=wiki`` to
enable simple MoinMoin wiki syntax. For stats which support them,
``--brief`` and ``--verbose`` can be used to specify a different
level of detail to be shown.
enable simple MoinMoin wiki syntax or ``--format=markdown`` to
enable markdown syntax. For stats which support them, ``--brief``
and ``--verbose`` can be used to specify a different level of
detail to be shown.

--format=FMT
Output style, possible values: text (default) or wiki
--format {text,markdown,wiki}
Output style, default: text

--width=WIDTH
Maximum width of the report output (default: 79)
Expand Down
15 changes: 12 additions & 3 deletions did/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,8 @@ def __init__(self, arguments=None):
# Formating options
group = self.parser.add_argument_group("Format")
group.add_argument(
"--format", default="text",
help="Output style, possible values: text (default) or wiki")
"--format", default="text", choices=["text", "markdown", "wiki"],
help="Output style, default: text")
group.add_argument(
"--width", default=width, type=int,
help="Maximum width of the report output (default: %(default)s)")
Expand Down Expand Up @@ -149,8 +149,17 @@ def parse(self):
raise RuntimeError(
"Invalid date range ({0} to {1})".format(
opt.since, opt.until.date - delta(days=1)))
header = "Status report for {0} ({1} to {2}).".format(

header = "Status report for {0} ({1} to {2})".format(
period, opt.since, opt.until.date - delta(days=1))
if opt.format == "markdown":
# In markdown the first line must be a header
# using alternate syntax allowing to use did's
# output in commit messages as well
header = f"{header}\n{'=' * len(header)}"
else:
# In markdown no trailing punctuation is allowed in headings
header = header + "."

# Finito
log.debug("Gathered options:")
Expand Down
4 changes: 4 additions & 0 deletions did/plugins/bugzilla.py
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,10 @@ def __str__(self):
""" Consistent identifier and summary for displaying """
if self.options.format == "wiki":
return "<<Bug({0})>> - {1}".format(self.id, self.summary)
elif self.options.format == "markdown":
link = self.parent.url.replace("xmlrpc.cgi", "show_bug.cgi?id=")
return "[{0}#{1}]({2}{1}) - {3}".format(
self.prefix, str(self.id), link, self.summary)
else:
return "{0}#{1} - {2}".format(
self.prefix, str(self.id).rjust(7, "0"), self.summary)
Expand Down
28 changes: 17 additions & 11 deletions did/plugins/github.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,20 +110,26 @@ def search(self, query):
class Issue(object):
""" GitHub Issue """

def __init__(self, data):
def __init__(self, data, parent):
self.data = data
self.title = data["title"]
matched = re.search(
r"/repos/([^/]+)/([^/]+)/issues/(\d+)", data["url"])
self.owner = matched.groups()[0]
self.project = matched.groups()[1]
self.id = matched.groups()[2]
self.options = parent.options

def __str__(self):
""" String representation """
return "{0}/{1}#{2} - {3}".format(
self.owner, self.project,
str(self.id).zfill(PADDING), self.data["title"])
if self.options.format == "markdown":
return "[{0}/{1}#{2}]({3}) - {4}".format(
self.owner, self.project,
str(self.id), self.data["html_url"], self.data["title"].strip())
else:
return "{0}/{1}#{2} - {3}".format(
self.owner, self.project,
str(self.id).zfill(PADDING), self.data["title"])


# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Expand All @@ -139,7 +145,7 @@ def fetch(self):
self.user.login, self.options.since, self.options.until)
query += "+type:issue"
self.stats = [
Issue(issue) for issue in self.parent.github.search(query)]
Issue(issue, self.parent) for issue in self.parent.github.search(query)]


class IssuesClosed(Stats):
Expand All @@ -151,7 +157,7 @@ def fetch(self):
self.user.login, self.options.since, self.options.until)
query += "+type:issue"
self.stats = [
Issue(issue) for issue in self.parent.github.search(query)]
Issue(issue, self.parent) for issue in self.parent.github.search(query)]


class IssueCommented(Stats):
Expand All @@ -163,7 +169,7 @@ def fetch(self):
self.user.login, self.options.since, self.options.until)
query += "+type:issue"
self.stats = [
Issue(issue) for issue in self.parent.github.search(query)]
Issue(issue, self.parent) for issue in self.parent.github.search(query)]


class PullRequestsCreated(Stats):
Expand All @@ -176,7 +182,7 @@ def fetch(self):
self.user.login, self.options.since, self.options.until)
query += "+type:pr"
self.stats = [
Issue(issue) for issue in self.parent.github.search(query)]
Issue(issue, self.parent) for issue in self.parent.github.search(query)]


class PullRequestsCommented(Stats):
Expand All @@ -189,7 +195,7 @@ def fetch(self):
self.user.login, self.options.since, self.options.until)
query += "+type:pr"
self.stats = [
Issue(issue) for issue in self.parent.github.search(query)]
Issue(issue, self.parent) for issue in self.parent.github.search(query)]


class PullRequestsClosed(Stats):
Expand All @@ -202,7 +208,7 @@ def fetch(self):
self.user.login, self.options.since, self.options.until)
query += "+type:pr"
self.stats = [
Issue(issue) for issue in self.parent.github.search(query)]
Issue(issue, self.parent) for issue in self.parent.github.search(query)]


class PullRequestsReviewed(Stats):
Expand All @@ -215,7 +221,7 @@ def fetch(self):
self.user.login, self.options.since, self.options.until)
query += "+type:pr"
self.stats = [
Issue(issue) for issue in self.parent.github.search(query)]
Issue(issue, self.parent) for issue in self.parent.github.search(query)]


# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Expand Down
38 changes: 26 additions & 12 deletions did/plugins/gitlab.py
Original file line number Diff line number Diff line change
Expand Up @@ -163,9 +163,10 @@ def search(self, user, since, until, target_type, action_name):
class Issue(object):
""" GitLab Issue """

def __init__(self, data, gitlabapi):
def __init__(self, data, parent):
self.parent = parent
self.data = data
self.gitlabapi = gitlabapi
self.gitlabapi = parent.gitlab
self.project = self.gitlabapi.get_project(data['project_id'])
self.id = self.iid()
self.title = data['target_title']
Expand All @@ -176,9 +177,22 @@ def iid(self):

def __str__(self):
""" String representation """
return "{0}#{1} - {2}".format(
self.project['path_with_namespace'],
str(self.id).zfill(PADDING), self.title)
if self.parent.options.format == "markdown":
endpoint = "merge_requests"
if self.data['target_type'] == 'Issue' or (
self.data['target_type'] == 'Note'
and self.data['note']['noteable_type'] == 'Issue'
):
endpoint = "issues"
return "[{1}#{3}]({0}/{1}/-/{2}/{3}) - {4}".format(
self.gitlabapi.url,
self.project['path_with_namespace'],
endpoint,
str(self.id), self.title)
else:
return "{0}#{1} - {2}".format(
self.project['path_with_namespace'],
str(self.id).zfill(PADDING), self.title)


class MergeRequest(Issue):
Expand Down Expand Up @@ -223,7 +237,7 @@ def fetch(self):
self.user.login, self.options.since, self.options.until,
'Issue', 'opened')
self.stats = [
Issue(issue, self.parent.gitlab)
Issue(issue, self.parent)
for issue in results]


Expand All @@ -237,7 +251,7 @@ def fetch(self):
self.user.login, self.options.since, self.options.until,
'Note', 'commented on')
self.stats = [
Note(issue, self.parent.gitlab)
Note(issue, self.parent)
for issue in results
if issue['note']['noteable_type'] == 'Issue']

Expand All @@ -252,7 +266,7 @@ def fetch(self):
self.user.login, self.options.since, self.options.until,
'Issue', 'closed')
self.stats = [
Issue(issue, self.parent.gitlab)
Issue(issue, self.parent)
for issue in results]


Expand All @@ -266,7 +280,7 @@ def fetch(self):
self.user.login, self.options.since, self.options.until,
'MergeRequest', 'opened')
self.stats = [
MergeRequest(mr, self.parent.gitlab)
MergeRequest(mr, self.parent)
for mr in results]


Expand All @@ -280,7 +294,7 @@ def fetch(self):
self.user.login, self.options.since, self.options.until,
'Note', 'commented on')
self.stats = [
Note(issue, self.parent.gitlab)
Note(issue, self.parent)
for issue in results
if issue['note']['noteable_type'] == 'MergeRequest']

Expand All @@ -295,7 +309,7 @@ def fetch(self):
self.user.login, self.options.since, self.options.until,
'MergeRequest', 'accepted')
self.stats = [
MergeRequest(mr, self.parent.gitlab)
MergeRequest(mr, self.parent)
for mr in results]


Expand All @@ -309,7 +323,7 @@ def fetch(self):
self.user.login, self.options.since, self.options.until,
'MergeRequest', 'approved')
self.stats = [
MergeRequest(mr, self.parent.gitlab)
MergeRequest(mr, self.parent)
for mr in results]


Expand Down
20 changes: 16 additions & 4 deletions did/plugins/jira.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,23 +112,32 @@
class Issue(object):
""" Jira issue investigator """

def __init__(self, issue=None, prefix=None):
def __init__(self, issue=None, parent=None):
""" Initialize issue """
if issue is None:
return
self.parent = parent
self.options = parent.options
self.issue = issue
self.key = issue["key"]
self.summary = issue["fields"]["summary"]
self.comments = issue["fields"]["comment"]["comments"]
matched = re.match(r"(\w+)-(\d+)", self.key)
self.identifier = matched.groups()[1]
if prefix is not None:
self.prefix = prefix
if parent.prefix is not None:
self.prefix = parent.prefix
else:
self.prefix = matched.groups()[0]

def __str__(self):
""" Jira key and summary for displaying """
if self.options.format == "markdown":
return "[{0}-{1}]({2}) - {3}".format(
self.prefix,
self.identifier,
f"{self.parent.url}/browse/{self.issue['key']}",
self.summary
)
return "{0}-{1} - {2}".format(
self.prefix, self.identifier, self.summary)

Expand Down Expand Up @@ -168,7 +177,10 @@ def search(query, stats):
if len(issues) >= data["total"]:
break
# Return the list of issue objects
return [Issue(issue, prefix=stats.parent.prefix) for issue in issues]
return [
Issue(issue, parent=stats.parent)
for issue in issues
]

def updated(self, user, options):
""" True if the issue was commented by given user """
Expand Down
2 changes: 2 additions & 0 deletions did/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,8 @@ def item(text, level=0, options=None):
return
# Four space for each level, additional space for wiki format
indent = level * 4
if options.format == "markdown":
indent = level * 2
if options.format == "wiki" and level == 0:
indent = 1
# Shorten the text if necessary to match the desired maximum width
Expand Down
4 changes: 3 additions & 1 deletion docs/examples.rst
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,9 @@ corresponding option groups for each of them::
--footer All above

Format:
--format FORMAT Output style, possible values: text (default) or wiki
Format:
--format {text,markdown,wiki}
Output style, default: text
--width WIDTH Maximum width of the report output (default: 79)
--brief Show brief summary only, do not list individual items
--verbose Include more details (like modified git directories)
Expand Down
Loading