else/Pathclass/pathclass.py

127 lines
3.6 KiB
Python
Raw Normal View History

2016-08-09 08:33:36 +00:00
import glob
import os
class Path:
'''
I started to use pathlib.Path, but it was too much of a pain.
'''
def __init__(self, path):
path = os.path.normpath(path)
path = os.path.abspath(path)
self.absolute_path = path
def __contains__(self, other):
2016-11-08 04:48:43 +00:00
this = os.path.normcase(self.absolute_path)
that = os.path.normcase(other.absolute_path)
return that.startswith(this)
2016-08-09 08:33:36 +00:00
2016-08-13 00:26:12 +00:00
def __eq__(self, other):
2016-11-08 04:48:43 +00:00
if not hasattr(other, 'absolute_path'):
return False
this = os.path.normcase(self.absolute_path)
that = os.path.normcase(other.absolute_path)
return this == that
2016-08-13 00:26:12 +00:00
2016-08-09 08:33:36 +00:00
def __hash__(self):
2016-11-08 04:48:43 +00:00
return hash(os.path.normcase(self.absolute_path))
2016-08-09 08:33:36 +00:00
2016-09-05 23:37:07 +00:00
def __repr__(self):
2016-09-24 00:35:58 +00:00
return '{c}({path})'.format(c=self.__class__.__name__, path=repr(self.absolute_path))
2016-09-05 23:37:07 +00:00
2016-08-09 08:33:36 +00:00
@property
def basename(self):
return os.path.basename(self.absolute_path)
2016-08-18 01:24:38 +00:00
def correct_case(self):
self.absolute_path = get_path_casing(self.absolute_path)
return self.absolute_path
2016-08-09 08:33:36 +00:00
@property
def exists(self):
return os.path.exists(self.absolute_path)
@property
def is_dir(self):
return os.path.isdir(self.absolute_path)
@property
def is_file(self):
return os.path.isfile(self.absolute_path)
@property
def is_link(self):
return os.path.islink(self.absolute_path)
@property
def parent(self):
parent = os.path.dirname(self.absolute_path)
parent = self.__class__(parent)
return parent
@property
def relative_path(self):
relative = self.absolute_path
relative = relative.replace(os.getcwd(), '')
relative = relative.lstrip(os.sep)
return relative
@property
def size(self):
if self.is_file:
return os.path.getsize(self.absolute_path)
else:
return None
@property
def stat(self):
return os.stat(self.absolute_path)
2016-11-11 23:52:25 +00:00
def with_child(self, basename):
basename = os.path.basename(basename)
return Path(os.path.join(self.absolute_path, basename))
2016-08-09 08:33:36 +00:00
def get_path_casing(path):
'''
Take what is perhaps incorrectly cased input and get the path's actual
casing according to the filesystem.
Thank you:
Ethan Furman http://stackoverflow.com/a/7133137/5430534
xvorsx http://stackoverflow.com/a/14742779/5430534
'''
if isinstance(path, Path):
path = path.absolute_path
(drive, subpath) = os.path.splitdrive(path)
2016-09-05 23:37:07 +00:00
drive = drive.upper()
2016-08-09 08:33:36 +00:00
subpath = subpath.lstrip(os.sep)
2016-08-13 00:26:12 +00:00
pattern = [glob_patternize(piece) for piece in subpath.split(os.sep)]
2016-08-09 08:33:36 +00:00
pattern = os.sep.join(pattern)
2016-09-05 23:37:07 +00:00
pattern = drive + os.sep + pattern
2016-08-09 08:33:36 +00:00
#print(pattern)
try:
return glob.glob(pattern)[0]
except IndexError:
2016-08-13 00:26:12 +00:00
return path
def glob_patternize(piece):
'''
Create a pattern like "[u]ser" from "user", forcing glob to look up the
correct path name, while guaranteeing that the only result will be the correct path.
Special cases are:
!, because in glob syntax, [!x] tells glob to look for paths that don't contain
"x". [!] is invalid syntax, so we pick the first non-! character to put
in the brackets.
[, because this starts a capture group
'''
piece = glob.escape(piece)
for character in piece:
if character not in '![]':
replacement = '[%s]' % character
#print(piece, character, replacement)
piece = piece.replace(character, replacement, 1)
break
return piece