Skip to content

Commit

Permalink
Property list determines property order in instance table output
Browse files Browse the repository at this point in the history
Details:

* Specifying a property list (--pl / --propertylist option) on instance commands
  with table output formats now uses the order of properties as specified in the
  property list in the output table, instead of sorting them. (See issue #702)

* Added table output testcases to instance associators and instance references
  commands.

* Added testcases that verify the order is controlled by propertylist options.

Signed-off-by: Andreas Maier <andreas.r.maier@gmx.de>
  • Loading branch information
andy-maier committed Aug 10, 2020
1 parent 3bac9a8 commit 36f37ad
Show file tree
Hide file tree
Showing 4 changed files with 143 additions and 17 deletions.
4 changes: 4 additions & 0 deletions docs/changes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,10 @@ Released: not yet
* Test: Enabled coveralls to run on all Python versions in the Travis CI,
resulting in a combined coverage for all Python versions.

* Specifying a property list (--pl option) on instance commands with table
output formats now uses the order of properties as specified in the property
list in the output table, instead of sorting them. (See issue #702)

**Cleanup**

* Remove unused NocaseList from __common.py
Expand Down
24 changes: 16 additions & 8 deletions pywbemtools/pywbemcli/_cmd_instance.py
Original file line number Diff line number Diff line change
Expand Up @@ -972,14 +972,16 @@ def cmd_instance_get(context, instancename, options):
instancepath = get_instancename(context, instancename, options)

try:
property_list = resolve_propertylist(options['propertylist'])
instance = context.conn.GetInstance(
instancepath,
LocalOnly=options['local_only'],
IncludeQualifiers=options['include_qualifiers'],
IncludeClassOrigin=options['include_classorigin'],
PropertyList=resolve_propertylist(options['propertylist']))
PropertyList=property_list)

display_cim_objects(context, instance, output_fmt)
display_cim_objects(context, instance, output_fmt,
property_list=property_list)

except Error as er:
raise_pywbem_error_exception(er)
Expand Down Expand Up @@ -1140,6 +1142,7 @@ def cmd_instance_enumerate(context, classname, options):
output_fmt = validate_output_format(context.output_format, ['CIM', 'TABLE'])

try:
property_list = resolve_propertylist(options['propertylist'])
if options['names_only']:
results = context.conn.PyWbemcliEnumerateInstancePaths(
ClassName=classname,
Expand All @@ -1158,10 +1161,11 @@ def cmd_instance_enumerate(context, classname, options):
FilterQuery=options['filter_query'],
FilterQueryLanguage=get_filterquerylanguage(options),
MaxObjectCount=context.pull_max_cnt,
PropertyList=resolve_propertylist(options['propertylist']))
PropertyList=property_list)

display_cim_objects(context, results, output_fmt,
summary=options['summary'], sort=True)
summary=options['summary'], sort=True,
property_list=property_list)

except Error as er:
raise_pywbem_error_exception(er)
Expand All @@ -1187,6 +1191,7 @@ def cmd_instance_references(context, instancename, options):
instancepath = get_instancename(context, instancename, options)

try:
property_list = resolve_propertylist(options['propertylist'])
if options['names_only']:
results = context.conn.PyWbemcliReferenceInstancePaths(
instancepath,
Expand All @@ -1205,10 +1210,11 @@ def cmd_instance_references(context, instancename, options):
FilterQuery=options['filter_query'],
FilterQueryLanguage=get_filterquerylanguage(options),
MaxObjectCount=context.pull_max_cnt,
PropertyList=resolve_propertylist(options['propertylist']))
PropertyList=property_list)

display_cim_objects(context, results, output_fmt,
summary=options['summary'], sort=True)
summary=options['summary'], sort=True,
property_list=property_list)

except Error as er:
raise_pywbem_error_exception(er)
Expand All @@ -1231,6 +1237,7 @@ def cmd_instance_associators(context, instancename, options):
instancepath = get_instancename(context, instancename, options)

try:
property_list = resolve_propertylist(options['propertylist'])
if options['names_only']:
results = context.conn.PyWbemcliAssociatorInstancePaths(
instancepath,
Expand All @@ -1253,10 +1260,11 @@ def cmd_instance_associators(context, instancename, options):
FilterQuery=options['filter_query'],
FilterQueryLanguage=get_filterquerylanguage(options),
MaxObjectCount=context.pull_max_cnt,
PropertyList=resolve_propertylist(options['propertylist']))
PropertyList=property_list)

display_cim_objects(context, results, output_fmt,
summary=options['summary'], sort=True)
summary=options['summary'], sort=True,
property_list=property_list)

except Error as er:
raise_pywbem_error_exception(er)
Expand Down
38 changes: 31 additions & 7 deletions pywbemtools/pywbemcli/_common.py
Original file line number Diff line number Diff line change
Expand Up @@ -1001,7 +1001,7 @@ def display_cim_objects_summary(context, objects, output_format):


def display_cim_objects(context, cim_objects, output_format, summary=False,
sort=False):
sort=False, property_list=None):
"""
Display CIM objects in form determined by input parameters.
Expand Down Expand Up @@ -1069,7 +1069,8 @@ def display_cim_objects(context, cim_objects, output_format, summary=False,
if isinstance(cim_objects, (list, tuple)):
# Table format output is processed as a group
if output_format_is_table(output_format):
_print_objects_as_table(cim_objects, output_format, context=context)
_print_objects_as_table(cim_objects, output_format, context=context,
property_list=property_list)
else:
# Call to display each object
for obj in cim_objects:
Expand All @@ -1080,7 +1081,8 @@ def display_cim_objects(context, cim_objects, output_format, summary=False,
object_ = cim_objects
# This allows passing single objects to the table formatter (i.e. not lists)
if output_format_is_table(output_format):
_print_objects_as_table([object_], output_format, context=context)
_print_objects_as_table([object_], output_format, context=context,
property_list=property_list)
elif output_format == 'mof':
try:
click.echo(object_.tomof())
Expand Down Expand Up @@ -1426,7 +1428,8 @@ def _format_instances_as_rows(insts, max_cell_width=DEFAULT_MAX_CELL_WIDTH,


def _print_instances_as_table(insts, table_width, table_format,
include_classes=False, context=None):
include_classes=False, context=None,
property_list=None):
"""
Print the properties of the instances defined in insts as a table where
each row is an instance and each column is a property value.
Expand All @@ -1448,7 +1451,10 @@ def _print_instances_as_table(insts, table_width, table_format,
if not isinstance(inst, CIMInstance):
raise ValueError('Only CIMInstance display allows table output')

prop_names = sorted_prop_names(insts)
if property_list:
prop_names = propertylist_prop_names(insts, property_list)
else:
prop_names = sorted_prop_names(insts)

# Try to estimate max cell width from number of cols
# This allows folding long data. However it is incomplete in
Expand Down Expand Up @@ -1519,7 +1525,24 @@ def sorted_prop_names(insts):
return key_prop_list


def _print_objects_as_table(objects, output_format, context=None):
def propertylist_prop_names(insts, property_list):
"""
Return the originally cased property list, based on the lexical case
in the instances.
If a property name is not in any instance, it is not returned.
"""
prop_list = []
for pname in property_list:
for inst in insts:
if pname in inst:
prop_list.append(inst.properties[pname].name)
break
return prop_list


def _print_objects_as_table(objects, output_format, context=None,
property_list=None):
"""
Call the method for each type of object to print that object type
information as a table.
Expand All @@ -1534,7 +1557,8 @@ def _print_objects_as_table(objects, output_format, context=None):
if objects:
if isinstance(objects[0], CIMInstance):
_print_instances_as_table(objects, table_width, output_format,
context=context)
context=context,
property_list=property_list)
elif isinstance(objects[0], CIMClass):
_print_classes_as_table(objects, table_width, output_format)
elif isinstance(objects[0], CIMQualifierDeclaration):
Expand Down
94 changes: 92 additions & 2 deletions tests/unit/test_instance_cmds.py
Original file line number Diff line number Diff line change
Expand Up @@ -963,7 +963,7 @@
'properties returns instance with all property types',
{'args': ['enumerate', 'PyWBEM_AllTypes', '--deep-inheritance',
'--propertylist',
'instanceid,scalbool,scaluint32,scalsint32'],
'instanceid,scalbool,scalsint32,scaluint32'],
'general': ['--output-format', 'grid']},
{'stdout': """
Instances: PyWBEM_AllTypes
Expand All @@ -981,7 +981,7 @@
'returns instance with all property types',
{'args': ['enumerate', 'PyWBEM_AllTypes', '--deep-inheritance',
'--propertylist',
'instanceid,arraybool,arrayuint32,arraysint32'],
'instanceid,arraybool,arraysint32,arrayuint32'],
'general': ['--output-format', 'grid']},
{'stdout': """
Instances: PyWBEM_AllTypes
Expand Down Expand Up @@ -1015,6 +1015,30 @@
| "Sofisub" | 1 (female) | |
+------------+------------+-----------------------+
""",
'rc': 0,
'test': 'linesnows'},
ASSOC_MOCK_FILE, OK],

['Verify instance command enumerate of TST_Person honors property list '
'order in table output',
{'args': ['enumerate', 'TST_Person', '--pl', 'Name,Likes,Gender'],
'general': ['--output-format', 'table']},
{'stdout': """
Instances: TST_Person
+------------+-----------------------+------------+
| name | likes | gender |
|------------+-----------------------+------------|
| "Gabi" | 2 (movies) | 1 (female) |
| "Mike" | 1 (books), 2 (movies) | 2 (male) |
| "Saara" | 1 (books) | 1 (female) |
| "Sofi" | | 1 (female) |
| "Gabisub" | | 1 (female) |
| "Mikesub" | | 2 (male) |
| "Saarasub" | | 1 (female) |
| "Sofisub" | | 1 (female) |
+------------+-----------------------+------------+
""",
'rc': 0,
'test': 'linesnows'},
Expand Down Expand Up @@ -2325,6 +2349,38 @@
'test': 'innows'},
ASSOC_MOCK_FILE, OK],

['Verify instance command references with --pl in sorted order',
{'args': ['references', 'TST_Person.name="Mike"',
'--rc', 'TST_Lineage', '--pl', 'instanceid,Parent'],
'general': ['--output-format', 'table']},
{'stdout': ["""Instances: TST_Lineage
+--------------+----------------------------------------+
| InstanceID | parent |
|--------------+----------------------------------------|
| "MikeGabi" | "/root/cimv2:TST_Person.name=\\"Mike\\"" |
| "MikeSofi" | "/root/cimv2:TST_Person.name=\\"Mike\\"" |
+--------------+----------------------------------------+
"""],
'rc': 0,
'test': 'linesnows'},
ASSOC_MOCK_FILE, OK],

['Verify instance command references with --pl in unsorted order',
{'args': ['references', 'TST_Person.name="Mike"',
'--rc', 'TST_Lineage', '--pl', 'Parent,instanceid'],
'general': ['--output-format', 'table']},
{'stdout': ["""Instances: TST_Lineage
+----------------------------------------+--------------+
| parent | InstanceID |
|----------------------------------------+--------------|
| "/root/cimv2:TST_Person.name=\\"Mike\\"" | "MikeGabi" |
| "/root/cimv2:TST_Person.name=\\"Mike\\"" | "MikeSofi" |
+----------------------------------------+--------------+
"""],
'rc': 0,
'test': 'linesnows'},
ASSOC_MOCK_FILE, OK],

['Verify instance command references, no instance name',
['references'],
{'stderr': ['Usage: pywbemcli [GENERAL-OPTIONS] instance references '
Expand Down Expand Up @@ -2451,6 +2507,40 @@
'test': 'linesnows'},
ASSOC_MOCK_FILE, OK],

['Verify instance command associators with --pl in sorted order',
{'args': ['associators', 'TST_Person.name="Mike"',
'--pl', 'Name,Gender,Likes'],
'general': ['--output-format', 'table']},
{'stdout': ["""Instances: TST_FamilyCollection
+-----------+------------+------------+
| name | gender | likes |
|-----------+------------+------------|
| "Family2" | | |
| "Gabi" | 1 (female) | 2 (movies) |
| "Sofi" | 1 (female) | |
+-----------+------------+------------+
"""],
'rc': 0,
'test': 'linesnows'},
ASSOC_MOCK_FILE, OK],

['Verify instance command associators with --pl in unsorted order',
{'args': ['associators', 'TST_Person.name="Mike"',
'--pl', 'Name,Likes,Gender'],
'general': ['--output-format', 'table']},
{'stdout': ["""Instances: TST_FamilyCollection
+-----------+------------+------------+
| name | likes | gender |
|-----------+------------+------------|
| "Family2" | | |
| "Gabi" | 2 (movies) | 1 (female) |
| "Sofi" | | 1 (female) |
+-----------+------------+------------+
"""],
'rc': 0,
'test': 'linesnows'},
ASSOC_MOCK_FILE, OK],

['Verify instance command associators CIM_Foo with --use-pull yes '
'and --pull-max-cnt=1',
{'args': ['associators', 'TST_Person.name="Mike"'],
Expand Down

0 comments on commit 36f37ad

Please sign in to comment.