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

results: Add support for --format for default text mode #1580

Merged
141 changes: 141 additions & 0 deletions behave/features/results.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
Feature: `osc results` command


Scenario: Run `osc results` with no arguments
When I execute osc with args "results"
Then the exit code is 2
And stderr is
"""
No project given
"""


Scenario: Run `osc results <project>/<package>`
When I execute osc with args "results test:factory/multibuild-pkg"
Then stdout is
"""
standard x86_64 multibuild-pkg disabled
standard x86_64 multibuild-pkg:flavor1 disabled
standard x86_64 multibuild-pkg:flavor2 disabled
standard i586 multibuild-pkg disabled
standard i586 multibuild-pkg:flavor1 disabled
standard i586 multibuild-pkg:flavor2 disabled
"""


Scenario: Run `osc results` from a package checkout
Given I set working directory to "{context.osc.temp}"
And I execute osc with args "checkout test:factory/multibuild-pkg"
And I set working directory to "{context.osc.temp}/test:factory/multibuild-pkg"
When I execute osc with args "results"
Then stdout is
"""
standard x86_64 multibuild-pkg disabled
standard x86_64 multibuild-pkg:flavor1 disabled
standard x86_64 multibuild-pkg:flavor2 disabled
standard i586 multibuild-pkg disabled
standard i586 multibuild-pkg:flavor1 disabled
standard i586 multibuild-pkg:flavor2 disabled
"""


Scenario: Run `osc results <project>/<package>`, no multibuild flavors
When I execute osc with args "results test:factory/multibuild-pkg --no-multibuild"
Then stdout is
"""
standard x86_64 multibuild-pkg disabled
standard i586 multibuild-pkg disabled
"""


Scenario: Run `osc results` from a package checkout, multibuild flavor specified
Given I set working directory to "{context.osc.temp}"
And I execute osc with args "checkout test:factory/multibuild-pkg"
And I set working directory to "{context.osc.temp}/test:factory/multibuild-pkg"
When I execute osc with args "results -M flavor1"
Then stdout is
"""
standard x86_64 multibuild-pkg:flavor1 disabled
standard i586 multibuild-pkg:flavor1 disabled
"""

Scenario: Run `osc results <project>/<package>`, specified output format
When I execute osc with args "results test:factory/multibuild-pkg --format='%(repository)s|%(arch)s|%(package)s|%(code)s'"
Then stdout is
"""
standard|x86_64|multibuild-pkg|disabled
standard|x86_64|multibuild-pkg:flavor1|disabled
standard|x86_64|multibuild-pkg:flavor2|disabled
standard|i586|multibuild-pkg|disabled
standard|i586|multibuild-pkg:flavor1|disabled
standard|i586|multibuild-pkg:flavor2|disabled
"""


Scenario: Run `osc results <project>/<package>`, csv output
When I execute osc with args "results test:factory/multibuild-pkg --csv"
Then stdout matches
"""
"standard","x86_64","multibuild-pkg","publish.*","False","disabled",""
"standard","x86_64","multibuild-pkg:flavor1","publish.*","False","disabled",""
"standard","x86_64","multibuild-pkg:flavor2","publish.*","False","disabled",""
"standard","i586","multibuild-pkg","publish.*","False","disabled",""
"standard","i586","multibuild-pkg:flavor1","publish.*","False","disabled",""
"standard","i586","multibuild-pkg:flavor2","publish.*","False","disabled",""
"""


Scenario: Run `osc results <project>/<package>`, csv output, multibuild flavor specified
When I execute osc with args "results test:factory/multibuild-pkg --csv -M flavor1"
Then stdout matches
"""
"standard","x86_64","multibuild-pkg:flavor1","publish.*","False","disabled",""
"standard","i586","multibuild-pkg:flavor1","publish.*","False","disabled",""
"""


Scenario: Run `osc results <project>/<package>`, csv output, specified output format (columns)
When I execute osc with args "results test:factory/multibuild-pkg --csv --format='repository,arch,package,code'"
Then stdout is
"""
"standard","x86_64","multibuild-pkg","disabled"
"standard","x86_64","multibuild-pkg:flavor1","disabled"
"standard","x86_64","multibuild-pkg:flavor2","disabled"
"standard","i586","multibuild-pkg","disabled"
"standard","i586","multibuild-pkg:flavor1","disabled"
"standard","i586","multibuild-pkg:flavor2","disabled"
"""


Scenario: Run `osc results <project>/<package>`, xml output
When I execute osc with args "results test:factory/multibuild-pkg --xml"
Then stdout matches
"""
<resultlist state=".*">
<result project="test:factory" repository="standard" arch="x86_64" code="publish.*" state="publish.*">
<status package="multibuild-pkg" code="disabled"/>
<status package="multibuild-pkg:flavor1" code="disabled"/>
<status package="multibuild-pkg:flavor2" code="disabled"/>
</result>
<result project="test:factory" repository="standard" arch="i586" code="publish.*" state="publish.*">
<status package="multibuild-pkg" code="disabled"/>
<status package="multibuild-pkg:flavor1" code="disabled"/>
<status package="multibuild-pkg:flavor2" code="disabled"/>
</result>
</resultlist>
"""


Scenario: Run `osc results <project>/<package>`, xml output, multibuild flavor specified
When I execute osc with args "results test:factory/multibuild-pkg --xml -M flavor1"
Then stdout matches
"""
<resultlist state=".*">
<result project="test:factory" repository="standard" arch="x86_64" code="publish.*" state="publish.*">
<status package="multibuild-pkg:flavor1" code="disabled" />
</result>
<result project="test:factory" repository="standard" arch="i586" code="publish.*" state="publish.*">
<status package="multibuild-pkg:flavor1" code="disabled" />
</result>
</resultlist>
"""
38 changes: 34 additions & 4 deletions osc/commandline.py
Original file line number Diff line number Diff line change
Expand Up @@ -6054,8 +6054,11 @@ def do_rremove(self, subcmd, opts):
help='generate output in XML (former results_meta)')
@cmdln.option('', '--csv', action='store_true', default=False,
help='generate output in CSV format')
@cmdln.option('', '--format', default='%(repository)s|%(arch)s|%(state)s|%(dirty)s|%(code)s|%(details)s',
help='format string for csv output')
@cmdln.option('', '--format', default=None,
help="Change the format of the text (default) or csv output. Not supported for xml output.\n"
"Supported fields: project, package, repository, arch, state, dirty, code, details.\n"
"Text output format requires using the field names in form of named fields for string interpolation: ``%%(field)s``.\n"
"CSV output format requires field names separated with commas.")
@cmdln.option('--show-excluded', action='store_true',
help='show repos that are excluded for this package')
def do_results(self, subcmd, opts, *args):
Expand Down Expand Up @@ -6090,6 +6093,12 @@ def do_results(self, subcmd, opts, *args):
if opts.failed and opts.status_filter:
raise oscerr.WrongArgs('-s and -f cannot be used together')

if opts.multibuild_package and opts.no_multibuild:
self.argparser.error("-M/--multibuild-package and --no-multibuild are mutually exclusive")

if opts.xml and opts.format:
self.argparser.error("--xml and --format are mutually exclusive")

if opts.failed:
opts.status_filter = 'failed'
opts.brief = True
Expand Down Expand Up @@ -6123,12 +6132,33 @@ def do_results(self, subcmd, opts, *args):
print(decode_it(xml), end='')
else:
# csv formatting
results = [r for r, _ in result_xml_to_dicts(xml)]
print('\n'.join(format_results(results, opts.format)))
if opts.format is None:
columns = ["repository", "arch", "package", "state", "dirty", "code", "details"]
else:
# split columns by colon, semicolon or pipe
columns = opts.format.split(",")

supported_columns = ["project", "package", "repository", "arch", "state", "dirty", "code", "details"]
unknown_columns = sorted(set(columns) - set(supported_columns))

if unknown_columns:
self.argparser.error(f"Unknown format fields: {''.join(unknown_columns)}")

f = io.StringIO()
writer = csv.writer(f, dialect="unix")

rows = [r for r, _ in result_xml_to_dicts(xml)]
for row in rows:
writer.writerow([row[i] for i in columns])

f.seek(0)
print(f.read(), end="")

else:
kwargs['verbose'] = opts.verbose
kwargs['wait'] = opts.watch
kwargs['printJoin'] = '\n'
kwargs['format'] = opts.format
get_results(**kwargs)

# WARNING: this function is also called by do_results. You need to set a default there
Expand Down
41 changes: 33 additions & 8 deletions osc/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -4101,8 +4101,9 @@ def get_results(apiurl: str, project: str, package: str, verbose=False, printJoi
# hmm the function name is a bit too generic - something like
# get_package_results_human would be better, but this would break the existing
# api (unless we keep get_results around as well)...
result_line_templ = '%(rep)-20s %(arch)-10s %(status)s'
result_line_mb_templ = '%(rep)-20s %(arch)-10s %(pkg)-30s %(status)s'
format = kwargs.pop('format')
if format is None:
format = '%(rep)-20s %(arch)-10s %(pkg)-30s %(status)s'
r = []
printed = False
multibuild_packages = kwargs.pop('multibuild_packages', [])
Expand Down Expand Up @@ -4145,10 +4146,7 @@ def get_results(apiurl: str, project: str, package: str, verbose=False, printJoi
# of the repository if the result is already prefiltered by the backend. So we need
# to filter out the repository states.
if code_filter is None or code_filter == res['code']:
if is_multi:
r.append(result_line_mb_templ % res)
else:
r.append(result_line_templ % res)
r.append(format % res)

if printJoin:
if printed:
Expand All @@ -4159,9 +4157,9 @@ def get_results(apiurl: str, project: str, package: str, verbose=False, printJoi
return r


def get_package_results(apiurl: str, project: str, package: Optional[str] = None, wait=False, *args, **kwargs):
def get_package_results(apiurl: str, project: str, package: Optional[str] = None, wait=False, multibuild_packages: Optional[List[str]] = None, *args, **kwargs):
"""generator that returns a the package results as an xml structure"""
xml = ''
xml = b''
waiting_states = ('blocked', 'scheduled', 'dispatching', 'building',
'signing', 'finished')
while True:
Expand Down Expand Up @@ -4194,6 +4192,33 @@ def get_package_results(apiurl: str, project: str, package: Optional[str] = None
waiting = True
break

# filter the result according to the specified multibuild_packages (flavors)
if multibuild_packages:
for result in list(root):
for status in list(result):
package = status.attrib["package"]
package_flavor = package.rsplit(":", 1)

# package has flavor, check if the flavor is in multibuild_packages
flavor_match = len(package_flavor) == 2 and package_flavor[1] in multibuild_packages

# package nas no flavor, check if "" is in multibuild_packages
no_flavor_match = len(package_flavor) == 1 and "" in multibuild_packages

if not flavor_match and not no_flavor_match:
# package doesn't match multibuild_packages, remove the corresponding <status> from <result>
result.remove(status)

# remove empty <result> from <resultlist>
if len(result) == 0:
root.remove(result)

if len(root) == 0:
break

xmlindent(root)
xml = ET.tostring(root)

if not wait or not waiting:
break
else:
Expand Down
Loading