Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
9 changes: 9 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,20 @@ jobs:
python3 -m pip install -U wheel setuptools
python3 -m pip install sphinx
python3 -m pip install ".[test]"
python3 -m pip install ruff

- name: Tests
run: |
python -W once -m testtools.run testrepository.tests.test_suite

- name: Lint
run: |
ruff check .

- name: Check formatting
run: |
ruff format --check .

success:
needs: build
runs-on: ubuntu-latest
Expand Down
2 changes: 1 addition & 1 deletion .testr.conf
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[DEFAULT]
test_command=${PYTHON:-python} -m subunit.run $LISTOPT $IDOPTION testrepository.tests.test_suite
test_command=${PYTHON:-python3} -m subunit.run $LISTOPT $IDOPTION testrepository.tests.test_suite
test_id_option=--load-list $IDFILE
test_list_option=--list
;filter_tags=worker-0
2 changes: 1 addition & 1 deletion testr
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python3
#
# Copyright (c) 2009 Testrepository Contributors
#
Expand Down
7 changes: 5 additions & 2 deletions testrepository/__init__.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
#
# Copyright (c) 2009 Testrepository Contributors
#
#
# Licensed under either the Apache License, Version 2.0 or the BSD 3-clause
# license at the users choice. A copy of both licenses are available in the
# project source as Apache-2.0 and BSD. You may not use this file except in
# compliance with one of these two licences.
#
#
# Unless required by applicable law or agreed to in writing, software
# distributed under these licenses is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
Expand All @@ -22,6 +22,9 @@
The tests package contains tests and test specific support code.
"""

__all__ = ["__version__"]


try:
# If setuptools_scm is installed (e.g. in a development environment with
# an editable install), then use it to determine the version dynamically.
Expand Down
28 changes: 14 additions & 14 deletions testrepository/arguments/__init__.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
#
# Copyright (c) 2010 Testrepository Contributors
#
#
# Licensed under either the Apache License, Version 2.0 or the BSD 3-clause
# license at the users choice. A copy of both licenses are available in the
# project source as Apache-2.0 and BSD. You may not use this file except in
# compliance with one of these two licences.
#
#
# Unless required by applicable law or agreed to in writing, software
# distributed under these licenses is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
Expand Down Expand Up @@ -61,19 +61,18 @@ def __init__(self, name, min=1, max=1):
def summary(self):
"""Get a regex-like summary of this argument."""
result = self.name
if (self.minimum_count == self.maximum_count and
self.minimum_count == 1):
return result
if self.minimum_count == self.maximum_count and self.minimum_count == 1:
return result
minmax = (self.minimum_count, self.maximum_count)
if minmax == (0, 1):
return result + '?'
return result + "?"
if minmax == (1, None):
return result + '+'
return result + "+"
if minmax == (0, None):
return result + '*'
if minmax[1] == None:
minmax = (minmax[0], '')
return result + '{%s,%s}' % minmax
return result + "*"
if minmax[1] is None:
minmax = (minmax[0], "")
return result + "{%s,%s}" % minmax

def parse(self, argv):
"""Evaluate arguments in argv.
Expand All @@ -87,7 +86,8 @@ def parse(self, argv):
result = []
error = None
while len(argv) > count and (
self.maximum_count is None or count < self.maximum_count):
self.maximum_count is None or count < self.maximum_count
):
arg = argv[count]
count += 1
try:
Expand All @@ -100,13 +100,13 @@ def parse(self, argv):
if count < self.minimum_count:
if error is not None:
raise error[1].with_traceback(error[2])
raise ValueError('not enough arguments present/matched in %s' % argv)
raise ValueError("not enough arguments present/matched in %s" % argv)
del argv[:count]
return result

def _parse_one(self, arg):
"""Parse a single argument.

:param arg: An arg from an argv.
:result: The parsed argument.
:raises ValueError: If the arg cannot be parsed/validated.
Expand Down
6 changes: 3 additions & 3 deletions testrepository/arguments/command.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
#
# Copyright (c) 2010 Testrepository Contributors
#
#
# Licensed under either the Apache License, Version 2.0 or the BSD 3-clause
# license at the users choice. A copy of both licenses are available in the
# project source as Apache-2.0 and BSD. You may not use this file except in
# compliance with one of these two licences.
#
#
# Unless required by applicable law or agreed to in writing, software
# distributed under these licenses is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
Expand All @@ -19,10 +19,10 @@


class CustomError(ValueError):

def __str__(self):
return self.args[0]


class CommandArgument(AbstractArgument):
"""An argument that looks up a command."""

Expand Down
10 changes: 5 additions & 5 deletions testrepository/arguments/doubledash.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
#
# Copyright (c) 2012 Testrepository Contributors
#
#
# Licensed under either the Apache License, Version 2.0 or the BSD 3-clause
# license at the users choice. A copy of both licenses are available in the
# project source as Apache-2.0 and BSD. You may not use this file except in
# compliance with one of these two licences.
#
#
# Unless required by applicable law or agreed to in writing, software
# distributed under these licenses is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
Expand All @@ -21,9 +21,9 @@ class DoubledashArgument(AbstractArgument):
"""An argument that captures '--'."""

def __init__(self):
super(DoubledashArgument, self).__init__('doubledash', min=0)
super(DoubledashArgument, self).__init__("doubledash", min=0)

def _parse_one(self, arg):
if arg != '--':
raise ValueError('not a doubledash %r' % (arg,))
if arg != "--":
raise ValueError("not a doubledash %r" % (arg,))
return arg
10 changes: 5 additions & 5 deletions testrepository/arguments/path.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
#
# Copyright (c) 2012 Testrepository Contributors
#
#
# Licensed under either the Apache License, Version 2.0 or the BSD 3-clause
# license at the users choice. A copy of both licenses are available in the
# project source as Apache-2.0 and BSD. You may not use this file except in
# compliance with one of these two licences.
#
#
# Unless required by applicable law or agreed to in writing, software
# distributed under these licenses is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
Expand All @@ -23,8 +23,8 @@ class ExistingPathArgument(AbstractArgument):
"""An argument that stores a string verbatim."""

def _parse_one(self, arg):
if arg == '--':
raise ValueError('-- is not a valid argument')
if arg == "--":
raise ValueError("-- is not a valid argument")
if not os.path.exists(arg):
raise ValueError('No such path %r' % (arg,))
raise ValueError("No such path %r" % (arg,))
return arg
8 changes: 4 additions & 4 deletions testrepository/arguments/string.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
#
# Copyright (c) 2010 Testrepository Contributors
#
#
# Licensed under either the Apache License, Version 2.0 or the BSD 3-clause
# license at the users choice. A copy of both licenses are available in the
# project source as Apache-2.0 and BSD. You may not use this file except in
# compliance with one of these two licences.
#
#
# Unless required by applicable law or agreed to in writing, software
# distributed under these licenses is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
Expand All @@ -21,6 +21,6 @@ class StringArgument(AbstractArgument):
"""An argument that stores a string verbatim."""

def _parse_one(self, arg):
if arg == '--':
raise ValueError('-- is not a valid argument')
if arg == "--":
raise ValueError("-- is not a valid argument")
return arg
49 changes: 25 additions & 24 deletions testrepository/commands/__init__.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
#
# Copyright (c) 2009, 2010 Testrepository Contributors
#
#
# Licensed under either the Apache License, Version 2.0 or the BSD 3-clause
# license at the users choice. A copy of both licenses are available in the
# project source as Apache-2.0 and BSD. You may not use this file except in
# compliance with one of these two licences.
#
#
# Unless required by applicable law or agreed to in writing, software
# distributed under these licenses is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
Expand All @@ -19,7 +19,7 @@

Actual commands can be found in testrepository.commands.$commandname.

For example, testrepository.commands.init is the init command name, and
For example, testrepository.commands.init is the init command name, and
testrepository.command.show_stats would be the show-stats command (if one
existed). The Command discovery logic looks for a class in the module with
the same name - e.g. tesrepository.commands.init.init would be the class.
Expand All @@ -37,13 +37,12 @@
import os
import sys

import subunit

from testrepository.repository import file


def _find_command(cmd_name):
orig_cmd_name = cmd_name
cmd_name = cmd_name.replace('-', '_')
cmd_name = cmd_name.replace("-", "_")
classname = "%s" % cmd_name
modname = "testrepository.commands.%s" % cmd_name
try:
Expand All @@ -54,8 +53,9 @@ def _find_command(cmd_name):
if result is None:
raise KeyError(
"Malformed command module - no command class %s found in module %s."
% (classname, modname))
if getattr(result, 'name', None) is None:
% (classname, modname)
)
if getattr(result, "name", None) is None:
# Store the name for the common case of name == lookup path.
result.name = orig_cmd_name
return result
Expand All @@ -69,13 +69,13 @@ def iter_commands():
# For now, only support regular installs. TODO: support zip, eggs.
for filename in os.listdir(path):
base = os.path.basename(filename)
if base.startswith('.'):
if base.startswith("."):
continue
name = base.split('.', 1)[0]
name = name.replace('_', '-')
name = base.split(".", 1)[0]
name = name.replace("_", "-")
names.add(name)
names.discard('--init--')
names.discard('--pycache--')
names.discard("--init--")
names.discard("--pycache--")
names = sorted(names)
for name in names:
yield _find_command(name)
Expand All @@ -91,7 +91,7 @@ class Command(object):
:ivar ui: a UI object which is responsible for brokering the command
arguments, input and output. There is no default ui, it must be
passed to the constructor.

:ivar repository_factory: a repository factory which is used to create or
open repositories. The default repository factory is suitable for
use in the command line tool.
Expand Down Expand Up @@ -129,7 +129,7 @@ def execute(self):
This interrogates the UI to ensure that arguments and options are
supplied, performs any validation for the same that the command needs
and finally calls run() to perform the command. Most commands should
not need to override this method, and any user wanting to run a
not need to override this method, and any user wanting to run a
command should call this method.

This is a synchronous method, and basically just a helper. GUI's or
Expand All @@ -150,7 +150,7 @@ def execute(self):

@classmethod
def get_summary(klass):
docs = klass.__doc__.split('\n')
docs = klass.__doc__.split("\n")
return docs[0]

def _init(self):
Expand All @@ -173,15 +173,16 @@ def run_argv(argv, stdin, stdout, stderr):
cmd_name = None
cmd_args = argv[1:]
for arg in argv[1:]:
if not arg.startswith('-'):
if not arg.startswith("-"):
cmd_name = arg
break
if cmd_name is None:
cmd_name = 'help'
cmd_args = ['help']
cmd_name = "help"
cmd_args = ["help"]
cmd_args.remove(cmd_name)
cmdclass = _find_command(cmd_name)
from testrepository.ui import cli

ui = cli.UI(cmd_args, stdin, stdout, stderr)
cmd = cmdclass(ui)
result = cmd.execute()
Expand All @@ -203,11 +204,11 @@ def get_command_parser(cmd):
parser = OptionParser()
for option in cmd.options:
parser.add_option(option)
usage = '%%prog %(cmd)s [options] %(args)s\n\n%(help)s' % {
'args': ' '.join(map(lambda x:x.summary(), cmd.args)),
'cmd': getattr(cmd, 'name', cmd),
'help': getdoc(cmd),
}
usage = "%%prog %(cmd)s [options] %(args)s\n\n%(help)s" % {
"args": " ".join(map(lambda x: x.summary(), cmd.args)),
"cmd": getattr(cmd, "name", cmd),
"help": getdoc(cmd),
}
parser.set_usage(usage)
return parser

Expand Down
7 changes: 4 additions & 3 deletions testrepository/commands/commands.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
#
# Copyright (c) 2010 Testrepository Contributors
#
#
# Licensed under either the Apache License, Version 2.0 or the BSD 3-clause
# license at the users choice. A copy of both licenses are available in the
# project source as Apache-2.0 and BSD. You may not use this file except in
# compliance with one of these two licences.
#
#
# Unless required by applicable law or agreed to in writing, software
# distributed under these licenses is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
Expand All @@ -16,11 +16,12 @@

import testrepository.commands


class commands(testrepository.commands.Command):
"""List available commands."""

def run(self):
table = [('command', 'description')]
table = [("command", "description")]
for command in testrepository.commands.iter_commands():
table.append((command.name, command.get_summary()))
self.ui.output_table(table)
Loading