You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
214 lines
7.6 KiB
214 lines
7.6 KiB
commit b1cc8624a2ad8afdc04181ccf6ca42c37a9a701e
|
|
Author: mulhern <amulhern@redhat.com>
|
|
Date: Mon Feb 15 14:13:49 2016 -0500
|
|
|
|
Fixes for ID_PATH parsing.
|
|
|
|
* Disable individual fields matching '-'.
|
|
* Do not try to parse delimiter '-' between distinct ids.
|
|
* Change format for a sas path.
|
|
* Handle virtio-pci.
|
|
|
|
Signed-off-by: mulhern <amulhern@redhat.com>
|
|
|
|
diff --git a/src/pyudev/_parsing/_id_path.py b/src/pyudev/_parsing/_id_path.py
|
|
index c94f332..0b65c43 100644
|
|
--- a/src/pyudev/_parsing/_id_path.py
|
|
+++ b/src/pyudev/_parsing/_id_path.py
|
|
@@ -35,6 +35,16 @@
|
|
from ._shared import Parser
|
|
|
|
|
|
+class IdPathField(Field):
|
|
+ """
|
|
+ Overrides default regular expression.
|
|
+ """
|
|
+ # pylint: disable=too-few-public-methods
|
|
+
|
|
+ def __init__(self, name, regexp=r'[^-]+', description=None):
|
|
+ super(IdPathField, self).__init__(name, regexp, description)
|
|
+
|
|
+
|
|
class IdPathParsers(object):
|
|
"""
|
|
Aggregate parsers.
|
|
@@ -42,70 +52,73 @@ class IdPathParsers(object):
|
|
# pylint: disable=too-few-public-methods
|
|
|
|
PARSERS = [
|
|
- Parser(r'acpi-%s', [Field('sys_name')]),
|
|
- Parser(r'ap-%s', [Field('sys_name')]),
|
|
- Parser(r'ata-%s', [Field('port_no')]),
|
|
- Parser(r'bcma-%s', [Field('core')]),
|
|
- Parser(r'cciss-disk%s', [Field('disk')]),
|
|
- Parser(r'ccw-%s', [Field('sys_name')]),
|
|
- Parser(r'ccwgroup-%s', [Field('sys_name')]),
|
|
- Parser(r'fc-%s-%s', [Field('port_name'), Field('lun')]),
|
|
+ Parser(r'acpi-%s', [IdPathField('sys_name')]),
|
|
+ Parser(r'ap-%s', [IdPathField('sys_name')]),
|
|
+ Parser(r'ata-%s', [IdPathField('port_no')]),
|
|
+ Parser(r'bcma-%s', [IdPathField('core')]),
|
|
+ Parser(r'cciss-disk%s', [IdPathField('disk')]),
|
|
+ Parser(r'ccw-%s', [IdPathField('sys_name')]),
|
|
+ Parser(r'ccwgroup-%s', [IdPathField('sys_name')]),
|
|
+ Parser(r'fc-%s-%s', [IdPathField('port_name'), IdPathField('lun')]),
|
|
Parser(
|
|
r'ip-%s:%s-iscsi-%s-%s',
|
|
[
|
|
- Field('persistent_address'),
|
|
- Field('persistent_port'),
|
|
- Field('target_name'),
|
|
- Field('lun')
|
|
+ IdPathField('persistent_address'),
|
|
+ IdPathField('persistent_port'),
|
|
+ IdPathField('target_name'),
|
|
+ IdPathField('lun')
|
|
]
|
|
),
|
|
- Parser(r'iucv-%s', [Field('sys_name')]),
|
|
- Parser(r'nst%s', [Field('name')]),
|
|
- Parser(r'pci-%s', [Field('sys_name')]),
|
|
- Parser(r'platform-%s', [Field('sys_name')]),
|
|
- Parser(r'sas-%s-%s', [Field('sas_address'), Field('lun')]),
|
|
+ Parser(r'iucv-%s', [IdPathField('sys_name')]),
|
|
+ Parser(r'nst%s', [IdPathField('name')]),
|
|
+ Parser(r'pci-%s', [IdPathField('sys_name')]),
|
|
+ Parser(r'platform-%s', [IdPathField('sys_name')]),
|
|
+ Parser(r'sas-%s-lun-%s',
|
|
+ [IdPathField('sas_address'), IdPathField('lun')]
|
|
+ ),
|
|
Parser(
|
|
r'sas-exp%s-phy%s-%s',
|
|
[
|
|
- Field(
|
|
+ IdPathField(
|
|
'sas_address',
|
|
r'.*',
|
|
'sysfs sas_address attribute of expander'
|
|
),
|
|
- Field(
|
|
+ IdPathField(
|
|
'phy_identifier',
|
|
r'.*',
|
|
'sysfs phy_identifier attribute of target sas device'
|
|
),
|
|
- Field('lun', description='sysnum of device (0 if none)')
|
|
+ IdPathField('lun', description='sysnum of device (0 if none)')
|
|
]
|
|
),
|
|
Parser(
|
|
r'sas-phy%s-%s',
|
|
[
|
|
- Field(
|
|
+ IdPathField(
|
|
'phy_identifier',
|
|
r'.*',
|
|
'sysfs phy_identifier attribute of target sas device'
|
|
),
|
|
- Field('lun', description='sysnum of device (0 if none)')
|
|
+ IdPathField('lun', description='sysnum of device (0 if none)')
|
|
]
|
|
),
|
|
- Parser(r'scm-%s', [Field('sys_name')]),
|
|
+ Parser(r'scm-%s', [IdPathField('sys_name')]),
|
|
Parser(
|
|
r'scsi-%s:%s:%s:%s',
|
|
[
|
|
- Field('host'),
|
|
- Field('bus'),
|
|
- Field('target'),
|
|
- Field('lun')
|
|
+ IdPathField('host'),
|
|
+ IdPathField('bus'),
|
|
+ IdPathField('target'),
|
|
+ IdPathField('lun')
|
|
]
|
|
),
|
|
- Parser('serio-%s', [Field('sysnum')]),
|
|
- Parser('st%s', [Field('name')]),
|
|
- Parser('usb-0:%s', [Field('port')]),
|
|
- Parser('vmbus-%s-%s', [Field('guid'), Field('lun')]),
|
|
- Parser('xen-%s', [Field('sys_name')])
|
|
+ Parser('serio-%s', [IdPathField('sysnum')]),
|
|
+ Parser('st%s', [IdPathField('name')]),
|
|
+ Parser('usb-0:%s', [IdPathField('port')]),
|
|
+ Parser('virtio-pci-%s', [IdPathField('sys_name')]),
|
|
+ Parser('vmbus-%s-%s', [IdPathField('guid'), IdPathField('lun')]),
|
|
+ Parser('xen-%s', [IdPathField('sys_name')])
|
|
]
|
|
|
|
|
|
@@ -166,6 +179,6 @@ def parse(self, value):
|
|
|
|
(parser, best_match) = max(matches, key=lambda x: len(x[0].prefix))
|
|
match_list.append((parser, best_match))
|
|
- value = value[len(best_match.group('total')):]
|
|
+ value = value[len(best_match.group('total')) + 1:]
|
|
|
|
return match_list
|
|
diff --git a/tests/test_parsing.py b/tests/test_parsing.py
|
|
index 619fb01..fba5575 100644
|
|
--- a/tests/test_parsing.py
|
|
+++ b/tests/test_parsing.py
|
|
@@ -52,20 +52,27 @@ class TestIDPATH(object):
|
|
Test parsing ID_PATH values.
|
|
"""
|
|
# pylint: disable=too-few-public-methods
|
|
-
|
|
- @given(
|
|
- strategies.sampled_from(_DEVICES).filter(
|
|
- lambda x: x.get('ID_PATH') is not None
|
|
- )
|
|
+ _devices = [d for d in _DEVICES if d.get('ID_PATH') is not None]
|
|
+ @pytest.mark.skipif(
|
|
+ len(_devices) == 0,
|
|
+ reason="no devices with ID_PATH property"
|
|
)
|
|
+ @given(strategies.sampled_from(_devices))
|
|
+ @settings(min_satisfying_examples=1)
|
|
def test_parsing(self, a_device):
|
|
"""
|
|
Test that parsing is satisfactory on all examples.
|
|
"""
|
|
+ parsers = _parsing.IdPathParsers.PARSERS
|
|
id_path = a_device.get('ID_PATH')
|
|
- parser = _parsing.IdPathParse(_parsing.IdPathParsers.PARSERS)
|
|
+ parser = _parsing.IdPathParse(parsers)
|
|
result = parser.parse(id_path)
|
|
assert isinstance(result, list) and result != []
|
|
+ assert all(
|
|
+ any(r[1].group('total').startswith(p.prefix) for p in parsers) \
|
|
+ for r in result
|
|
+ )
|
|
+ assert not any(r[1].group('total').startswith('-') for r in result)
|
|
|
|
_devices = [d for d in _DEVICES if d.get('ID_SAS_PATH') is not None]
|
|
@pytest.mark.skipif(
|
|
@@ -78,10 +85,25 @@ def test_parsing_sas_path(self, a_device):
|
|
"""
|
|
Test that parsing is satisfactory on all examples.
|
|
"""
|
|
+ parsers = _parsing.IdPathParsers.PARSERS
|
|
id_path = a_device.get('ID_SAS_PATH')
|
|
- parser = _parsing.IdPathParse(_parsing.IdPathParsers.PARSERS)
|
|
+ parser = _parsing.IdPathParse(parsers)
|
|
result = parser.parse(id_path)
|
|
assert isinstance(result, list) and result != []
|
|
+ assert all(
|
|
+ any(r[1].group('total').startswith(p.prefix) for p in parsers) \
|
|
+ for r in result
|
|
+ )
|
|
+ assert not any(r[1].group('total').startswith('-') for r in result)
|
|
+
|
|
+ def test_failure(self):
|
|
+ """
|
|
+ Test at least one failure.
|
|
+ """
|
|
+ id_path = 'pci-0000_09_00_0-sas0x5000155359566200-lun-0'
|
|
+ parser = _parsing.IdPathParse(_parsing.IdPathParsers.PARSERS)
|
|
+ result = parser.parse(id_path)
|
|
+ assert result == []
|
|
|
|
|
|
class TestDevlinks(object):
|