1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3# path.py: Path functions.
4#
5# Copyright (C) 2010 Yesudeep Mangalapilly <yesudeep@gmail.com>
6#
7# Permission is hereby granted, free of charge, to any person obtaining a copy
8# of this software and associated documentation files (the "Software"), to deal
9# in the Software without restriction, including without limitation the rights
10# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11# copies of the Software, and to permit persons to whom the Software is
12# furnished to do so, subject to the following conditions:
13#
14# The above copyright notice and this permission notice shall be included in
15# all copies or substantial portions of the Software.
16#
17# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23# THE SOFTWARE.
24
25"""
26:module: pathtools.path
27:synopsis: Directory walking, listing, and path sanitizing functions.
28:author: Yesudeep Mangalapilly <yesudeep@gmail.com>
29
30Functions
31---------
32.. autofunction:: get_dir_walker
33.. autofunction:: walk
34.. autofunction:: listdir
35.. autofunction:: list_directories
36.. autofunction:: list_files
37.. autofunction:: absolute_path
38.. autofunction:: real_absolute_path
39.. autofunction:: parent_dir_path
40"""
41
42import os.path
43import os.path
44from functools import partial
45
46
47__all__ = [
48    'get_dir_walker',
49    'walk',
50    'listdir',
51    'list_directories',
52    'list_files',
53    'absolute_path',
54    'real_absolute_path',
55    'parent_dir_path',
56]
57
58
59def get_dir_walker(recursive, topdown=True, followlinks=False):
60    """
61    Returns a recursive or a non-recursive directory walker.
62
63    :param recursive:
64        ``True`` produces a recursive walker; ``False`` produces a non-recursive
65        walker.
66    :returns:
67        A walker function.
68    """
69    if recursive:
70        walk = partial(os.walk, topdown=topdown, followlinks=followlinks)
71    else:
72        def walk(path, topdown=topdown, followlinks=followlinks):
73            try:
74                yield next(os.walk(path, topdown=topdown, followlinks=followlinks))
75            except NameError:
76                yield os.walk(path, topdown=topdown, followlinks=followlinks).next() #IGNORE:E1101
77    return walk
78
79
80def walk(dir_pathname, recursive=True, topdown=True, followlinks=False):
81    """
82    Walks a directory tree optionally recursively. Works exactly like
83    :func:`os.walk` only adding the `recursive` argument.
84
85    :param dir_pathname:
86        The directory to traverse.
87    :param recursive:
88        ``True`` for walking recursively through the directory tree;
89        ``False`` otherwise.
90    :param topdown:
91        Please see the documentation for :func:`os.walk`
92    :param followlinks:
93        Please see the documentation for :func:`os.walk`
94    """
95    walk_func = get_dir_walker(recursive, topdown, followlinks)
96    for root, dirnames, filenames in walk_func(dir_pathname):
97        yield (root, dirnames, filenames)
98
99
100def listdir(dir_pathname,
101            recursive=True,
102            topdown=True,
103            followlinks=False):
104    """
105    Enlists all items using their absolute paths in a directory, optionally
106    recursively.
107
108    :param dir_pathname:
109        The directory to traverse.
110    :param recursive:
111        ``True`` for walking recursively through the directory tree;
112        ``False`` otherwise.
113    :param topdown:
114        Please see the documentation for :func:`os.walk`
115    :param followlinks:
116        Please see the documentation for :func:`os.walk`
117    """
118    for root, dirnames, filenames\
119    in walk(dir_pathname, recursive, topdown, followlinks):
120        for dirname in dirnames:
121            yield absolute_path(os.path.join(root, dirname))
122        for filename in filenames:
123            yield absolute_path(os.path.join(root, filename))
124
125
126def list_directories(dir_pathname,
127                     recursive=True,
128                     topdown=True,
129                     followlinks=False):
130    """
131    Enlists all the directories using their absolute paths within the specified
132    directory, optionally recursively.
133
134    :param dir_pathname:
135        The directory to traverse.
136    :param recursive:
137        ``True`` for walking recursively through the directory tree;
138        ``False`` otherwise.
139    :param topdown:
140        Please see the documentation for :func:`os.walk`
141    :param followlinks:
142        Please see the documentation for :func:`os.walk`
143    """
144    for root, dirnames, filenames\
145    in walk(dir_pathname, recursive, topdown, followlinks):
146        for dirname in dirnames:
147            yield absolute_path(os.path.join(root, dirname))
148
149
150def list_files(dir_pathname,
151               recursive=True,
152               topdown=True,
153               followlinks=False):
154    """
155    Enlists all the files using their absolute paths within the specified
156    directory, optionally recursively.
157
158    :param dir_pathname:
159        The directory to traverse.
160    :param recursive:
161        ``True`` for walking recursively through the directory tree;
162        ``False`` otherwise.
163    :param topdown:
164        Please see the documentation for :func:`os.walk`
165    :param followlinks:
166        Please see the documentation for :func:`os.walk`
167    """
168    for root, dirnames, filenames\
169    in walk(dir_pathname, recursive, topdown, followlinks):
170        for filename in filenames:
171            yield absolute_path(os.path.join(root, filename))
172
173
174def absolute_path(path):
175    """
176    Returns the absolute path for the given path and normalizes the path.
177
178    :param path:
179        Path for which the absolute normalized path will be found.
180    :returns:
181        Absolute normalized path.
182    """
183    return os.path.abspath(os.path.normpath(path))
184
185
186def real_absolute_path(path):
187    """
188    Returns the real absolute normalized path for the given path.
189
190    :param path:
191        Path for which the real absolute normalized path will be found.
192    :returns:
193        Real absolute normalized path.
194    """
195    return os.path.realpath(absolute_path(path))
196
197
198def parent_dir_path(path):
199    """
200    Returns the parent directory path.
201
202    :param path:
203        Path for which the parent directory will be obtained.
204    :returns:
205        Parent directory path.
206    """
207    return absolute_path(os.path.dirname(path))
208