Skip to content

Commit

Permalink
Merge branch 'ranges' into develop
Browse files Browse the repository at this point in the history
  • Loading branch information
Peter Sprygada committed Jul 22, 2015
2 parents 78464ea + 278cd0b commit 453e22e
Show file tree
Hide file tree
Showing 2 changed files with 96 additions and 8 deletions.
65 changes: 65 additions & 0 deletions pyeapi/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@
import logging.handlers
import collections

from itertools import tee, izip_longest

_LOGGER = logging.getLogger(__name__)

_syslog_handler = logging.handlers.SysLogHandler()
Expand Down Expand Up @@ -160,3 +162,66 @@ def make_iterable(value):

return value

def lookahead(it):
it1, it2 = tee(iter(it))
next(it2)
return izip_longest(it1, it2)

def expand_range(arg, value_delimiter=',', range_delimiter='-'):
"""
Expands a delimited string of ranged integers into a list of strings
:param arg: The string range to expand
:param value_delimiter: The delimiter that separates values
:param range_delimiter: The delimiter that signifies a range of values
:return: An array of expanded string values
:rtype: list
"""
values = list()
expanded = arg.split(value_delimiter)
for item in expanded:
if range_delimiter in item:
start, end = item.split(range_delimiter)
_expand = range(int(start), int(end)+1)
values.extend([str(x) for x in _expand])
else:
values.extend([item])
return [str(x) for x in values]

def collapse_range(arg, value_delimiter=',', range_delimiter='-'):
"""
Collapses a list of values into a range set
:param arg: The list of values to collapse
:param value_delimiter: The delimiter that separates values
:param range_delimiter: The delimiter that separates a value range
:return: An array of collapsed string values
:rtype: list
"""
values = list()
expanded = arg.split(value_delimiter)
range_start = None

for v1, v2 in lookahead(expanded):
if v2:
v1 = int(v1)
v2 = int(v2)
if (v1 + 1) == v2:
if not range_start:
range_start = v1
elif range_start:
item = '{}{}{}'.format(range_start, range_delimiter, v1)
values.extend([item])
range_start = None
else:
values.extend([v1])
elif range_start:
item = '{}{}{}'.format(range_start, range_delimiter, v1)
values.extend([item])
range_start = None
else:
values.extend([v1])
return [str(x) for x in values]

39 changes: 31 additions & 8 deletions test/unit/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,37 @@ def test_import_module_raises_import_error(self):
with self.assertRaises(ImportError):
pyeapi.utils.import_module('fake.module.test')

# Do not use syslog directly, instead use the 'logging' module
# facility and select the logging target (syslog, log file, stderr)
# externally.
# @patch('pyeapi.utils.syslog')
# def test_debug(self, mock_syslog):
# pyeapi.utils.islocalconnection = Mock(return_value=True)
# pyeapi.utils.debug('test')
# mock_syslog.syslog.assert_called_with(mock_syslog.LOG_NOTICE, 'test')
def test_expand_singles(self):
vlans = '1,2,3'
result = pyeapi.utils.expand_range(vlans)
result = ','.join(result)
self.assertTrue(vlans == result)

def test_expand_range(self):
vlans = '1-15'
expected = [str(x) for x in range(1, 16)]
result = pyeapi.utils.expand_range(vlans)
self.assertEqual(result, expected)

def test_expand_mixed(self):
vlans = '1,3,5-7,9'
result = pyeapi.utils.expand_range(vlans)
self.assertEqual(result, ['1','3','5','6','7','9'])

def test_collapse_singles(self):
vlans = '1,3,5,7'
result = pyeapi.utils.collapse_range(vlans)
self.assertEqual(result, ['1','3','5','7'])

def test_collapse_range(self):
vlans = '1,2,3,4,5'
result = pyeapi.utils.collapse_range(vlans)
self.assertEqual(result, ['1-5'])

def test_collapse_mixed(self):
vlans = '1,3,5,6,7,9'
result = pyeapi.utils.collapse_range(vlans)
self.assertEqual(result, ['1','3','5-7','9'])

@patch('pyeapi.utils._LOGGER')
def test_debug(self, mock_logger):
Expand Down

0 comments on commit 453e22e

Please sign in to comment.