Normalize sort column names
Make --sort-column consistent with --column by normalizing case, whitespace, and spaces in requested column names. Preserve exact-match priority when normalized column names are ambiguous. Closes-bug: #2168826 Change-Id: I9c6a93caa50df47f237b100b5a359c7bacba685c Signed-off-by: t.hosseini <taaahaaa75@gmail.com>
This commit is contained in:
1 parent
89efc71e36
commit
7b8e5dd270
4 files changed
+92
-10
No files matched your search
+10
-5
@@ -135,12 +135,13 @@ class DisplayCommandBase(
|
||||
if not parsed_args.columns:
|
||||
return list(column_names), None
|
||||
|
||||
def normalize_column(column_name: str) -> str:
|
||||
return column_name.lower().strip().replace(' ', '_')
|
||||
|
||||
requested_columns = [normalize_column(c) for c in parsed_args.columns]
|
||||
requested_columns = [
|
||||
self._normalize_column_name(c) for c in parsed_args.columns
|
||||
]
|
||||
columns_to_include = [
|
||||
c for c in column_names if normalize_column(c) in requested_columns
|
||||
c
|
||||
for c in column_names
|
||||
if self._normalize_column_name(c) in requested_columns
|
||||
]
|
||||
if not columns_to_include:
|
||||
raise ValueError(
|
||||
@@ -152,6 +153,10 @@ class DisplayCommandBase(
|
||||
selector = [(c in columns_to_include) for c in column_names]
|
||||
return columns_to_include, selector
|
||||
|
||||
@staticmethod
|
||||
def _normalize_column_name(column_name: str) -> str:
|
||||
return column_name.lower().strip().replace(' ', '_')
|
||||
|
||||
def run(self, parsed_args: argparse.Namespace) -> int:
|
||||
parsed_args = self._run_before_hooks(parsed_args)
|
||||
formatter = self._formatter_plugins[parsed_args.formatter].obj
|
||||
|
||||
+15
-5
@@ -69,7 +69,8 @@ class Lister(
|
||||
help=(
|
||||
'specify the column(s) to sort the data (columns specified '
|
||||
'first have a priority, non-existing columns are ignored), '
|
||||
'can be repeated'
|
||||
'column names are case-insensitive and accept underscores '
|
||||
'for spaces, can be repeated'
|
||||
),
|
||||
)
|
||||
sort_dir_group = group.add_mutually_exclusive_group()
|
||||
@@ -96,11 +97,20 @@ class Lister(
|
||||
data: Iterable[Sequence[Any]],
|
||||
) -> int:
|
||||
if parsed_args.sort_columns and self.need_sort_by_cliff:
|
||||
indexes = [
|
||||
column_names.index(c)
|
||||
for c in parsed_args.sort_columns
|
||||
if c in column_names
|
||||
normalized_column_names = [
|
||||
self._normalize_column_name(c) for c in column_names
|
||||
]
|
||||
indexes = []
|
||||
for column in parsed_args.sort_columns:
|
||||
if column in column_names:
|
||||
indexes.append(column_names.index(column))
|
||||
continue
|
||||
|
||||
normalized_column = self._normalize_column_name(column)
|
||||
if normalized_column in normalized_column_names:
|
||||
indexes.append(
|
||||
normalized_column_names.index(normalized_column)
|
||||
)
|
||||
reverse = parsed_args.sort_direction == 'desc'
|
||||
for index in indexes[::-1]:
|
||||
try:
|
||||
|
||||
@@ -118,6 +118,66 @@ class TestLister(base.TestBase):
|
||||
data = list(args[1])
|
||||
self.assertEqual([['a', 'A'], ['c', 'A'], ['b', 'B']], data)
|
||||
|
||||
def test_sort_by_column_normalized(self):
|
||||
test_lister = ExerciseLister(mock.Mock(), None)
|
||||
parsed_args = mock.Mock()
|
||||
parsed_args.columns = ('Col1', 'Col2')
|
||||
parsed_args.formatter = 'test'
|
||||
parsed_args.sort_columns = ['col2', 'COL1']
|
||||
|
||||
test_lister.run(parsed_args)
|
||||
|
||||
f = test_lister._formatter_plugins['test']
|
||||
assert isinstance(f, FauxFormatter)
|
||||
args = f.args[0]
|
||||
data = list(args[1])
|
||||
self.assertEqual([['a', 'A'], ['c', 'A'], ['b', 'B']], data)
|
||||
|
||||
def test_sort_by_column_normalized_spaces(self):
|
||||
test_lister = ExerciseLister(mock.Mock(), None)
|
||||
parsed_args = mock.Mock()
|
||||
parsed_args.columns = ('Column One', 'Column Two')
|
||||
parsed_args.formatter = 'test'
|
||||
parsed_args.sort_columns = ['column_two', 'column_one']
|
||||
|
||||
test_lister.run(parsed_args)
|
||||
|
||||
f = test_lister._formatter_plugins['test']
|
||||
assert isinstance(f, FauxFormatter)
|
||||
args = f.args[0]
|
||||
data = list(args[1])
|
||||
self.assertEqual([['a', 'A'], ['c', 'A'], ['b', 'B']], data)
|
||||
|
||||
def test_sort_by_column_normalized_whitespace(self):
|
||||
test_lister = ExerciseLister(mock.Mock(), None)
|
||||
parsed_args = mock.Mock()
|
||||
parsed_args.columns = ('Column One', 'Column Two')
|
||||
parsed_args.formatter = 'test'
|
||||
parsed_args.sort_columns = [' column_two ']
|
||||
|
||||
test_lister.run(parsed_args)
|
||||
|
||||
f = test_lister._formatter_plugins['test']
|
||||
assert isinstance(f, FauxFormatter)
|
||||
args = f.args[0]
|
||||
data = list(args[1])
|
||||
self.assertEqual([['a', 'A'], ['c', 'A'], ['b', 'B']], data)
|
||||
|
||||
def test_sort_by_column_exact_match_takes_priority(self):
|
||||
test_lister = ExerciseLister(mock.Mock(), None)
|
||||
parsed_args = mock.Mock()
|
||||
parsed_args.columns = ('Column One', 'column_one')
|
||||
parsed_args.formatter = 'test'
|
||||
parsed_args.sort_columns = ['column_one']
|
||||
|
||||
test_lister.run(parsed_args)
|
||||
|
||||
f = test_lister._formatter_plugins['test']
|
||||
assert isinstance(f, FauxFormatter)
|
||||
args = f.args[0]
|
||||
data = list(args[1])
|
||||
self.assertEqual([['a', 'A'], ['c', 'A'], ['b', 'B']], data)
|
||||
|
||||
def test_sort_by_column_reverse_order(self):
|
||||
test_lister = ExerciseLister(mock.Mock(), None)
|
||||
parsed_args = mock.Mock()
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
---
|
||||
fixes:
|
||||
- |
|
||||
Values passed to ``--sort-column`` are now normalized in the same way as
|
||||
values passed to ``--column``. Sorting is therefore case-insensitive and
|
||||
accepts underscores in place of spaces in column names, including leading
|
||||
or trailing whitespace around the requested name.
|
||||
Reference in new issue
Block a user