From 4c89e07ac5721744f41a938037a7285e6de9b1e0 Mon Sep 17 00:00:00 2001 From: Robert Collins Date: Tue, 31 Mar 2015 14:40:30 +1300 Subject: [PATCH] Create ensure_dir helper. We had a very widely used pattern which can be factored out for a mild saving in LOC, and a gain in clarity. --- pip/commands/install.py | 4 ++-- pip/commands/zip.py | 8 +++----- pip/req/req_install.py | 5 ++--- pip/req/req_set.py | 6 +++--- pip/utils/__init__.py | 32 +++++++++++++++++++------------- pip/utils/logging.py | 6 ++---- pip/utils/outdated.py | 8 ++------ pip/wheel.py | 9 ++++----- 8 files changed, 37 insertions(+), 41 deletions(-) diff --git a/pip/commands/install.py b/pip/commands/install.py index dfac045a844..458772c4556 100644 --- a/pip/commands/install.py +++ b/pip/commands/install.py @@ -16,6 +16,7 @@ InstallationError, CommandError, PreviousBuildDirError, ) from pip import cmdoptions +from pip.utils import ensure_dir from pip.utils.build import BuildDirectory from pip.utils.deprecation import RemovedInPip7Warning, RemovedInPip8Warning @@ -361,8 +362,7 @@ def run(self, options, args): requirement_set.cleanup_files() if options.target_dir: - if not os.path.exists(options.target_dir): - os.makedirs(options.target_dir) + ensure_dir(options.target_dir) lib_dir = distutils_scheme('', home=temp_target_dir)['purelib'] diff --git a/pip/commands/zip.py b/pip/commands/zip.py index 078c5ffad6e..135455b8c62 100644 --- a/pip/commands/zip.py +++ b/pip/commands/zip.py @@ -9,7 +9,7 @@ import warnings import zipfile -from pip.utils import display_path, backup_dir, rmtree +from pip.utils import display_path, ensure_dir, backup_dir, rmtree from pip.utils.deprecation import RemovedInPip7Warning from pip.utils.logging import indent_log from pip.exceptions import InstallationError @@ -183,11 +183,9 @@ def unzip_package(self, module_name, filename): if name.startswith(module_name + os.path.sep): content = zip.read(name) dest = os.path.join(package_path, name) - if not os.path.exists(os.path.dirname(dest)): - os.makedirs(os.path.dirname(dest)) + ensure_dir(os.path.dirname(dest)) if not content and dest.endswith(os.path.sep): - if not os.path.exists(dest): - os.makedirs(dest) + ensure_dir(os.path.dirname(dest)) else: with open(dest, 'wb') as f: f.write(content) diff --git a/pip/req/req_install.py b/pip/req/req_install.py index 8ed5e347a00..d27efc4cfa7 100644 --- a/pip/req/req_install.py +++ b/pip/req/req_install.py @@ -31,7 +31,7 @@ from pip.utils import ( display_path, rmtree, ask_path_exists, backup_dir, is_installable_dir, dist_in_usersite, dist_in_site_packages, egg_link_path, make_path_relative, - call_subprocess, read_text_file, FakeFile, _make_build_dir, + call_subprocess, read_text_file, FakeFile, _make_build_dir, ensure_dir, ) from pip.utils.deprecation import RemovedInPip8Warning from pip.utils.logging import indent_log @@ -391,8 +391,7 @@ def run_egg_info(self): egg_base_option = [] else: egg_info_dir = os.path.join(self.source_dir, 'pip-egg-info') - if not os.path.exists(egg_info_dir): - os.makedirs(egg_info_dir) + ensure_dir(egg_info_dir) egg_base_option = ['--egg-base', 'pip-egg-info'] cwd = self.source_dir if self.editable_options and \ diff --git a/pip/req/req_set.py b/pip/req/req_set.py index 0a2bddc519a..6fe593234e6 100644 --- a/pip/req/req_set.py +++ b/pip/req/req_set.py @@ -14,7 +14,8 @@ DistributionNotFound, PreviousBuildDirError) from pip.locations import (PIP_DELETE_MARKER_FILENAME, build_prefix) from pip.req.req_install import InstallRequirement -from pip.utils import (display_path, rmtree, dist_in_usersite, normalize_path) +from pip.utils import ( + ensure_dir, display_path, rmtree, dist_in_usersite, normalize_path) from pip.utils.logging import indent_log from pip.vcs import vcs @@ -343,8 +344,7 @@ def prepare_files(self, finder): """ # make the wheelhouse if self.wheel_download_dir: - if not os.path.exists(self.wheel_download_dir): - os.makedirs(self.wheel_download_dir) + ensure_dir(self.wheel_download_dir) self._walk_req_to_install( functools.partial(self._prepare_file, finder)) diff --git a/pip/utils/__init__.py b/pip/utils/__init__.py index 1535c9c72f8..d9ea6affa01 100644 --- a/pip/utils/__init__.py +++ b/pip/utils/__init__.py @@ -1,6 +1,7 @@ from __future__ import absolute_import import contextlib +import errno import locale import logging import re @@ -38,7 +39,7 @@ 'make_path_relative', 'normalize_path', 'renames', 'get_terminal_size', 'get_prog', 'unzip_file', 'untar_file', 'unpack_file', 'call_subprocess', - 'captured_stdout', 'remove_tracebacks'] + 'captured_stdout', 'remove_tracebacks', 'ensure_dir'] logger = logging.getLogger(__name__) @@ -51,6 +52,17 @@ def import_or_raise(pkg_or_module_string, ExceptionType, *args, **kwargs): raise ExceptionType(*args, **kwargs) +def ensure_dir(path): + """os.path.makedirs without EEXIST.""" + try: + os.makedirs(path) + except OSError as e: + if e.errno == errno.EEXIST: + pass + else: + raise + + def get_prog(): try: if os.path.basename(sys.argv[0]) in ('__main__.py', '-c'): @@ -502,8 +514,7 @@ def unzip_file(filename, location, flatten=True): written. Note that for windows, any execute changes using os.chmod are no-ops per the python docs. """ - if not os.path.exists(location): - os.makedirs(location) + ensure_dir(location) zipfp = open(filename, 'rb') try: zip = zipfile.ZipFile(zipfp, allowZip64=True) @@ -516,13 +527,11 @@ def unzip_file(filename, location, flatten=True): fn = split_leading_dir(name)[1] fn = os.path.join(location, fn) dir = os.path.dirname(fn) - if not os.path.exists(dir): - os.makedirs(dir) if fn.endswith('/') or fn.endswith('\\'): # A directory - if not os.path.exists(fn): - os.makedirs(fn) + ensure_dir(fn) else: + ensure_dir(dir) fp = open(fn, 'wb') try: fp.write(data) @@ -548,8 +557,7 @@ def untar_file(filename, location): written. Note that for windows, any execute changes using os.chmod are no-ops per the python docs. """ - if not os.path.exists(location): - os.makedirs(location) + ensure_dir(location) if filename.lower().endswith('.gz') or filename.lower().endswith('.tgz'): mode = 'r:gz' elif (filename.lower().endswith('.bz2') or @@ -577,8 +585,7 @@ def untar_file(filename, location): fn = split_leading_dir(fn)[1] path = os.path.join(location, fn) if member.isdir(): - if not os.path.exists(path): - os.makedirs(path) + ensure_dir(path) elif member.issym(): try: tar._extract_member(member, path) @@ -601,8 +608,7 @@ def untar_file(filename, location): filename, member.name, exc, ) continue - if not os.path.exists(os.path.dirname(path)): - os.makedirs(os.path.dirname(path)) + ensure_dir(os.path.dirname(path)) destfp = open(path, 'wb') try: shutil.copyfileobj(fp, destfp) diff --git a/pip/utils/logging.py b/pip/utils/logging.py index e2467d8ffd6..865df4b30c4 100644 --- a/pip/utils/logging.py +++ b/pip/utils/logging.py @@ -11,6 +11,7 @@ import dummy_threading as threading from pip.compat import WINDOWS +from pip.utils import ensure_dir try: from pip._vendor import colorama @@ -114,8 +115,5 @@ def format(self, record): class BetterRotatingFileHandler(logging.handlers.RotatingFileHandler): def _open(self): - # Ensure the directory exists - if not os.path.exists(os.path.dirname(self.baseFilename)): - os.makedirs(os.path.dirname(self.baseFilename)) - + ensure_dir(os.path.dirname(self.baseFilename)) return logging.handlers.RotatingFileHandler._open(self) diff --git a/pip/utils/outdated.py b/pip/utils/outdated.py index f995cf718fe..53d3139e6bc 100644 --- a/pip/utils/outdated.py +++ b/pip/utils/outdated.py @@ -1,7 +1,6 @@ from __future__ import absolute_import import datetime -import errno import json import logging import os.path @@ -13,6 +12,7 @@ from pip.compat import total_seconds from pip.index import PyPI from pip.locations import USER_CACHE_DIR, running_under_virtualenv +from pip.utils import ensure_dir from pip.utils.filesystem import check_path_owner @@ -65,11 +65,7 @@ def save(self, pypi_version, current_time): # Now that we've ensured the directory is owned by this user, we'll go # ahead and make sure that all our directories are created. - try: - os.makedirs(os.path.dirname(self.statefile_path)) - except OSError as exc: - if exc.errno != errno.EEXIST: - raise + ensure_dir(self.statefile_path) # Attempt to write out our version check file with lockfile.LockFile(self.statefile_path): diff --git a/pip/wheel.py b/pip/wheel.py index 55b41b11f4a..d689903fc57 100644 --- a/pip/wheel.py +++ b/pip/wheel.py @@ -23,7 +23,8 @@ from pip.exceptions import InvalidWheelFilename, UnsupportedWheel from pip.locations import distutils_scheme from pip import pep425tags -from pip.utils import call_subprocess, make_path_relative, captured_stdout +from pip.utils import ( + call_subprocess, ensure_dir, make_path_relative, captured_stdout) from pip.utils.logging import indent_log from pip._vendor.distlib.scripts import ScriptMaker from pip._vendor import pkg_resources @@ -174,8 +175,7 @@ def record_installed(srcfile, destfile, modified=False): changed.add(destfile) def clobber(source, dest, is_base, fixer=None, filter=None): - if not os.path.exists(dest): # common for the 'include' path - os.makedirs(dest) + ensure_dir(dest) # common for the 'include' path for dir, subdirs, files in os.walk(source): basedir = dir[len(source):].lstrip(os.path.sep) @@ -203,8 +203,7 @@ def clobber(source, dest, is_base, fixer=None, filter=None): # directory creation is lazy and after the file filtering above # to ensure we don't install empty dirs; empty dirs can't be # uninstalled. - if not os.path.exists(destdir): - os.makedirs(destdir) + ensure_dir(destdir) # We use copyfile (not move, copy, or copy2) to be extra sure # that we are not moving directories over (copyfile fails for