1
1
Fork 0
mirror of https://github.com/pypa/pip synced 2023-12-13 21:30:23 +01:00

Refactor tests.lib.path a bit

* Add a .join() method for a more explicit joining than /
* Return values where possible
* Make glob an iterator
* Remove checks for versions of Python we don't support
* Add a write() function to make it simple to write some text
  into a file
* Add a touch() function to make it simple to ensure a file
  exists
This commit is contained in:
Donald Stufft 2013-08-18 22:40:20 -04:00
parent ad0191f79a
commit 30934fede2
2 changed files with 154 additions and 68 deletions

View file

@ -218,9 +218,9 @@ class TestPipResult(object):
egg_link_file.bytes)))) egg_link_file.bytes))))
if use_user_site: if use_user_site:
pth_file = Path.string(e.user_site / 'easy-install.pth') pth_file = e.user_site/'easy-install.pth'
else: else:
pth_file = Path.string(e.site_packages / 'easy-install.pth') pth_file = e.site_packages/'easy-install.pth'
if (pth_file in self.files_updated) == without_egg_link: if (pth_file in self.files_updated) == without_egg_link:
raise TestFailure('%r unexpectedly %supdated by install' % ( raise TestFailure('%r unexpectedly %supdated by install' % (
@ -232,7 +232,7 @@ class TestPipResult(object):
actually created: actually created:
%s %s
''') % ( ''') % (
Path.string(pkg_dir), pkg_dir,
(curdir in without_files and 'not ' or ''), (curdir in without_files and 'not ' or ''),
sorted(self.files_created.keys()))) sorted(self.files_created.keys())))
@ -408,8 +408,7 @@ class TestPipEnvironment(TestFileEnvironment):
cwd = kw.pop('cwd', None) cwd = kw.pop('cwd', None)
run_from = kw.pop('run_from', None) run_from = kw.pop('run_from', None)
assert not cwd or not run_from, "Don't use run_from; it's going away" assert not cwd or not run_from, "Don't use run_from; it's going away"
cwd = Path.string(cwd or run_from or self.cwd) cwd = cwd or run_from or self.cwd
assert not isinstance(cwd, Path)
return TestPipResult(super(TestPipEnvironment, self).run(cwd=cwd, *args, **kw), verbose=self.verbose) return TestPipResult(super(TestPipEnvironment, self).run(cwd=cwd, *args, **kw), verbose=self.verbose)
def _use_cached_pypi_server(self): def _use_cached_pypi_server(self):

View file

@ -1,9 +1,15 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Author: Aziz Köksal # Author: Aziz Köksal
import glob
import os import os
import sys import sys
import shutil import shutil
try:
from os import supports_fd
except ImportError:
supports_fd = set()
if sys.version_info >= (3,): if sys.version_info >= (3,):
unicode = str unicode = str
u = str u = str
@ -13,15 +19,17 @@ else:
_base = os.path.supports_unicode_filenames and unicode or str _base = os.path.supports_unicode_filenames and unicode or str
from pip.util import rmtree
class Path(_base): class Path(_base):
""" Models a path in an object oriented way. """ """
Models a path in an object oriented way.
"""
sep = os.sep # File system path separator: '/' or '\'. # File system path separator: '/' or '\'.
pathsep = os.pathsep # Separator in the PATH environment variable. sep = os.sep
string = _base
# Separator in the PATH environment variable.
pathsep = os.pathsep
def __new__(cls, *paths): def __new__(cls, *paths):
if len(paths): if len(paths):
@ -29,49 +37,74 @@ class Path(_base):
return _base.__new__(cls) return _base.__new__(cls)
def __div__(self, path): def __div__(self, path):
""" Joins this path with another path. """ """
""" path_obj / 'bc.d' """ Joins this path with another path.
""" path_obj / path_obj2 """
>>> path_obj / 'bc.d'
>>> path_obj / path_obj2
"""
return Path(self, path) return Path(self, path)
__truediv__ = __div__ __truediv__ = __div__
def __rdiv__(self, path): def __rdiv__(self, path):
""" Joins this path with another path. """ """
""" "/home/a" / path_obj """ Joins this path with another path.
>>> "/home/a" / path_obj
"""
return Path(path, self) return Path(path, self)
__rtruediv__ = __rdiv__ __rtruediv__ = __rdiv__
def __idiv__(self, path): def __idiv__(self, path):
""" Like __div__ but also assigns to the variable. """ """
""" path_obj /= 'bc.d' """ Like __div__ but also assigns to the variable.
>>> path_obj /= 'bc.d'
"""
return Path(self, path) return Path(self, path)
__itruediv__ = __idiv__ __itruediv__ = __idiv__
def __floordiv__(self, paths): def __floordiv__(self, paths):
""" Returns a list of paths prefixed with 'self'. """ """
""" '/home/a' // [bc.d, ef.g] -> [/home/a/bc.d, /home/a/ef.g] """ Returns a list of paths prefixed with 'self'.
>>> '/home/a' // [bc.d, ef.g]
[/home/a/bc.d, /home/a/ef.g]
"""
return [Path(self, path) for path in paths] return [Path(self, path) for path in paths]
def __sub__(self, path): def __sub__(self, path):
""" Makes this path relative to another path. """ """
""" path_obj - '/home/a' """ Makes this path relative to another path.
""" path_obj - path_obj2 """
>>> path_obj - '/home/a'
>>> path_obj - path_obj2
"""
return Path(os.path.relpath(self, path)) return Path(os.path.relpath(self, path))
def __rsub__(self, path): def __rsub__(self, path):
""" Returns path relative to this path. """ """
""" "/home/a" - path_obj """ Returns path relative to this path.
>>> "/home/a" - path_obj
"""
return Path(os.path.relpath(path, self)) return Path(os.path.relpath(path, self))
def __add__(self, path): def __add__(self, path):
""" Path('/home/a') + 'bc.d' -> '/home/abc.d' """ """
>>> Path('/home/a') + 'bc.d'
'/home/abc.d'
"""
return Path(_base(self) + path) return Path(_base(self) + path)
def __radd__(self, path): def __radd__(self, path):
""" '/home/a' + Path('bc.d') -> '/home/abc.d' """ """
>>> '/home/a' + Path('bc.d')
'/home/abc.d'
"""
return Path(path + _base(self)) return Path(path + _base(self))
def __repr__(self): def __repr__(self):
@ -82,128 +115,182 @@ class Path(_base):
@property @property
def name(self): def name(self):
""" '/home/a/bc.d' -> 'bc.d' """ """
'/home/a/bc.d' -> 'bc.d'
"""
return os.path.basename(self) return os.path.basename(self)
@property @property
def namebase(self): def namebase(self):
""" '/home/a/bc.d' -> 'bc' """ """
'/home/a/bc.d' -> 'bc'
"""
return self.noext.name return self.noext.name
@property @property
def noext(self): def noext(self):
""" '/home/a/bc.d' -> '/home/a/bc' """ """
'/home/a/bc.d' -> '/home/a/bc'
"""
return Path(os.path.splitext(self)[0]) return Path(os.path.splitext(self)[0])
@property @property
def ext(self): def ext(self):
""" '/home/a/bc.d' -> '.d' """ """
'/home/a/bc.d' -> '.d'
"""
return Path(os.path.splitext(self)[1]) return Path(os.path.splitext(self)[1])
@property @property
def abspath(self): def abspath(self):
""" './a/bc.d' -> '/home/a/bc.d' """ """
'./a/bc.d' -> '/home/a/bc.d'
"""
return Path(os.path.abspath(self)) return Path(os.path.abspath(self))
@property @property
def realpath(self): def realpath(self):
""" Resolves symbolic links. """ """
Resolves symbolic links.
"""
return Path(os.path.realpath(self)) return Path(os.path.realpath(self))
@property @property
def normpath(self): def normpath(self):
""" '/home/x/.././a//bc.d' -> '/home/a/bc.d' """ """
'/home/x/.././a//bc.d' -> '/home/a/bc.d'
"""
return Path(os.path.normpath(self)) return Path(os.path.normpath(self))
@property @property
def normcase(self): def normcase(self):
""" Deals with case-insensitive filesystems """ """
Deals with case-insensitive filesystems
"""
return Path(os.path.normcase(self)) return Path(os.path.normcase(self))
@property @property
def folder(self): def folder(self):
""" Returns the folder of this path. """ """
""" '/home/a/bc.d' -> '/home/a' """ Returns the folder of this path.
""" '/home/a/' -> '/home/a' """
""" '/home/a' -> '/home' """ '/home/a/bc.d' -> '/home/a'
'/home/a/' -> '/home/a'
'/home/a' -> '/home'
"""
return Path(os.path.dirname(self)) return Path(os.path.dirname(self))
@property @property
def exists(self): def exists(self):
""" Returns True if the path exists. """ """
Returns True if the path exists.
"""
return os.path.exists(self) return os.path.exists(self)
@property @property
def atime(self): def atime(self):
""" Returns last accessed time. """ """
Returns last accessed time.
"""
return os.path.getatime(self) return os.path.getatime(self)
@property @property
def mtime(self): def mtime(self):
""" Returns last modified time. """ """
Returns last modified time.
"""
return os.path.getmtime(self) return os.path.getmtime(self)
@property @property
def ctime(self): def ctime(self):
""" Returns last changed time. """ """
Returns last changed time.
"""
return os.path.getctime(self) return os.path.getctime(self)
@classmethod @classmethod
def supports_unicode(self): def supports_unicode(self):
""" Returns True if the system can handle Unicode file names. """ """
Returns True if the system can handle Unicode file names.
"""
return os.path.supports_unicode_filenames() return os.path.supports_unicode_filenames()
def walk(self, **kwargs): def walk(self, **kwargs):
""" Returns a generator that walks through a directory tree. """ """ Returns a generator that walks through a directory tree. """
if "followlinks" in kwargs:
from sys import version_info as vi
if vi[0]*10+vi[1] < 26: # Only Python 2.6 or newer supports followlinks
del kwargs["followlinks"]
return os.walk(self, **kwargs) return os.walk(self, **kwargs)
def mkdir(self, mode=0x1FF): # 0o777 def mkdir(self, mode=0x1FF): # 0o777
""" Creates a directory, if it doesn't exist already. """ """
Creates a directory, if it doesn't exist already.
"""
if not self.exists: if not self.exists:
os.mkdir(self, mode) os.mkdir(self, mode)
return self
def makedirs(self, mode=0x1FF): # 0o777 def makedirs(self, mode=0x1FF): # 0o777
""" Like mkdir(), but also creates parent directories. """ """
Like mkdir(), but also creates parent directories.
"""
if not self.exists: if not self.exists:
os.makedirs(self, mode) os.makedirs(self, mode)
return self
def remove(self): def remove(self):
""" Removes a file. """ """
os.remove(self) Removes a file.
"""
return os.remove(self)
rm = remove # Alias. rm = remove # Alias.
def rmdir(self): def rmdir(self):
""" Removes a directory. """ """
Removes a directory.
"""
return os.rmdir(self) return os.rmdir(self)
def rmtree(self, noerrors=True): def rmtree(self, noerrors=True):
""" Removes a directory tree. Ignores errors by default. """ """
return rmtree(self, ignore_errors=noerrors) Removes a directory tree. Ignores errors by default.
"""
return shutil.rmtree(self, ignore_errors=noerrors)
def copy(self, to): def copy(self, to):
shutil.copy(self, to) return shutil.copy(self, to)
def copytree(self, to): def copytree(self, to):
""" Copies a directory tree to another path. """ """
shutil.copytree(self, to) Copies a directory tree to another path.
"""
return shutil.copytree(self, to)
def move(self, to): def move(self, to):
""" Moves a file or directory to another path. """ """
shutil.move(self, to) Moves a file or directory to another path.
"""
return shutil.move(self, to)
def rename(self, to): def rename(self, to):
""" Renames a file or directory. May throw an OSError. """ """
os.rename(self, to) Renames a file or directory. May throw an OSError.
"""
return os.rename(self, to)
def renames(self, to): def renames(self, to):
os.renames(self, to) return os.renames(self, to)
def glob(self, pattern): def glob(self, pattern):
from glob import glob return (Path(i) for i in glob.iglob(self.join(pattern)))
return list(map(Path, glob(_base(self/pattern))))
def join(self, *parts):
return Path(self, *parts)
def write(self, content):
with open(self, "w") as fp:
fp.write(content)
def touch(self, times=None):
with open(self, "a") as fp:
os.utime(fp.fileno() if os.utime in supports_fd else self, times)
curdir = Path(os.path.curdir) curdir = Path(os.path.curdir)