move commands into their own package

Separate the CLI command modules from the support modules.

Change-Id: Ie47bd36ebd6fa9287ca6988cc201f2c1879fd897
This commit is contained in:
Doug Hellmann 2015-07-15 21:29:04 +00:00
parent 6210a4aa41
commit b5e5387067
6 changed files with 192 additions and 150 deletions

View File

View File

@ -0,0 +1,51 @@
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from __future__ import print_function
import argparse
from releasetools import governance
def main():
parser = argparse.ArgumentParser()
parser.add_argument(
'--project-list',
default=governance.PROJECTS_LIST,
help='a URL pointing to a projects.yaml file, defaults to %(default)s',
)
parser.add_argument(
'--code-only',
default=False,
action='store_true',
help='only show repositories containing code, not docs or templates',
)
parser.add_argument(
'--team',
help='the name of the project team, such as "Nova" or "Oslo"',
)
parser.add_argument(
'--tag',
action='append',
default=[],
help='the name of a tag, such as "release:managed"',
)
args = parser.parse_args()
repos = governance.get_repositories(
args.team,
args.tag,
code_only=args.code_only,
)
for repo in repos:
print(repo['repo'])

View File

@ -0,0 +1,122 @@
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import argparse
import os
from releasetools import release_notes
def main():
parser = argparse.ArgumentParser(
prog='release_notes',
description=__doc__,
formatter_class=argparse.RawDescriptionHelpFormatter)
parser.add_argument("library", metavar='path', action="store",
help="library directory, for example"
" 'openstack/cliff'",
)
parser.add_argument("start_revision", metavar='revision',
action="store",
help="start revision, for example '1.8.0'",
)
parser.add_argument("end_revision", metavar='revision',
action="store",
nargs='?',
help="end revision, for example '1.9.0'"
" (default: HEAD)",
default="HEAD")
parser.add_argument('--changes-only',
action='store_true',
default=False,
help='List only the change summary, without details',
)
parser.add_argument('--include-pypi-link',
action='store_true',
default=False,
help='include a pypi hyperlink for the library',
)
parser.add_argument("--notable-changes", metavar='path',
action="store",
help="a file containing any notable changes")
parser.add_argument("--skip-requirement-merges",
action='store_true', default=False,
help="skip requirement update commit messages"
" (default: False)")
parser.add_argument("--show-dates",
action='store_true', default=False,
help="show dates in the change log")
parser.add_argument("--series", "-s",
default="",
help="release series name, such as 'kilo'",
)
parser.add_argument("--stable",
default=False,
action='store_true',
help="this is a stable release",
)
email_group = parser.add_argument_group('email settings')
email_group.add_argument(
"--email", "-e",
action='store_true', default=False,
help="output a fully formed email message",
)
email_group.add_argument(
"--email-to",
default="openstack-announce@lists.openstack.org",
help="recipient of the email, defaults to %(default)s",
)
email_group.add_argument(
"--email-reply-to",
default="openstack-dev@lists.openstack.org",
help="follow-up for discussions, defaults to %(default)s",
)
email_group.add_argument(
"--email-from", "--from",
default=os.environ.get('EMAIL', ''),
help="source of the email, defaults to $EMAIL",
)
email_group.add_argument(
"--email-tags",
default="",
help="extra topic tags for email subject, e.g. '[oslo]'",
)
args = parser.parse_args()
library_path = os.path.abspath(args.library)
notable_changes = ''
if args.notable_changes:
with open(args.notable_changes, 'r') as fh:
notable_changes = fh.read().rstrip()
notes = release_notes.generate_release_notes(
library=args.library,
library_path=library_path,
start_revision=args.start_revision,
end_revision=args.end_revision,
show_dates=args.show_dates,
skip_requirement_merges=args.skip_requirement_merges,
notable_changes=notable_changes,
is_stable=args.stable,
series=args.series,
email=args.email,
email_from=args.email_from,
email_to=args.email_to,
email_reply_to=args.email_reply_to,
email_tags=args.email_tags,
include_pypi_link=args.include_pypi_link,
changes_only=args.changes_only,
)
print(notes)
return 0

View File

@ -1,5 +1,3 @@
#!/usr/bin/env python
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
@ -15,9 +13,6 @@
"""Work with the governance repository.
"""
from __future__ import print_function
import argparse
import itertools
import requests
import yaml
@ -37,7 +32,21 @@ def get_team_data(url=PROJECTS_LIST):
return yaml.load(r.text)
def get_repositories(team, tags, code_only=False, url=PROJECTS_LIST):
def get_repo_owner(repo_name):
"""Return the name of the team that owns the repository.
:param repo_name: Long name of the repository, such as 'openstack/nova'.
"""
team_data = get_team_data()
for team, info in team_data.items():
for project in info.get('projects', []):
if project['repo'] == repo_name:
return team
raise ValueError('Repository %s not found in governance list' % repo_name)
def get_repositories(team, tags, code_only=False):
"""Return a sequence of repositories, possibly filtered.
:param team: The name of the team owning the repositories. Can be
@ -48,7 +57,7 @@ def get_repositories(team, tags, code_only=False, url=PROJECTS_LIST):
repositories (ignoring specs and cookiecutter templates).
"""
team_data = get_team_data(url)
team_data = get_team_data()
if team is not None:
if team not in team_data:
@ -77,33 +86,3 @@ def get_repositories(team, tags, code_only=False, url=PROJECTS_LIST):
)
return list(projects)
def list_repos():
parser = argparse.ArgumentParser()
parser.add_argument(
'--project-list',
default=PROJECTS_LIST,
help='a URL pointing to a projects.yaml file, defaults to %(default)s',
)
parser.add_argument(
'--code-only',
default=False,
action='store_true',
help='only show repositories containing code, not docs or templates',
)
parser.add_argument(
'--team',
help='the name of the project team, such as "Nova" or "Oslo"',
)
parser.add_argument(
'--tag',
action='append',
default=[],
help='the name of a tag, such as "release:managed"',
)
args = parser.parse_args()
repos = get_repositories(args.team, args.tag, code_only=args.code_only)
for repo in repos:
print(repo['repo'])

View File

@ -12,7 +12,6 @@
"""Generates a standard set of release notes for a repository."""
import argparse
import glob
import os
import random
@ -183,112 +182,6 @@ def is_skippable_commit(skip_requirement_merges, line):
line.lower().endswith('updated from global requirements'))
def main():
parser = argparse.ArgumentParser(
prog='release_notes',
description=__doc__,
formatter_class=argparse.RawDescriptionHelpFormatter)
parser.add_argument("library", metavar='path', action="store",
help="library directory, for example"
" 'openstack/cliff'",
)
parser.add_argument("start_revision", metavar='revision',
action="store",
help="start revision, for example '1.8.0'",
)
parser.add_argument("end_revision", metavar='revision',
action="store",
nargs='?',
help="end revision, for example '1.9.0'"
" (default: HEAD)",
default="HEAD")
parser.add_argument('--changes-only',
action='store_true',
default=False,
help='List only the change summary, without details',
)
parser.add_argument('--include-pypi-link',
action='store_true',
default=False,
help='include a pypi hyperlink for the library',
)
parser.add_argument("--notable-changes", metavar='path',
action="store",
help="a file containing any notable changes")
parser.add_argument("--skip-requirement-merges",
action='store_true', default=False,
help="skip requirement update commit messages"
" (default: False)")
parser.add_argument("--show-dates",
action='store_true', default=False,
help="show dates in the change log")
parser.add_argument("--series", "-s",
default="",
help="release series name, such as 'kilo'",
)
parser.add_argument("--stable",
default=False,
action='store_true',
help="this is a stable release",
)
email_group = parser.add_argument_group('email settings')
email_group.add_argument(
"--email", "-e",
action='store_true', default=False,
help="output a fully formed email message",
)
email_group.add_argument(
"--email-to",
default="openstack-announce@lists.openstack.org",
help="recipient of the email, defaults to %(default)s",
)
email_group.add_argument(
"--email-reply-to",
default="openstack-dev@lists.openstack.org",
help="follow-up for discussions, defaults to %(default)s",
)
email_group.add_argument(
"--email-from", "--from",
default=os.environ.get('EMAIL', ''),
help="source of the email, defaults to $EMAIL",
)
email_group.add_argument(
"--email-tags",
default="",
help="extra topic tags for email subject, e.g. '[oslo]'",
)
args = parser.parse_args()
library_path = os.path.abspath(args.library)
notable_changes = ''
if args.notable_changes:
with open(args.notable_changes, 'r') as fh:
notable_changes = fh.read().rstrip()
notes = generate_release_notes(
library=args.library,
library_path=library_path,
start_revision=args.start_revision,
end_revision=args.end_revision,
show_dates=args.show_dates,
skip_requirement_merges=args.skip_requirement_merges,
notable_changes=notable_changes,
is_stable=args.stable,
series=args.series,
email=args.email,
email_from=args.email_from,
email_to=args.email_to,
email_reply_to=args.email_reply_to,
email_tags=args.email_tags,
include_pypi_link=args.include_pypi_link,
changes_only=args.changes_only,
)
print(notes)
return 0
def generate_release_notes(library, library_path,
start_revision, end_revision,
show_dates, skip_requirement_merges,
@ -432,7 +325,3 @@ def generate_release_notes(library, library_path,
response.append(parawrap.fill(header))
response.append(expand_template(CHANGE_RELEASE_TPL, params))
return '\n'.join(response)
if __name__ == '__main__':
sys.exit(main())

View File

@ -20,8 +20,9 @@ classifier =
[files]
packages =
releasetools
releasetools.cmds
[entry_points]
console_scripts =
release-notes = releasetools.release_notes:main
list-repos = releasetools.governance:list_repos
release-notes = releasetools.cmds.release_notes:main
list-repos = releasetools.cmds.list_repos:main