move osutils stuff into fileutils

This commit is contained in:
Mahmoud Hashemi 2015-03-22 02:16:18 -07:00
parent f56aa8bf2b
commit 91e6f2e313
2 changed files with 119 additions and 120 deletions

View File

@ -1,9 +1,12 @@
# -*- coding: utf-8 -*-
import os
import re
import stat
import errno
import fnmatch
import tempfile
from shutil import copy2, copystat, Error
VALID_PERM_CHARS = 'rwx'
@ -157,13 +160,122 @@ class AtomicSaver(object):
return
#with atomic_save('/home/mahmoud/tmp/final.txt') as f:
# f.write('rofl')
# raise ValueError('nope')
# f.write('\n')
_CUR_DIR = os.path.dirname(os.path.abspath(__file__))
def iter_find_files(directory, patterns, ignored=None):
"""\
Finds files under a `directory`, matching `patterns` using "glob"
syntax (e.g., "*.txt"). It's also possible to ignore patterns with
the `ignored` argument, which uses the same format as `patterns.
>>> filenames = sorted(iter_find_files(_CUR_DIR, '*.py'))
>>> filenames[-1].split('/')[-1]
'tzutils.py'
>>> filenames = iter_find_files(_CUR_DIR, '*.py', ignored='.#*')
That last example ignores emacs lockfiles.
"""
if isinstance(patterns, basestring):
patterns = [patterns]
pats_re = re.compile('|'.join([fnmatch.translate(p) for p in patterns]))
if not ignored:
ignored = []
elif isinstance(ignored, basestring):
ignored = [ignored]
ign_re = re.compile('|'.join([fnmatch.translate(p) for p in ignored]))
for root, dirs, files in os.walk(directory):
for basename in files:
if pats_re.match(basename):
if ignored and ign_re.match(basename):
continue
filename = os.path.join(root, basename)
yield filename
return
def mkdir_p(path):
try:
os.makedirs(path)
except OSError as exc:
if exc.errno == errno.EEXIST and os.path.isdir(path):
return
raise
return
def copytree(src, dst, symlinks=False, ignore=None):
"""Recursively copy a directory tree using copy2().
The destination directory is allowed to already exist.
If exception(s) occur, an Error is raised with a list of reasons.
If the optional symlinks flag is true, symbolic links in the
source tree result in symbolic links in the destination tree; if
it is false, the contents of the files pointed to by symbolic
links are copied.
The optional ignore argument is a callable. If given, it
is called with the `src` parameter, which is the directory
being visited by copytree(), and `names` which is the list of
`src` contents, as returned by os.listdir():
callable(src, names) -> ignored_names
Since copytree() is called recursively, the callable will be
called once for each directory that is copied. It returns a
list of names relative to the `src` directory that should
not be copied.
XXX Consider this example code rather than the ultimate tool.
"""
names = os.listdir(src)
if ignore is not None:
ignored_names = ignore(src, names)
else:
ignored_names = set()
mkdir_p(dst)
errors = []
for name in names:
if name in ignored_names:
continue
srcname = os.path.join(src, name)
dstname = os.path.join(dst, name)
try:
if symlinks and os.path.islink(srcname):
linkto = os.readlink(srcname)
os.symlink(linkto, dstname)
elif os.path.isdir(srcname):
copytree(srcname, dstname, symlinks, ignore)
else:
# Will raise a SpecialFileError for unsupported file types
copy2(srcname, dstname)
# catch the Error from the recursive copytree so that we can
# continue with other files
except Error as e:
errors.extend(e.args[0])
except EnvironmentError, why:
errors.append((srcname, dstname, str(why)))
try:
copystat(src, dst)
except OSError, why:
if WindowsError is not None and isinstance(why, WindowsError):
# Copying file access times may fail on Windows
pass
else:
errors.append((src, dst, str(why)))
if errors:
raise Error(errors)
if __name__ == '__main__':
#with atomic_save('/tmp/final.txt') as f:
# f.write('rofl')
# raise ValueError('nope')
# f.write('\n')
def _main():
up = FilePerms()

View File

@ -1,117 +1,4 @@
# -*- coding: utf-8 -*-
import os
import re
import errno
import fnmatch
from shutil import copy2, copystat, Error
_CUR_DIR = os.path.dirname(os.path.abspath(__file__))
def iter_find_files(directory, patterns, ignored=None):
"""\
Finds files under a `directory`, matching `patterns` using "glob"
syntax (e.g., "*.txt"). It's also possible to ignore patterns with
the `ignored` argument, which uses the same format as `patterns.
>>> filenames = sorted(iter_find_files(_CUR_DIR, '*.py'))
>>> filenames[-1].split('/')[-1]
'tzutils.py'
>>> filenames = iter_find_files(_CUR_DIR, '*.py', ignored='.#*')
That last example ignores emacs lockfiles.
"""
if isinstance(patterns, basestring):
patterns = [patterns]
pats_re = re.compile('|'.join([fnmatch.translate(p) for p in patterns]))
if not ignored:
ignored = []
elif isinstance(ignored, basestring):
ignored = [ignored]
ign_re = re.compile('|'.join([fnmatch.translate(p) for p in ignored]))
for root, dirs, files in os.walk(directory):
for basename in files:
if pats_re.match(basename):
if ignored and ign_re.match(basename):
continue
filename = os.path.join(root, basename)
yield filename
return
def mkdir_p(path):
try:
os.makedirs(path)
except OSError as exc:
if exc.errno == errno.EEXIST and os.path.isdir(path):
return
raise
return
def copytree(src, dst, symlinks=False, ignore=None):
"""Recursively copy a directory tree using copy2().
The destination directory is allowed to already exist.
If exception(s) occur, an Error is raised with a list of reasons.
If the optional symlinks flag is true, symbolic links in the
source tree result in symbolic links in the destination tree; if
it is false, the contents of the files pointed to by symbolic
links are copied.
The optional ignore argument is a callable. If given, it
is called with the `src` parameter, which is the directory
being visited by copytree(), and `names` which is the list of
`src` contents, as returned by os.listdir():
callable(src, names) -> ignored_names
Since copytree() is called recursively, the callable will be
called once for each directory that is copied. It returns a
list of names relative to the `src` directory that should
not be copied.
XXX Consider this example code rather than the ultimate tool.
"""
names = os.listdir(src)
if ignore is not None:
ignored_names = ignore(src, names)
else:
ignored_names = set()
mkdir_p(dst)
errors = []
for name in names:
if name in ignored_names:
continue
srcname = os.path.join(src, name)
dstname = os.path.join(dst, name)
try:
if symlinks and os.path.islink(srcname):
linkto = os.readlink(srcname)
os.symlink(linkto, dstname)
elif os.path.isdir(srcname):
copytree(srcname, dstname, symlinks, ignore)
else:
# Will raise a SpecialFileError for unsupported file types
copy2(srcname, dstname)
# catch the Error from the recursive copytree so that we can
# continue with other files
except Error as e:
errors.extend(e.args[0])
except EnvironmentError, why:
errors.append((srcname, dstname, str(why)))
try:
copystat(src, dst)
except OSError, why:
if WindowsError is not None and isinstance(why, WindowsError):
# Copying file access times may fail on Windows
pass
else:
errors.append((src, dst, str(why)))
if errors:
raise Error(errors)
print 'Deprecation warning: the contents of osutils have moved to fileutils'
from fileutils import *