Source code for stoqlib.lib.stringutils
# -*- coding: utf-8 -*-
# vi:si:et:sw=4:sts=4:ts=4
##
## Copyright (C) 2013 Async Open Source
##
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU Lesser General Public License
## as published by the Free Software Foundation; either version 2
## of the License, or (at your option) any later version.
##
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
## GNU Lesser General Public License for more details.
##
## You should have received a copy of the GNU Lesser General Public License
## along with this program; if not, write to the Free Software
## Foundation, Inc., or visit: http://www.gnu.org/.
##
##
## Author(s): Stoq Team <stoq-devel@async.com.br>
##
"""Utilities for manipulating strings"""
def _increment(value):
# Make sure the new value is at least the same size the old one was.
# For example, this will make '009' become '010' instead of just '10'
return unicode(int(value) + 1).zfill(len(value))
[docs]def next_value_for(value):
"""Generate the next value for value.
For instance 4 -> 5, 99 -> 100, A83 -> A84 etc::
>>> next_value_for(u'999')
u'1000'
>>> next_value_for(u'1')
u'2'
>>> next_value_for(u'abc')
u'abd'
>>> next_value_for(u'XYZ')
u'XZ0'
>>> next_value_for(u'AB00099')
u'AB00100'
:param unicode value:
:returns:
:rtype: unicode
"""
if not value:
return u'1'
if value.isdigit():
return _increment(value)
last = value[-1]
if last.isdigit():
l = u''
# Get the greatest part in the string's end that is a number.
# For instance: 'ABC123' will get '123'
for c in reversed(value):
if not c.isdigit():
break
l = c + l
value = value[:-len(l)] + _increment(l)
elif last.isalpha():
last = chr(ord(last) + 1)
if last.isalpha():
value = value[:-1] + last
else:
value_len = len(value)
value = next_value_for(value[:-1])
# If the next_value_for didn't increased the string length, we
# need to. For instance: 'ABZ' would make the line above return
# 'AC' and thus the next value for the sequence is 'AC0'. It should
# be fine for '99Z' because it would generate '100'
if len(value) <= value_len:
value += u'0'
else:
value += u'0'
return value
[docs]def max_value_for(values):
"""Get the maximum value from the values
Python compares strings from left to right and thus comparisons
like '9' > '10' would be true.
This avoid that problem by 0-"padding" the strings to the same length
of the longest string on the sequence. Because of that, the return value
will be in that format. For instance::
>>> max_value_for([u'1', u'2'])
u'2'
>>> max_value_for([u'99', u'100'])
u'100'
>>> max_value_for([u'99', u'0001'])
u'0099'
:param values: a sequence of strings
:returns: the greatest string on the sequence
"""
max_length = max(len(v) for v in values)
return max(v.zfill(max_length) for v in values)