2010-06-01 11:10:06 -05:00
|
|
|
#!/usr/bin/env python
|
2013-04-01 04:41:48 -05:00
|
|
|
# -*- coding: utf-8 -*-
|
2008-06-05 03:58:43 -05:00
|
|
|
"""
|
2010-06-01 11:10:06 -05:00
|
|
|
path
|
|
|
|
~~~~
|
2008-06-05 03:58:43 -05:00
|
|
|
|
2016-01-14 15:54:04 -06:00
|
|
|
:copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS.
|
2010-06-01 11:10:06 -05:00
|
|
|
:license: BSD, see LICENSE for details.
|
|
|
|
"""
|
|
|
|
import os
|
|
|
|
import sys
|
|
|
|
import shutil
|
2015-12-19 03:57:40 -06:00
|
|
|
from io import open
|
2008-06-05 03:58:43 -05:00
|
|
|
|
2015-03-20 16:26:32 -05:00
|
|
|
from six import PY2, text_type, binary_type
|
2014-04-28 21:46:47 -05:00
|
|
|
|
2008-06-05 03:58:43 -05:00
|
|
|
|
2010-06-01 11:10:06 -05:00
|
|
|
FILESYSTEMENCODING = sys.getfilesystemencoding() or sys.getdefaultencoding()
|
2008-06-05 03:58:43 -05:00
|
|
|
|
|
|
|
|
2014-04-29 09:44:12 -05:00
|
|
|
class path(text_type):
|
2010-06-01 12:59:38 -05:00
|
|
|
"""
|
|
|
|
Represents a path which behaves like a string.
|
|
|
|
"""
|
2014-04-30 07:30:46 -05:00
|
|
|
if PY2:
|
2010-06-12 13:21:14 -05:00
|
|
|
def __new__(cls, s, encoding=FILESYSTEMENCODING, errors='strict'):
|
2012-05-01 01:13:06 -05:00
|
|
|
if isinstance(s, str):
|
|
|
|
s = s.decode(encoding, errors)
|
2014-04-29 09:44:12 -05:00
|
|
|
return text_type.__new__(cls, s)
|
|
|
|
return text_type.__new__(cls, s)
|
2008-06-05 03:58:43 -05:00
|
|
|
|
2010-06-01 11:10:06 -05:00
|
|
|
@property
|
|
|
|
def parent(self):
|
2010-06-01 12:59:38 -05:00
|
|
|
"""
|
|
|
|
The name of the directory the file or directory is in.
|
|
|
|
"""
|
2010-06-01 11:10:06 -05:00
|
|
|
return self.__class__(os.path.dirname(self))
|
2008-06-05 03:58:43 -05:00
|
|
|
|
2014-08-10 08:23:52 -05:00
|
|
|
def basename(self):
|
|
|
|
return os.path.basename(self)
|
|
|
|
|
2010-06-01 11:10:06 -05:00
|
|
|
def abspath(self):
|
2010-06-01 12:59:38 -05:00
|
|
|
"""
|
|
|
|
Returns the absolute path.
|
|
|
|
"""
|
2010-06-01 11:10:06 -05:00
|
|
|
return self.__class__(os.path.abspath(self))
|
2008-06-05 03:58:43 -05:00
|
|
|
|
2010-06-01 12:59:38 -05:00
|
|
|
def isabs(self):
|
|
|
|
"""
|
|
|
|
Returns ``True`` if the path is absolute.
|
|
|
|
"""
|
|
|
|
return os.path.isabs(self)
|
|
|
|
|
2010-06-01 11:10:06 -05:00
|
|
|
def isdir(self):
|
2010-06-01 12:59:38 -05:00
|
|
|
"""
|
|
|
|
Returns ``True`` if the path is a directory.
|
|
|
|
"""
|
2010-06-01 11:10:06 -05:00
|
|
|
return os.path.isdir(self)
|
2008-06-05 03:58:43 -05:00
|
|
|
|
2010-06-01 11:10:06 -05:00
|
|
|
def isfile(self):
|
2010-06-01 12:59:38 -05:00
|
|
|
"""
|
|
|
|
Returns ``True`` if the path is a file.
|
|
|
|
"""
|
2010-06-01 11:10:06 -05:00
|
|
|
return os.path.isfile(self)
|
2008-06-05 03:58:43 -05:00
|
|
|
|
2010-06-01 12:59:38 -05:00
|
|
|
def islink(self):
|
|
|
|
"""
|
|
|
|
Returns ``True`` if the path is a symbolic link.
|
|
|
|
"""
|
|
|
|
return os.path.islink(self)
|
|
|
|
|
|
|
|
def ismount(self):
|
|
|
|
"""
|
|
|
|
Returns ``True`` if the path is a mount point.
|
|
|
|
"""
|
|
|
|
return os.path.ismount(self)
|
|
|
|
|
2010-06-01 11:10:06 -05:00
|
|
|
def rmtree(self, ignore_errors=False, onerror=None):
|
2010-06-01 12:59:38 -05:00
|
|
|
"""
|
|
|
|
Removes the file or directory and any files or directories it may
|
|
|
|
contain.
|
|
|
|
|
|
|
|
:param ignore_errors:
|
|
|
|
If ``True`` errors are silently ignored, otherwise an exception
|
|
|
|
is raised in case an error occurs.
|
|
|
|
|
|
|
|
:param onerror:
|
|
|
|
A callback which gets called with the arguments `func`, `path` and
|
|
|
|
`exc_info`. `func` is one of :func:`os.listdir`, :func:`os.remove`
|
|
|
|
or :func:`os.rmdir`. `path` is the argument to the function which
|
|
|
|
caused it to fail and `exc_info` is a tuple as returned by
|
|
|
|
:func:`sys.exc_info`.
|
|
|
|
"""
|
2010-06-01 11:10:06 -05:00
|
|
|
shutil.rmtree(self, ignore_errors=ignore_errors, onerror=onerror)
|
2008-06-05 03:58:43 -05:00
|
|
|
|
2010-08-14 12:48:42 -05:00
|
|
|
def copytree(self, destination, symlinks=False):
|
2010-06-01 12:59:38 -05:00
|
|
|
"""
|
|
|
|
Recursively copy a directory to the given `destination`. If the given
|
|
|
|
`destination` does not exist it will be created.
|
|
|
|
|
|
|
|
:param symlinks:
|
|
|
|
If ``True`` symbolic links in the source tree result in symbolic
|
|
|
|
links in the destination tree otherwise the contents of the files
|
|
|
|
pointed to by the symbolic links are copied.
|
|
|
|
"""
|
2010-08-14 12:48:42 -05:00
|
|
|
shutil.copytree(self, destination, symlinks=symlinks)
|
2008-06-05 03:58:43 -05:00
|
|
|
|
2010-06-01 12:59:38 -05:00
|
|
|
def movetree(self, destination):
|
|
|
|
"""
|
|
|
|
Recursively move the file or directory to the given `destination`
|
|
|
|
similar to the Unix "mv" command.
|
|
|
|
|
|
|
|
If the `destination` is a file it may be overwritten depending on the
|
|
|
|
:func:`os.rename` semantics.
|
|
|
|
"""
|
|
|
|
shutil.move(self, destination)
|
|
|
|
|
|
|
|
move = movetree
|
|
|
|
|
2010-06-01 11:10:06 -05:00
|
|
|
def unlink(self):
|
2010-06-01 12:59:38 -05:00
|
|
|
"""
|
|
|
|
Removes a file.
|
|
|
|
"""
|
2010-06-01 11:10:06 -05:00
|
|
|
os.unlink(self)
|
2008-06-05 03:58:43 -05:00
|
|
|
|
2014-09-21 11:26:50 -05:00
|
|
|
def utime(self, arg):
|
|
|
|
os.utime(self, arg)
|
|
|
|
|
2015-12-19 17:07:40 -06:00
|
|
|
def open(self, mode='r', **kwargs):
|
|
|
|
return open(self, mode, **kwargs)
|
|
|
|
|
2015-12-19 03:57:40 -06:00
|
|
|
def write_text(self, text, encoding='utf-8', **kwargs):
|
2010-06-01 12:59:38 -05:00
|
|
|
"""
|
|
|
|
Writes the given `text` to the file.
|
|
|
|
"""
|
2015-12-19 03:57:40 -06:00
|
|
|
if isinstance(text, bytes):
|
|
|
|
text = text.decode(encoding)
|
2015-12-19 17:07:40 -06:00
|
|
|
with open(self, 'w', encoding=encoding, **kwargs) as f:
|
2010-06-01 11:10:06 -05:00
|
|
|
f.write(text)
|
2008-06-05 03:58:43 -05:00
|
|
|
|
2015-12-19 03:57:40 -06:00
|
|
|
def text(self, encoding='utf-8', **kwargs):
|
2010-06-01 12:59:38 -05:00
|
|
|
"""
|
|
|
|
Returns the text in the file.
|
|
|
|
"""
|
2015-12-19 17:07:40 -06:00
|
|
|
with open(self, mode='U', encoding=encoding, **kwargs) as f:
|
2015-03-20 16:26:32 -05:00
|
|
|
text = f.read()
|
|
|
|
contents = repr_as(text, '<%s contents>' % self.basename())
|
|
|
|
return contents
|
2008-06-05 03:58:43 -05:00
|
|
|
|
2010-06-19 12:58:28 -05:00
|
|
|
def bytes(self):
|
|
|
|
"""
|
|
|
|
Returns the bytes in the file.
|
|
|
|
"""
|
2015-12-19 17:07:40 -06:00
|
|
|
with open(self, mode='rb') as f:
|
2010-06-19 12:58:28 -05:00
|
|
|
return f.read()
|
|
|
|
|
|
|
|
def write_bytes(self, bytes, append=False):
|
|
|
|
"""
|
|
|
|
Writes the given `bytes` to the file.
|
|
|
|
|
|
|
|
:param append:
|
|
|
|
If ``True`` given `bytes` are added at the end of the file.
|
|
|
|
"""
|
|
|
|
if append:
|
|
|
|
mode = 'ab'
|
|
|
|
else:
|
|
|
|
mode = 'wb'
|
2015-12-19 17:07:40 -06:00
|
|
|
with open(self, mode=mode) as f:
|
2010-06-19 12:58:28 -05:00
|
|
|
f.write(bytes)
|
|
|
|
|
2010-06-01 11:10:06 -05:00
|
|
|
def exists(self):
|
2010-06-01 12:59:38 -05:00
|
|
|
"""
|
|
|
|
Returns ``True`` if the path exist.
|
|
|
|
"""
|
2010-06-01 11:10:06 -05:00
|
|
|
return os.path.exists(self)
|
2008-06-05 03:58:43 -05:00
|
|
|
|
2010-06-01 12:59:38 -05:00
|
|
|
def lexists(self):
|
|
|
|
"""
|
|
|
|
Returns ``True`` if the path exists unless it is a broken symbolic
|
|
|
|
link.
|
|
|
|
"""
|
|
|
|
return os.path.lexists(self)
|
|
|
|
|
2014-01-19 04:17:10 -06:00
|
|
|
def makedirs(self, mode=0o777):
|
2010-06-01 12:59:38 -05:00
|
|
|
"""
|
|
|
|
Recursively create directories.
|
|
|
|
"""
|
2008-06-05 03:58:43 -05:00
|
|
|
os.makedirs(self, mode)
|
|
|
|
|
2010-06-01 11:10:06 -05:00
|
|
|
def joinpath(self, *args):
|
2010-06-01 12:59:38 -05:00
|
|
|
"""
|
|
|
|
Joins the path with the argument given and returns the result.
|
|
|
|
"""
|
2010-06-01 11:10:06 -05:00
|
|
|
return self.__class__(os.path.join(self, *map(self.__class__, args)))
|
2008-06-05 03:58:43 -05:00
|
|
|
|
2014-09-21 10:17:02 -05:00
|
|
|
def listdir(self):
|
|
|
|
return os.listdir(self)
|
|
|
|
|
2010-06-01 11:10:06 -05:00
|
|
|
__div__ = __truediv__ = joinpath
|
2008-06-05 03:58:43 -05:00
|
|
|
|
2010-06-01 11:10:06 -05:00
|
|
|
def __repr__(self):
|
2014-04-29 09:44:12 -05:00
|
|
|
return '%s(%s)' % (self.__class__.__name__, text_type.__repr__(self))
|
2015-03-20 16:26:32 -05:00
|
|
|
|
|
|
|
|
|
|
|
# Lives here only to avoid circular references; use it from util.py!
|
|
|
|
class _repr_text(text_type):
|
|
|
|
def __repr__(self):
|
|
|
|
return self._repr
|
2016-06-11 10:00:52 -05:00
|
|
|
|
|
|
|
|
2015-03-20 16:26:32 -05:00
|
|
|
class _repr_bin(binary_type):
|
|
|
|
def __repr__(self):
|
|
|
|
return self._repr
|
|
|
|
|
2016-06-11 10:00:52 -05:00
|
|
|
|
2015-03-20 16:26:32 -05:00
|
|
|
def repr_as(string, repr_):
|
|
|
|
wrapper = _repr_text if isinstance(string, text_type) else _repr_bin
|
|
|
|
proxy = wrapper(string)
|
|
|
|
proxy._repr = repr_
|
|
|
|
return proxy
|