Source code for spawn.util.path_builder
# spawn
# Copyright (C) 2018-2019, Simmovation Ltd.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
"""Path building
"""
import re
import string
LETTERS = string.ascii_lowercase
[docs]class PathBuilder:
"""The path builder class
This class provides a standardised way to build paths and interpolate/format them with values
"""
def __init__(self, path=''):
"""Initialises :class:`PathBuilder`
:param path: The initial path. Defaults to an empty string.
:type path: str
"""
self._path = path
[docs] def join(self, other):
"""Join two paths by adding ``other`` onto the end of ``self``
:param other: The path to add to the end of this path
:type other: str
:returns: A new path builder with the joined paths
:rtype: :class:`PathBuilder`
"""
new_path = '{}/{}'.format(self._path, other) if self._path else other
return PathBuilder(new_path)
[docs] def join_start(self, other):
"""Join two paths by adding ``other`` onto the start of ``self``
:param other: The path to add to the start of this path
:type other: str
:returns: A new path builder with the joined paths
:rtype: :class:`PathBuilder`
"""
new_path = '{}/{}'.format(other, self._path) if self._path else other
return PathBuilder(new_path)
@staticmethod
def _token(value):
return r'\{' + value + r':?(?P<index_format>[^\}]*)\}'
def __repr__(self):
return self._path
[docs] @staticmethod
def index(index, index_format='1'):
#pylint: disable=anomalous-backslash-in-string
"""Formats an index given the ``index_format`` provided
:param index: The index to format
:type index: int
:param index_format: The index format (see below for examples).
:type index_format: str
:returns: The formatted index
:rtype: str
======= ======================================== =======================
Format Description Examples
======= ======================================== =======================
0*[\d]+ Padded integer with start value 01 -> 01, 02, 03...
002 -> 002, 003, 004...
[a]+ Alphabetical a -> a, b, c, d...
aa -> aa, ab, ac, ad...
======= ======================================== =======================
"""
if re.search(r'0*[\d]+', index_format):
start_index = int(index_format)
pad_width = len(index_format)
return '{index:0>{pad_width}}'.format(index=index + start_index, pad_width=pad_width)
if re.search(r'[a]+', index_format):
index_string = ''
while index > 0:
next_value, index = index % 26, index // 26
index_string = LETTERS[next_value] + index_string
return '{index_string:a>{pad_width}}'.format(
index_string=index_string, pad_width=len(index_format)
)
raise ValueError('index_format has unsupported value {}'.format(index_format))