aboutsummaryrefslogtreecommitdiffstats
path: root/lib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/python/filepath.py
diff options
context:
space:
mode:
Diffstat (limited to 'lib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/python/filepath.py')
-rwxr-xr-xlib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/python/filepath.py1442
1 files changed, 0 insertions, 1442 deletions
diff --git a/lib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/python/filepath.py b/lib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/python/filepath.py
deleted file mode 100755
index a4016d6d..00000000
--- a/lib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/python/filepath.py
+++ /dev/null
@@ -1,1442 +0,0 @@
-# -*- test-case-name: twisted.test.test_paths -*-
-# Copyright (c) Twisted Matrix Laboratories.
-# See LICENSE for details.
-
-"""
-Object-oriented filesystem path representation.
-"""
-
-import os
-import errno
-import random
-import base64
-
-from os.path import isabs, exists, normpath, abspath, splitext
-from os.path import basename, dirname
-from os.path import join as joinpath
-from os import sep as slash
-from os import listdir, utime, stat
-
-from stat import S_ISREG, S_ISDIR, S_IMODE, S_ISBLK, S_ISSOCK
-from stat import S_IRUSR, S_IWUSR, S_IXUSR
-from stat import S_IRGRP, S_IWGRP, S_IXGRP
-from stat import S_IROTH, S_IWOTH, S_IXOTH
-
-
-# Please keep this as light as possible on other Twisted imports; many, many
-# things import this module, and it would be good if it could easily be
-# modified for inclusion in the standard library. --glyph
-
-from twisted.python.runtime import platform
-from twisted.python.hashlib import sha1
-
-from twisted.python.win32 import ERROR_FILE_NOT_FOUND, ERROR_PATH_NOT_FOUND
-from twisted.python.win32 import ERROR_INVALID_NAME, ERROR_DIRECTORY, O_BINARY
-from twisted.python.win32 import WindowsError
-
-from twisted.python.util import FancyEqMixin
-
-from zope.interface import Interface, Attribute, implements
-
-_CREATE_FLAGS = (os.O_EXCL |
- os.O_CREAT |
- os.O_RDWR |
- O_BINARY)
-
-
-def _stub_islink(path):
- """
- Always return 'false' if the operating system does not support symlinks.
-
- @param path: a path string.
- @type path: L{str}
- @return: false
- """
- return False
-
-
-def _stub_urandom(n):
- """
- Provide random data in versions of Python prior to 2.4. This is an
- effectively compatible replacement for 'os.urandom'.
-
- @type n: L{int}
- @param n: the number of bytes of data to return
- @return: C{n} bytes of random data.
- @rtype: str
- """
- randomData = [random.randrange(256) for n in xrange(n)]
- return ''.join(map(chr, randomData))
-
-
-def _stub_armor(s):
- """
- ASCII-armor for random data. This uses a hex encoding, although we will
- prefer url-safe base64 encoding for features in this module if it is
- available.
- """
- return s.encode('hex')
-
-islink = getattr(os.path, 'islink', _stub_islink)
-randomBytes = getattr(os, 'urandom', _stub_urandom)
-armor = getattr(base64, 'urlsafe_b64encode', _stub_armor)
-
-class IFilePath(Interface):
- """
- File path object.
-
- A file path represents a location for a file-like-object and can be
- organized into a hierarchy; a file path can can children which are
- themselves file paths.
-
- A file path has a name which unique identifies it in the context of its
- parent (if it has one); a file path can not have two children with the same
- name. This name is referred to as the file path's "base name".
-
- A series of such names can be used to locate nested children of a file path;
- such a series is referred to as the child's "path", relative to the parent.
- In this case, each name in the path is referred to as a "path segment"; the
- child's base name is the segment in the path.
-
- When representing a file path as a string, a "path separator" is used to
- delimit the path segments within the string. For a file system path, that
- would be C{os.sep}.
-
- Note that the values of child names may be restricted. For example, a file
- system path will not allow the use of the path separator in a name, and
- certain names (eg. C{"."} and C{".."}) may be reserved or have special
- meanings.
-
- @since: 12.1
- """
- sep = Attribute("The path separator to use in string representations")
-
- def child(name):
- """
- Obtain a direct child of this file path. The child may or may not
- exist.
-
- @param name: the name of a child of this path. C{name} must be a direct
- child of this path and may not contain a path separator.
- @return: the child of this path with the given C{name}.
- @raise InsecurePath: if C{name} describes a file path that is not a
- direct child of this file path.
- """
-
- def open(mode="r"):
- """
- Opens this file path with the given mode.
- @return: a file-like-object.
- @raise Exception: if this file path cannot be opened.
- """
-
- def changed():
- """
- Clear any cached information about the state of this path on disk.
- """
-
- def getsize():
- """
- @return: the size of the file at this file path in bytes.
- @raise Exception: if the size cannot be obtained.
- """
-
- def getModificationTime():
- """
- Retrieve the time of last access from this file.
-
- @return: a number of seconds from the epoch.
- @rtype: float
- """
-
- def getStatusChangeTime():
- """
- Retrieve the time of the last status change for this file.
-
- @return: a number of seconds from the epoch.
- @rtype: float
- """
-
- def getAccessTime():
- """
- Retrieve the time that this file was last accessed.
-
- @return: a number of seconds from the epoch.
- @rtype: float
- """
-
- def exists():
- """
- @return: C{True} if the file at this file path exists, C{False}
- otherwise.
- """
-
- def isdir():
- """
- @return: C{True} if the file at this file path is a directory, C{False}
- otherwise.
- """
-
- def isfile():
- """
- @return: C{True} if the file at this file path is a regular file,
- C{False} otherwise.
- """
-
- def children():
- """
- @return: a sequence of the children of the directory at this file path.
- @raise Exception: if the file at this file path is not a directory.
- """
-
- def basename():
- """
- @return: the base name of this file path.
- """
-
- def parent():
- """
- A file path for the directory containing the file at this file path.
- """
-
- def sibling(name):
- """
- A file path for the directory containing the file at this file path.
- @param name: the name of a sibling of this path. C{name} must be a direct
- sibling of this path and may not contain a path separator.
-
- @return: a sibling file path of this one.
- """
-
-class InsecurePath(Exception):
- """
- Error that is raised when the path provided to FilePath is invalid.
- """
-
-
-
-class LinkError(Exception):
- """
- An error with symlinks - either that there are cyclical symlinks or that
- symlink are not supported on this platform.
- """
-
-
-
-class UnlistableError(OSError):
- """
- An exception which is used to distinguish between errors which mean 'this
- is not a directory you can list' and other, more catastrophic errors.
-
- This error will try to look as much like the original error as possible,
- while still being catchable as an independent type.
-
- @ivar originalException: the actual original exception instance, either an
- L{OSError} or a L{WindowsError}.
- """
- def __init__(self, originalException):
- """
- Create an UnlistableError exception.
-
- @param originalException: an instance of OSError.
- """
- self.__dict__.update(originalException.__dict__)
- self.originalException = originalException
-
-
-
-class _WindowsUnlistableError(UnlistableError, WindowsError):
- """
- This exception is raised on Windows, for compatibility with previous
- releases of FilePath where unportable programs may have done "except
- WindowsError:" around a call to children().
-
- It is private because all application code may portably catch
- L{UnlistableError} instead.
- """
-
-
-
-def _secureEnoughString():
- """
- Create a pseudorandom, 16-character string for use in secure filenames.
- """
- return armor(sha1(randomBytes(64)).digest())[:16]
-
-
-
-class AbstractFilePath(object):
- """
- Abstract implementation of an IFilePath; must be completed by a subclass.
-
- This class primarily exists to provide common implementations of certain
- methods in IFilePath. It is *not* a required parent class for IFilePath
- implementations, just a useful starting point.
- """
-
- def getContent(self):
- fp = self.open()
- try:
- return fp.read()
- finally:
- fp.close()
-
-
- def parents(self):
- """
- @return: an iterator of all the ancestors of this path, from the most
- recent (its immediate parent) to the root of its filesystem.
- """
- path = self
- parent = path.parent()
- # root.parent() == root, so this means "are we the root"
- while path != parent:
- yield parent
- path = parent
- parent = parent.parent()
-
-
- def children(self):
- """
- List the children of this path object.
-
- @raise OSError: If an error occurs while listing the directory. If the
- error is 'serious', meaning that the operation failed due to an access
- violation, exhaustion of some kind of resource (file descriptors or
- memory), OSError or a platform-specific variant will be raised.
-
- @raise UnlistableError: If the inability to list the directory is due
- to this path not existing or not being a directory, the more specific
- OSError subclass L{UnlistableError} is raised instead.
-
- @return: an iterable of all currently-existing children of this object
- accessible with L{_PathHelper.child}.
- """
- try:
- subnames = self.listdir()
- except WindowsError, winErrObj:
- # WindowsError is an OSError subclass, so if not for this clause
- # the OSError clause below would be handling these. Windows error
- # codes aren't the same as POSIX error codes, so we need to handle
- # them differently.
-
- # Under Python 2.5 on Windows, WindowsError has a winerror
- # attribute and an errno attribute. The winerror attribute is
- # bound to the Windows error code while the errno attribute is
- # bound to a translation of that code to a perhaps equivalent POSIX
- # error number.
-
- # Under Python 2.4 on Windows, WindowsError only has an errno
- # attribute. It is bound to the Windows error code.
-
- # For simplicity of code and to keep the number of paths through
- # this suite minimal, we grab the Windows error code under either
- # version.
-
- # Furthermore, attempting to use os.listdir on a non-existent path
- # in Python 2.4 will result in a Windows error code of
- # ERROR_PATH_NOT_FOUND. However, in Python 2.5,
- # ERROR_FILE_NOT_FOUND results instead. -exarkun
- winerror = getattr(winErrObj, 'winerror', winErrObj.errno)
- if winerror not in (ERROR_PATH_NOT_FOUND,
- ERROR_FILE_NOT_FOUND,
- ERROR_INVALID_NAME,
- ERROR_DIRECTORY):
- raise
- raise _WindowsUnlistableError(winErrObj)
- except OSError, ose:
- if ose.errno not in (errno.ENOENT, errno.ENOTDIR):
- # Other possible errors here, according to linux manpages:
- # EACCES, EMIFLE, ENFILE, ENOMEM. None of these seem like the
- # sort of thing which should be handled normally. -glyph
- raise
- raise UnlistableError(ose)
- return map(self.child, subnames)
-
- def walk(self, descend=None):
- """
- Yield myself, then each of my children, and each of those children's
- children in turn. The optional argument C{descend} is a predicate that
- takes a FilePath, and determines whether or not that FilePath is
- traversed/descended into. It will be called with each path for which
- C{isdir} returns C{True}. If C{descend} is not specified, all
- directories will be traversed (including symbolic links which refer to
- directories).
-
- @param descend: A one-argument callable that will return True for
- FilePaths that should be traversed, False otherwise.
-
- @return: a generator yielding FilePath-like objects.
- """
- yield self
- if self.isdir():
- for c in self.children():
- # we should first see if it's what we want, then we
- # can walk through the directory
- if (descend is None or descend(c)):
- for subc in c.walk(descend):
- if os.path.realpath(self.path).startswith(
- os.path.realpath(subc.path)):
- raise LinkError("Cycle in file graph.")
- yield subc
- else:
- yield c
-
-
- def sibling(self, path):
- """
- Return a L{FilePath} with the same directory as this instance but with a
- basename of C{path}.
-
- @param path: The basename of the L{FilePath} to return.
- @type path: C{str}
-
- @rtype: L{FilePath}
- """
- return self.parent().child(path)
-
-
- def descendant(self, segments):
- """
- Retrieve a child or child's child of this path.
-
- @param segments: A sequence of path segments as C{str} instances.
-
- @return: A L{FilePath} constructed by looking up the C{segments[0]}
- child of this path, the C{segments[1]} child of that path, and so
- on.
-
- @since: 10.2
- """
- path = self
- for name in segments:
- path = path.child(name)
- return path
-
-
- def segmentsFrom(self, ancestor):
- """
- Return a list of segments between a child and its ancestor.
-
- For example, in the case of a path X representing /a/b/c/d and a path Y
- representing /a/b, C{Y.segmentsFrom(X)} will return C{['c',
- 'd']}.
-
- @param ancestor: an instance of the same class as self, ostensibly an
- ancestor of self.
-
- @raise: ValueError if the 'ancestor' parameter is not actually an
- ancestor, i.e. a path for /x/y/z is passed as an ancestor for /a/b/c/d.
-
- @return: a list of strs
- """
- # this might be an unnecessarily inefficient implementation but it will
- # work on win32 and for zipfiles; later I will deterimine if the
- # obvious fast implemenation does the right thing too
- f = self
- p = f.parent()
- segments = []
- while f != ancestor and p != f:
- segments[0:0] = [f.basename()]
- f = p
- p = p.parent()
- if f == ancestor and segments:
- return segments
- raise ValueError("%r not parent of %r" % (ancestor, self))
-
-
- # new in 8.0
- def __hash__(self):
- """
- Hash the same as another FilePath with the same path as mine.
- """
- return hash((self.__class__, self.path))
-
-
- # pending deprecation in 8.0
- def getmtime(self):
- """
- Deprecated. Use getModificationTime instead.
- """
- return int(self.getModificationTime())
-
-
- def getatime(self):
- """
- Deprecated. Use getAccessTime instead.
- """
- return int(self.getAccessTime())
-
-
- def getctime(self):
- """
- Deprecated. Use getStatusChangeTime instead.
- """
- return int(self.getStatusChangeTime())
-
-
-
-class RWX(FancyEqMixin, object):
- """
- A class representing read/write/execute permissions for a single user
- category (i.e. user/owner, group, or other/world). Instantiate with
- three boolean values: readable? writable? executable?.
-
- @type read: C{bool}
- @ivar read: Whether permission to read is given
-
- @type write: C{bool}
- @ivar write: Whether permission to write is given
-
- @type execute: C{bool}
- @ivar execute: Whether permission to execute is given
-
- @since: 11.1
- """
- compareAttributes = ('read', 'write', 'execute')
- def __init__(self, readable, writable, executable):
- self.read = readable
- self.write = writable
- self.execute = executable
-
-
- def __repr__(self):
- return "RWX(read=%s, write=%s, execute=%s)" % (
- self.read, self.write, self.execute)
-
-
- def shorthand(self):
- """
- Returns a short string representing the permission bits. Looks like
- part of what is printed by command line utilities such as 'ls -l'
- (e.g. 'rwx')
- """
- returnval = ['r', 'w', 'x']
- i = 0
- for val in (self.read, self.write, self.execute):
- if not val:
- returnval[i] = '-'
- i += 1
- return ''.join(returnval)
-
-
-
-class Permissions(FancyEqMixin, object):
- """
- A class representing read/write/execute permissions. Instantiate with any
- portion of the file's mode that includes the permission bits.
-
- @type user: L{RWX}
- @ivar user: User/Owner permissions
-
- @type group: L{RWX}
- @ivar group: Group permissions
-
- @type other: L{RWX}
- @ivar other: Other/World permissions
-
- @since: 11.1
- """
-
- compareAttributes = ('user', 'group', 'other')
-
- def __init__(self, statModeInt):
- self.user, self.group, self.other = (
- [RWX(*[statModeInt & bit > 0 for bit in bitGroup]) for bitGroup in
- [[S_IRUSR, S_IWUSR, S_IXUSR],
- [S_IRGRP, S_IWGRP, S_IXGRP],
- [S_IROTH, S_IWOTH, S_IXOTH]]]
- )
-
-
- def __repr__(self):
- return "[%s | %s | %s]" % (
- str(self.user), str(self.group), str(self.other))
-
-
- def shorthand(self):
- """
- Returns a short string representing the permission bits. Looks like
- what is printed by command line utilities such as 'ls -l'
- (e.g. 'rwx-wx--x')
- """
- return "".join(
- [x.shorthand() for x in (self.user, self.group, self.other)])
-
-
-
-class FilePath(AbstractFilePath):
- """
- I am a path on the filesystem that only permits 'downwards' access.
-
- Instantiate me with a pathname (for example,
- FilePath('/home/myuser/public_html')) and I will attempt to only provide
- access to files which reside inside that path. I may be a path to a file,
- a directory, or a file which does not exist.
-
- The correct way to use me is to instantiate me, and then do ALL filesystem
- access through me. In other words, do not import the 'os' module; if you
- need to open a file, call my 'open' method. If you need to list a
- directory, call my 'path' method.
-
- Even if you pass me a relative path, I will convert that to an absolute
- path internally.
-
- Note: although time-related methods do return floating-point results, they
- may still be only second resolution depending on the platform and the last
- value passed to L{os.stat_float_times}. If you want greater-than-second
- precision, call C{os.stat_float_times(True)}, or use Python 2.5.
- Greater-than-second precision is only available in Windows on Python2.5 and
- later.
-
- @type alwaysCreate: C{bool}
- @ivar alwaysCreate: When opening this file, only succeed if the file does
- not already exist.
-
- @type path: C{str}
- @ivar path: The path from which 'downward' traversal is permitted.
-
- @ivar statinfo: The currently cached status information about the file on
- the filesystem that this L{FilePath} points to. This attribute is
- C{None} if the file is in an indeterminate state (either this
- L{FilePath} has not yet had cause to call C{stat()} yet or
- L{FilePath.changed} indicated that new information is required), 0 if
- C{stat()} was called and returned an error (i.e. the path did not exist
- when C{stat()} was called), or a C{stat_result} object that describes
- the last known status of the underlying file (or directory, as the case
- may be). Trust me when I tell you that you do not want to use this
- attribute. Instead, use the methods on L{FilePath} which give you
- information about it, like C{getsize()}, C{isdir()},
- C{getModificationTime()}, and so on.
- @type statinfo: C{int} or L{types.NoneType} or L{os.stat_result}
- """
-
- implements(IFilePath)
-
- statinfo = None
- path = None
-
- sep = slash
-
- def __init__(self, path, alwaysCreate=False):
- """
- Convert a path string to an absolute path if necessary and initialize
- the L{FilePath} with the result.
- """
- self.path = abspath(path)
- self.alwaysCreate = alwaysCreate
-
- def __getstate__(self):
- """
- Support serialization by discarding cached L{os.stat} results and
- returning everything else.
- """
- d = self.__dict__.copy()
- if 'statinfo' in d:
- del d['statinfo']
- return d
-
-
- def child(self, path):
- """
- Create and return a new L{FilePath} representing a path contained by
- C{self}.
-
- @param path: The base name of the new L{FilePath}. If this contains
- directory separators or parent references it will be rejected.
- @type path: C{str}
-
- @raise InsecurePath: If the result of combining this path with C{path}
- would result in a path which is not a direct child of this path.
- """
- if platform.isWindows() and path.count(":"):
- # Catch paths like C:blah that don't have a slash
- raise InsecurePath("%r contains a colon." % (path,))
- norm = normpath(path)
- if self.sep in norm:
- raise InsecurePath("%r contains one or more directory separators" % (path,))
- newpath = abspath(joinpath(self.path, norm))
- if not newpath.startswith(self.path):
- raise InsecurePath("%r is not a child of %s" % (newpath, self.path))
- return self.clonePath(newpath)
-
-
- def preauthChild(self, path):
- """
- Use me if `path' might have slashes in it, but you know they're safe.
-
- (NOT slashes at the beginning. It still needs to be a _child_).
- """
- newpath = abspath(joinpath(self.path, normpath(path)))
- if not newpath.startswith(self.path):
- raise InsecurePath("%s is not a child of %s" % (newpath, self.path))
- return self.clonePath(newpath)
-
- def childSearchPreauth(self, *paths):
- """Return my first existing child with a name in 'paths'.
-
- paths is expected to be a list of *pre-secured* path fragments; in most
- cases this will be specified by a system administrator and not an
- arbitrary user.
-
- If no appropriately-named children exist, this will return None.
- """
- p = self.path
- for child in paths:
- jp = joinpath(p, child)
- if exists(jp):
- return self.clonePath(jp)
-
- def siblingExtensionSearch(self, *exts):
- """Attempt to return a path with my name, given multiple possible
- extensions.
-
- Each extension in exts will be tested and the first path which exists
- will be returned. If no path exists, None will be returned. If '' is
- in exts, then if the file referred to by this path exists, 'self' will
- be returned.
-
- The extension '*' has a magic meaning, which means "any path that
- begins with self.path+'.' is acceptable".
- """
- p = self.path
- for ext in exts:
- if not ext and self.exists():
- return self
- if ext == '*':
- basedot = basename(p)+'.'
- for fn in listdir(dirname(p)):
- if fn.startswith(basedot):
- return self.clonePath(joinpath(dirname(p), fn))
- p2 = p + ext
- if exists(p2):
- return self.clonePath(p2)
-
-
- def realpath(self):
- """
- Returns the absolute target as a FilePath if self is a link, self
- otherwise. The absolute link is the ultimate file or directory the
- link refers to (for instance, if the link refers to another link, and
- another...). If the filesystem does not support symlinks, or
- if the link is cyclical, raises a LinkError.
-
- Behaves like L{os.path.realpath} in that it does not resolve link
- names in the middle (ex. /x/y/z, y is a link to w - realpath on z
- will return /x/y/z, not /x/w/z).
-
- @return: FilePath of the target path
- @raises LinkError: if links are not supported or links are cyclical.
- """
- if self.islink():
- result = os.path.realpath(self.path)
- if result == self.path:
- raise LinkError("Cyclical link - will loop forever")
- return self.clonePath(result)
- return self
-
-
- def siblingExtension(self, ext):
- return self.clonePath(self.path+ext)
-
-
- def linkTo(self, linkFilePath):
- """
- Creates a symlink to self to at the path in the L{FilePath}
- C{linkFilePath}. Only works on posix systems due to its dependence on
- C{os.symlink}. Propagates C{OSError}s up from C{os.symlink} if
- C{linkFilePath.parent()} does not exist, or C{linkFilePath} already
- exists.
-
- @param linkFilePath: a FilePath representing the link to be created
- @type linkFilePath: L{FilePath}
- """
- os.symlink(self.path, linkFilePath.path)
-
-
- def open(self, mode='r'):
- """
- Open this file using C{mode} or for writing if C{alwaysCreate} is
- C{True}.
-
- In all cases the file is opened in binary mode, so it is not necessary
- to include C{b} in C{mode}.
-
- @param mode: The mode to open the file in. Default is C{r}.
- @type mode: C{str}
- @raises AssertionError: If C{a} is included in the mode and
- C{alwaysCreate} is C{True}.
- @rtype: C{file}
- @return: An open C{file} object.
- """
- if self.alwaysCreate:
- assert 'a' not in mode, ("Appending not supported when "
- "alwaysCreate == True")
- return self.create()
- # This hack is necessary because of a bug in Python 2.7 on Windows:
- # http://bugs.python.org/issue7686
- mode = mode.replace('b', '')
- return open(self.path, mode + 'b')
-
- # stat methods below
-
- def restat(self, reraise=True):
- """
- Re-calculate cached effects of 'stat'. To refresh information on this path
- after you know the filesystem may have changed, call this method.
-
- @param reraise: a boolean. If true, re-raise exceptions from
- L{os.stat}; otherwise, mark this path as not existing, and remove any
- cached stat information.
-
- @raise Exception: is C{reraise} is C{True} and an exception occurs while
- reloading metadata.
- """
- try:
- self.statinfo = stat(self.path)
- except OSError:
- self.statinfo = 0
- if reraise:
- raise
-
-
- def changed(self):
- """
- Clear any cached information about the state of this path on disk.
-
- @since: 10.1.0
- """
- self.statinfo = None
-
-
- def chmod(self, mode):
- """
- Changes the permissions on self, if possible. Propagates errors from
- C{os.chmod} up.
-
- @param mode: integer representing the new permissions desired (same as
- the command line chmod)
- @type mode: C{int}
- """
- os.chmod(self.path, mode)
-
-
- def getsize(self):
- st = self.statinfo
- if not st:
- self.restat()
- st = self.statinfo
- return st.st_size
-
-
- def getModificationTime(self):
- """
- Retrieve the time of last access from this file.
-
- @return: a number of seconds from the epoch.
- @rtype: float
- """
- st = self.statinfo
- if not st:
- self.restat()
- st = self.statinfo
- return float(st.st_mtime)
-
-
- def getStatusChangeTime(self):
- """
- Retrieve the time of the last status change for this file.
-
- @return: a number of seconds from the epoch.
- @rtype: float
- """
- st = self.statinfo
- if not st:
- self.restat()
- st = self.statinfo
- return float(st.st_ctime)
-
-
- def getAccessTime(self):
- """
- Retrieve the time that this file was last accessed.
-
- @return: a number of seconds from the epoch.
- @rtype: float
- """
- st = self.statinfo
- if not st:
- self.restat()
- st = self.statinfo
- return float(st.st_atime)
-
-
- def getInodeNumber(self):
- """
- Retrieve the file serial number, also called inode number, which
- distinguishes this file from all other files on the same device.
-
- @raise: NotImplementedError if the platform is Windows, since the
- inode number would be a dummy value for all files in Windows
- @return: a number representing the file serial number
- @rtype: C{long}
- @since: 11.0
- """
- if platform.isWindows():
- raise NotImplementedError
-
- st = self.statinfo
- if not st:
- self.restat()
- st = self.statinfo
- return long(st.st_ino)
-
-
- def getDevice(self):
- """
- Retrieves the device containing the file. The inode number and device
- number together uniquely identify the file, but the device number is
- not necessarily consistent across reboots or system crashes.
-
- @raise: NotImplementedError if the platform is Windows, since the
- device number would be 0 for all partitions on a Windows
- platform
- @return: a number representing the device
- @rtype: C{long}
- @since: 11.0
- """
- if platform.isWindows():
- raise NotImplementedError
-
- st = self.statinfo
- if not st:
- self.restat()
- st = self.statinfo
- return long(st.st_dev)
-
-
- def getNumberOfHardLinks(self):
- """
- Retrieves the number of hard links to the file. This count keeps
- track of how many directories have entries for this file. If the
- count is ever decremented to zero then the file itself is discarded
- as soon as no process still holds it open. Symbolic links are not
- counted in the total.
-
- @raise: NotImplementedError if the platform is Windows, since Windows
- doesn't maintain a link count for directories, and os.stat
- does not set st_nlink on Windows anyway.
- @return: the number of hard links to the file
- @rtype: C{int}
- @since: 11.0
- """
- if platform.isWindows():
- raise NotImplementedError
-
- st = self.statinfo
- if not st:
- self.restat()
- st = self.statinfo
- return int(st.st_nlink)
-
-
- def getUserID(self):
- """
- Returns the user ID of the file's owner.
-
- @raise: NotImplementedError if the platform is Windows, since the UID
- is always 0 on Windows
- @return: the user ID of the file's owner
- @rtype: C{int}
- @since: 11.0
- """
- if platform.isWindows():
- raise NotImplementedError
-
- st = self.statinfo
- if not st:
- self.restat()
- st = self.statinfo
- return int(st.st_uid)
-
-
- def getGroupID(self):
- """
- Returns the group ID of the file.
-
- @raise: NotImplementedError if the platform is Windows, since the GID
- is always 0 on windows
- @return: the group ID of the file
- @rtype: C{int}
- @since: 11.0
- """
- if platform.isWindows():
- raise NotImplementedError
-
- st = self.statinfo
- if not st:
- self.restat()
- st = self.statinfo
- return int(st.st_gid)
-
-
- def getPermissions(self):
- """
- Returns the permissions of the file. Should also work on Windows,
- however, those permissions may not what is expected in Windows.
-
- @return: the permissions for the file
- @rtype: L{Permissions}
- @since: 11.1
- """
- st = self.statinfo
- if not st:
- self.restat()
- st = self.statinfo
- return Permissions(S_IMODE(st.st_mode))
-
-
- def exists(self):
- """
- Check if this L{FilePath} exists.
-
- @return: C{True} if the stats of C{path} can be retrieved successfully,
- C{False} in the other cases.
- @rtype: C{bool}
- """
- if self.statinfo:
- return True
- else:
- self.restat(False)
- if self.statinfo:
- return True
- else:
- return False
-
-
- def isdir(self):
- """
- @return: C{True} if this L{FilePath} refers to a directory, C{False}
- otherwise.
- """
- st = self.statinfo
- if not st:
- self.restat(False)
- st = self.statinfo
- if not st:
- return False
- return S_ISDIR(st.st_mode)
-
-
- def isfile(self):
- """
- @return: C{True} if this L{FilePath} points to a regular file (not a
- directory, socket, named pipe, etc), C{False} otherwise.
- """
- st = self.statinfo
- if not st:
- self.restat(False)
- st = self.statinfo
- if not st:
- return False
- return S_ISREG(st.st_mode)
-
-
- def isBlockDevice(self):
- """
- Returns whether the underlying path is a block device.
-
- @return: C{True} if it is a block device, C{False} otherwise
- @rtype: C{bool}
- @since: 11.1
- """
- st = self.statinfo
- if not st:
- self.restat(False)
- st = self.statinfo
- if not st:
- return False
- return S_ISBLK(st.st_mode)
-
-
- def isSocket(self):
- """
- Returns whether the underlying path is a socket.
-
- @return: C{True} if it is a socket, C{False} otherwise
- @rtype: C{bool}
- @since: 11.1
- """
- st = self.statinfo
- if not st:
- self.restat(False)
- st = self.statinfo
- if not st:
- return False
- return S_ISSOCK(st.st_mode)
-
-
- def islink(self):
- """
- @return: C{True} if this L{FilePath} points to a symbolic link.
- """
- # We can't use cached stat results here, because that is the stat of
- # the destination - (see #1773) which in *every case* but this one is
- # the right thing to use. We could call lstat here and use that, but
- # it seems unlikely we'd actually save any work that way. -glyph
- return islink(self.path)
-
-
- def isabs(self):
- """
- @return: C{True}, always.
- """
- return isabs(self.path)
-
-
- def listdir(self):
- """
- List the base names of the direct children of this L{FilePath}.
-
- @return: a C{list} of C{str} giving the names of the contents of the
- directory this L{FilePath} refers to. These names are relative to
- this L{FilePath}.
-
- @raise: Anything the platform C{os.listdir} implementation might raise
- (typically OSError).
- """
- return listdir(self.path)
-
-
- def splitext(self):
- """
- @return: tuple where the first item is the filename and second item is
- the file extension. See Python docs for C{os.path.splitext}
- """
- return splitext(self.path)
-
-
- def __repr__(self):
- return 'FilePath(%r)' % (self.path,)
-
-
- def touch(self):
- """
- Updates the access and last modification times of the file at this
- file path to the current time. Also creates the file if it does not
- already exist.
-
- @raise Exception: if unable to create or modify the last modification
- time of the file.
- """
- try:
- self.open('a').close()
- except IOError:
- pass
- utime(self.path, None)
-
-
- def remove(self):
- """
- Removes the file or directory that is represented by self. If
- C{self.path} is a directory, recursively remove all its children
- before removing the directory. If it's a file or link, just delete it.
- """
- if self.isdir() and not self.islink():
- for child in self.children():
- child.remove()
- os.rmdir(self.path)
- else:
- os.remove(self.path)
- self.changed()
-
-
- def makedirs(self):
- """
- Create all directories not yet existing in C{path} segments, using
- C{os.makedirs}.
- """
- return os.makedirs(self.path)
-
-
- def globChildren(self, pattern):
- """
- Assuming I am representing a directory, return a list of
- FilePaths representing my children that match the given
- pattern.
- """
- import glob
- path = self.path[-1] == '/' and self.path + pattern or self.sep.join([self.path, pattern])
- return map(self.clonePath, glob.glob(path))
-
-
- def basename(self):
- """
- @return: The final component of the L{FilePath}'s path (Everything after
- the final path separator).
- @rtype: C{str}
- """
- return basename(self.path)
-
-
- def dirname(self):
- """
- @return: All of the components of the L{FilePath}'s path except the last
- one (everything up to the final path separator).
- @rtype: C{str}
- """
- return dirname(self.path)
-
-
- def parent(self):
- """
- @return: A L{FilePath} representing the path which directly contains
- this L{FilePath}.
- """
- return self.clonePath(self.dirname())
-
-
- def setContent(self, content, ext='.new'):
- """
- Replace the file at this path with a new file that contains the given
- bytes, trying to avoid data-loss in the meanwhile.
-
- On UNIX-like platforms, this method does its best to ensure that by the
- time this method returns, either the old contents I{or} the new contents
- of the file will be present at this path for subsequent readers
- regardless of premature device removal, program crash, or power loss,
- making the following assumptions:
-
- - your filesystem is journaled (i.e. your filesystem will not
- I{itself} lose data due to power loss)
-
- - your filesystem's C{rename()} is atomic
-
- - your filesystem will not discard new data while preserving new
- metadata (see U{http://mjg59.livejournal.com/108257.html} for more
- detail)
-
- On most versions of Windows there is no atomic C{rename()} (see
- U{http://bit.ly/win32-overwrite} for more information), so this method
- is slightly less helpful. There is a small window where the file at
- this path may be deleted before the new file is moved to replace it:
- however, the new file will be fully written and flushed beforehand so in
- the unlikely event that there is a crash at that point, it should be
- possible for the user to manually recover the new version of their data.
- In the future, Twisted will support atomic file moves on those versions
- of Windows which I{do} support them: see U{Twisted ticket
- 3004<http://twistedmatrix.com/trac/ticket/3004>}.
-
- This method should be safe for use by multiple concurrent processes, but
- note that it is not easy to predict which process's contents will
- ultimately end up on disk if they invoke this method at close to the
- same time.
-
- @param content: The desired contents of the file at this path.
-
- @type content: L{str}
-
- @param ext: An extension to append to the temporary filename used to
- store the bytes while they are being written. This can be used to
- make sure that temporary files can be identified by their suffix,
- for cleanup in case of crashes.
-
- @type ext: C{str}
- """
- sib = self.temporarySibling(ext)
- f = sib.open('w')
- try:
- f.write(content)
- finally:
- f.close()
- if platform.isWindows() and exists(self.path):
- os.unlink(self.path)
- os.rename(sib.path, self.path)
-
-
- def __cmp__(self, other):
- if not isinstance(other, FilePath):
- return NotImplemented
- return cmp(self.path, other.path)
-
-
- def createDirectory(self):
- """
- Create the directory the L{FilePath} refers to.
-
- @see: L{makedirs}
-
- @raise OSError: If the directory cannot be created.
- """
- os.mkdir(self.path)
-
-
- def requireCreate(self, val=1):
- self.alwaysCreate = val
-
-
- def create(self):
- """
- Exclusively create a file, only if this file previously did not exist.
- """
- fdint = os.open(self.path, _CREATE_FLAGS)
-
- # XXX TODO: 'name' attribute of returned files is not mutable or
- # settable via fdopen, so this file is slighly less functional than the
- # one returned from 'open' by default. send a patch to Python...
-
- return os.fdopen(fdint, 'w+b')
-
-
- def temporarySibling(self, extension=""):
- """
- Construct a path referring to a sibling of this path.
-
- The resulting path will be unpredictable, so that other subprocesses
- should neither accidentally attempt to refer to the same path before it
- is created, nor they should other processes be able to guess its name in
- advance.
-
- @param extension: A suffix to append to the created filename. (Note
- that if you want an extension with a '.' you must include the '.'
- yourself.)
-
- @type extension: C{str}
-
- @return: a path object with the given extension suffix, C{alwaysCreate}
- set to True.
-
- @rtype: L{FilePath}
- """
- sib = self.sibling(_secureEnoughString() + self.basename() + extension)
- sib.requireCreate()
- return sib
-
-
- _chunkSize = 2 ** 2 ** 2 ** 2
-
- def copyTo(self, destination, followLinks=True):
- """
- Copies self to destination.
-
- If self doesn't exist, an OSError is raised.
-
- If self is a directory, this method copies its children (but not
- itself) recursively to destination - if destination does not exist as a
- directory, this method creates it. If destination is a file, an
- IOError will be raised.
-
- If self is a file, this method copies it to destination. If
- destination is a file, this method overwrites it. If destination is a
- directory, an IOError will be raised.
-
- If self is a link (and followLinks is False), self will be copied
- over as a new symlink with the same target as returned by os.readlink.
- That means that if it is absolute, both the old and new symlink will
- link to the same thing. If it's relative, then perhaps not (and
- it's also possible that this relative link will be broken).
-
- File/directory permissions and ownership will NOT be copied over.
-
- If followLinks is True, symlinks are followed so that they're treated
- as their targets. In other words, if self is a link, the link's target
- will be copied. If destination is a link, self will be copied to the
- destination's target (the actual destination will be destination's
- target). Symlinks under self (if self is a directory) will be
- followed and its target's children be copied recursively.
-
- If followLinks is False, symlinks will be copied over as symlinks.
-
- @param destination: the destination (a FilePath) to which self
- should be copied
- @param followLinks: whether symlinks in self should be treated as links
- or as their targets
- """
- if self.islink() and not followLinks:
- os.symlink(os.readlink(self.path), destination.path)
- return
- # XXX TODO: *thorough* audit and documentation of the exact desired
- # semantics of this code. Right now the behavior of existent
- # destination symlinks is convenient, and quite possibly correct, but
- # its security properties need to be explained.
- if self.isdir():
- if not destination.exists():
- destination.createDirectory()
- for child in self.children():
- destChild = destination.child(child.basename())
- child.copyTo(destChild, followLinks)
- elif self.isfile():
- writefile = destination.open('w')
- try:
- readfile = self.open()
- try:
- while 1:
- # XXX TODO: optionally use os.open, os.read and O_DIRECT
- # and use os.fstatvfs to determine chunk sizes and make
- # *****sure**** copy is page-atomic; the following is
- # good enough for 99.9% of everybody and won't take a
- # week to audit though.
- chunk = readfile.read(self._chunkSize)
- writefile.write(chunk)
- if len(chunk) < self._chunkSize:
- break
- finally:
- readfile.close()
- finally:
- writefile.close()
- elif not self.exists():
- raise OSError(errno.ENOENT, "No such file or directory")
- else:
- # If you see the following message because you want to copy
- # symlinks, fifos, block devices, character devices, or unix
- # sockets, please feel free to add support to do sensible things in
- # reaction to those types!
- raise NotImplementedError(
- "Only copying of files and directories supported")
-
-
- def moveTo(self, destination, followLinks=True):
- """
- Move self to destination - basically renaming self to whatever
- destination is named. If destination is an already-existing directory,
- moves all children to destination if destination is empty. If
- destination is a non-empty directory, or destination is a file, an
- OSError will be raised.
-
- If moving between filesystems, self needs to be copied, and everything
- that applies to copyTo applies to moveTo.
-
- @param destination: the destination (a FilePath) to which self
- should be copied
- @param followLinks: whether symlinks in self should be treated as links
- or as their targets (only applicable when moving between
- filesystems)
- """
- try:
- os.rename(self.path, destination.path)
- except OSError, ose:
- if ose.errno == errno.EXDEV:
- # man 2 rename, ubuntu linux 5.10 "breezy":
-
- # oldpath and newpath are not on the same mounted filesystem.
- # (Linux permits a filesystem to be mounted at multiple
- # points, but rename(2) does not work across different mount
- # points, even if the same filesystem is mounted on both.)
-
- # that means it's time to copy trees of directories!
- secsib = destination.temporarySibling()
- self.copyTo(secsib, followLinks) # slow
- secsib.moveTo(destination, followLinks) # visible
-
- # done creating new stuff. let's clean me up.
- mysecsib = self.temporarySibling()
- self.moveTo(mysecsib, followLinks) # visible
- mysecsib.remove() # slow
- else:
- raise
- else:
- self.changed()
- destination.changed()
-
-
-FilePath.clonePath = FilePath