Source code for xotl.tools.fs.path
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# ---------------------------------------------------------------------
# Copyright (c) Merchise Autrement [~º/~] and Contributors
# All rights reserved.
#
# This is free software; you can do what the LICENCE file allows you to.
#
"""Extensions to os.path
Functions inside this module must not have side-effects on the
file-system. This module re-exports (without change) several functions from the
`os.path`:mod: standard module.
"""
import sys
from os.path import abspath, dirname, expanduser
from os.path import join as _orig_join
from os.path import normpath, sep
from xotl.tools.future.functools import power as pow_
__all__ = (
"abspath",
"expanduser",
"dirname",
"sep",
"normpath",
"rtrim",
"fix_encoding",
"join",
"normalize_path",
"shorten_module_filename",
"shorten_user",
)
# TODO: import all in "from os.path import *"
[docs]def rtrim(path, n=1):
"""Trims the last `n` components of the pathname `path`.
This basically applies `n` times the function `os.path.dirname` to `path`.
`path` is normalized before proceeding (but not tested to exists).
.. versionchanged:: 1.5.5 `n` defaults to 1. In this case rtrim is
identical to `os.path.dirname`:func:.
Example::
>>> rtrim('/tmp/a/b/c/d', 3)
'/tmp/a'
# It does not matter if `/` is at the end
>>> rtrim('/tmp/a/b/c/d/', 3)
'/tmp/a'
"""
return pow_(dirname, n)(normalize_path(path))
[docs]def fix_encoding(name, encoding=None):
"""Fix encoding of a file system resource name.
`encoding` is ignored if `name` is already a `str`.
"""
if not isinstance(name, str):
if not encoding:
from xotl.tools.future.codecs import force_encoding
encoding = force_encoding(sys.getfilesystemencoding())
fixer = name.decode if isinstance(name, bytes) else name.encode
return fixer(encoding)
else:
return name
[docs]def join(base, *extras):
"""Join two or more pathname components, inserting '/' as needed.
If any component is an absolute path, all previous path components
will be discarded.
Normalize path (after join parts), eliminating double slashes, etc.
"""
try:
path = _orig_join(base, *extras)
except Exception: # TODO: @med which exceptions expected?
base = fix_encoding(base)
extras = [fix_encoding(extra) for extra in extras]
path = _orig_join(base, *extras)
return normpath(path)
[docs]def normalize_path(base, *extras):
"""Normalize path by:
- expanding '~' and '~user' constructions.
- eliminating double slashes
- converting to absolute.
"""
# FIXME: [med] Redundant "path" in name "xotl.tools.fs.path.normalize_path"
try:
path = _orig_join(base, *extras)
except Exception: # TODO: @med which exceptions expected?
path = join(base, *extras)
return abspath(expanduser(path))
[docs]def shorten_module_filename(filename):
"""A filename, normally a module o package name, is shortened looking his
head in all python path.
"""
path = sys.path[:]
path.sort(lambda x, y: len(y) - len(x))
for item in path:
if item and filename.startswith(item):
filename = filename[len(item) :]
if filename.startswith(sep):
filename = filename[len(sep) :]
for item in ("__init__.py", "__init__.pyc"):
if filename.endswith(item):
filename = filename[: -len(item)]
if filename.endswith(sep):
filename = filename[: -len(sep)]
return shorten_user(filename)
[docs]def shorten_user(filename):
"""A filename is shortened looking for the (expantion) $HOME in his head
and replacing it by '~'.
"""
home = expanduser("~")
if filename.startswith(home):
filename = _orig_join("~", filename[len(home) :])
return filename