Completed
Push — master ( eb9dd6...a22857 )
by Alexandre M.
02:03
created

hansel._split()   B

Complexity

Conditions 5

Size

Total Lines 20

Duplication

Lines 0
Ratio 0 %
Metric Value
cc 5
dl 0
loc 20
rs 8.5455
1
# -*- coding: utf-8 -*-
2
# emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: nil -*-
3
# vi: set ft=python sts=4 ts=4 sw=4 et:
4
"""
5
Crumb manipulation utilities
6
"""
7
import os
8
import os.path as op
9
10
from   six import string_types
11
12
13
def _get_path(crumb_path):
14
    """ Return the path string from `crumb_path`.
15
    Parameters
16
    ----------
17
    crumb_path: str or Crumb
18
19
    Returns
20
    -------
21
    path: str
22
    """
23
    if hasattr(crumb_path, '_path'):
24
        crumb_path = crumb_path._path
25
26
    if not isinstance(crumb_path, string_types):
27
        raise TypeError("Expected `crumb_path` to be a {}, got {}.".format(string_types, type(crumb_path)))
28
29
    return crumb_path
30
31
32
def _is_crumb_arg(crumb_arg, start_sym='{', end_sym='}'):
33
    """ Returns True if `crumb_arg` is a well formed crumb argument, i.e.,
34
    is a string that starts with `start_sym` and ends with `end_sym`. False otherwise."""
35
    if not isinstance(crumb_arg, string_types):
36
        return False
37
38
    return crumb_arg.startswith(start_sym) and crumb_arg.endswith(end_sym)
39
40
41
def _arg_name(arg, start_sym='{', end_sym='}'):
42
    """ Return the name of the argument given its crumb representation.
43
    Parameters
44
    ----------
45
    arg_crumb: str
46
47
    Returns
48
    -------
49
    arg_name: str
50
    """
51
    if not _is_crumb_arg(arg):
52
        raise ValueError("Expected an well formed crumb argument, "
53
                         "got {}.".format(arg))
54
    return arg[len(start_sym):-len(end_sym)]
55
56
57
def _arg_format(arg_name, start_sym='{', end_sym='}'):
58
    """ Return the crumb argument for its string `format()` representation.
59
    Parameters
60
    ----------
61
    arg_name: str
62
63
    Returns
64
    -------
65
    arg_format: str
66
    """
67
    return start_sym + arg_name + end_sym
68
69
70
def is_valid(crumb_path, start_sym='{', end_sym='}'):
71
    """ Return True if `crumb_path` is a well formed path with crumb arguments,
72
    False otherwise.
73
    Parameters
74
    ----------
75
    crumb_path: str
76
77
    Returns
78
    -------
79
    is_valid: bool
80
    """
81
    crumb_path = _get_path(crumb_path)
82
83
    splt = crumb_path.split(op.sep)
84
    for crumb in splt:
85
        if op.isdir(crumb):
86
            continue
87
88
        if _is_crumb_arg(crumb, start_sym=start_sym, end_sym=end_sym):
89
            crumb = _arg_name(crumb, start_sym=start_sym, end_sym=end_sym)
90
91
        if start_sym in crumb or end_sym in crumb:
92
            return False
93
94
    return True
95
96
97
def has_crumbs(crumb_path, start_sym='{', end_sym='}'):
98
    """ Return True if the `crumb_path.split(op.sep)` has item which is a crumb argument
99
    that starts with '{' and ends with '}'."""
100
    crumb_path = _get_path(crumb_path)
101
102
    splt = crumb_path.split(op.sep)
103
    for i in splt:
104
        if _is_crumb_arg(i, start_sym=start_sym, end_sym=end_sym):
105
            return True
106
107
    return False
108
109
110
def _replace(crumb_path, start_sym='{', end_sym='}', **kwargs):
111
    """ Return `crumb_path` where every crumb argument found in `kwargs` has been
112
    replaced by the given value in `kwargs."""
113
    if not kwargs:
114
        return crumb_path
115
116
    for k in kwargs:
117
        karg = _arg_format(k, start_sym=start_sym, end_sym=end_sym)
118
        if k not in crumb_path:
119
            raise KeyError("Could not find argument {} in"
120
                           " `path` {}.".format(k, crumb_path))
121
122
        crumb_path = crumb_path.replace(karg, kwargs[k])
123
124
    return crumb_path
125
126
127
def _split(crumb_path, start_sym='{', end_sym='}'):
128
    """ Return a list of sub-strings of `crumb_path` where the
129
        path parts are separated from the crumb arguments.
130
    """
131
    crumb_path = _get_path(crumb_path)
132
133
    if not is_valid(crumb_path, start_sym, end_sym):
134
        raise ValueError('Crumb path {} is not valid.'.format(crumb_path))
135
136
    splt = []
137
    tmp = '/' if crumb_path.startswith(op.sep) else ''
138
    for i in crumb_path.split(op.sep):
139
        if i.startswith(start_sym):
140
            splt.append(tmp)
141
            tmp = ''
142
            splt.append(i)
143
        else:
144
            tmp = op.join(tmp, i)
145
146
    return splt
147
148
149
def _touch(crumb_path, exist_ok=True, start_sym='{', end_sym='}'):
150
    """ Create a leaf directory and all intermediate ones
151
    using the non crumbed part of `crumb_path`.
152
    If the target directory already exists, raise an IOError
153
    if exist_ok is False. Otherwise no exception is raised.
154
    Parameters
155
    ----------
156
    crumb_path: str
157
158
    exist_ok: bool
159
        Default = True
160
161
    Returns
162
    -------
163
    nupath: str
164
        The new path created.
165
    """
166
    if has_crumbs(crumb_path, start_sym=start_sym, end_sym=end_sym):
167
        nupath = _split(crumb_path, start_sym=start_sym, end_sym=end_sym)[0]
168
    else:
169
        nupath = crumb_path
170
171
    if op.exists(nupath) and not exist_ok:
172
        raise IOError("Folder {} already exists.".format(nupath))
173
174
    try:
175
        os.makedirs(nupath, exist_ok=exist_ok)
176
    except:
177
        raise
178
    else:
179
        return nupath
180
181
182
def _split_exists(crumb_path, start_sym='{', end_sym='}'):
183
    """ Return True if the part without crumb arguments of `crumb_path`
184
    is an existing path or a symlink, False otherwise.
185
    Returns
186
    -------
187
    exists: bool
188
    """
189
    if has_crumbs(crumb_path):
190
        rpath = _split(crumb_path, start_sym=start_sym, end_sym=end_sym)[0]
191
    else:
192
        rpath = str(crumb_path)
193
194
    return op.exists(rpath) or op.islink(rpath)
195