| ======= |
| py.path |
| ======= |
| |
| The 'py' lib provides a uniform high-level api to deal with filesystems |
| and filesystem-like interfaces: ``py.path``. It aims to offer a central |
| object to fs-like object trees (reading from and writing to files, adding |
| files/directories, examining the types and structure, etc.), and out-of-the-box |
| provides a number of implementations of this API. |
| |
| py.path.local - local file system path |
| =============================================== |
| |
| .. _`local`: |
| |
| basic interactive example |
| ------------------------------------- |
| |
| The first and most obvious of the implementations is a wrapper around a local |
| filesystem. It's just a bit nicer in usage than the regular Python APIs, and |
| of course all the functionality is bundled together rather than spread over a |
| number of modules. |
| |
| Example usage, here we use the ``py.test.ensuretemp()`` function to create |
| a ``py.path.local`` object for us (which wraps a directory): |
| |
| .. sourcecode:: pycon |
| |
| >>> import py |
| >>> temppath = py.test.ensuretemp('py.path_documentation') |
| >>> foopath = temppath.join('foo') # get child 'foo' (lazily) |
| >>> foopath.check() # check if child 'foo' exists |
| False |
| >>> foopath.write('bar') # write some data to it |
| >>> foopath.check() |
| True |
| >>> foopath.read() |
| 'bar' |
| >>> foofile = foopath.open() # return a 'real' file object |
| >>> foofile.read(1) |
| 'b' |
| |
| reference documentation |
| --------------------------------- |
| |
| .. autoclass:: py._path.local.LocalPath |
| :members: |
| :inherited-members: |
| |
| ``py.path.svnurl`` and ``py.path.svnwc`` |
| ================================================== |
| |
| Two other ``py.path`` implementations that the py lib provides wrap the |
| popular `Subversion`_ revision control system: the first (called 'svnurl') |
| by interfacing with a remote server, the second by wrapping a local checkout. |
| Both allow you to access relatively advanced features such as metadata and |
| versioning, and both in a way more user-friendly manner than existing other |
| solutions. |
| |
| Some example usage of ``py.path.svnurl``: |
| |
| .. sourcecode:: pycon |
| |
| .. >>> import py |
| .. >>> if not py.test.config.option.urlcheck: raise ValueError('skipchunk') |
| >>> url = py.path.svnurl('http://codespeak.net/svn/py') |
| >>> info = url.info() |
| >>> info.kind |
| 'dir' |
| >>> firstentry = url.log()[-1] |
| >>> import time |
| >>> time.strftime('%Y-%m-%d', time.gmtime(firstentry.date)) |
| '2004-10-02' |
| |
| Example usage of ``py.path.svnwc``: |
| |
| .. sourcecode:: pycon |
| |
| .. >>> if not py.test.config.option.urlcheck: raise ValueError('skipchunk') |
| >>> temp = py.test.ensuretemp('py.path_documentation') |
| >>> wc = py.path.svnwc(temp.join('svnwc')) |
| >>> wc.checkout('http://codespeak.net/svn/py/dist/py/path/local') |
| >>> wc.join('local.py').check() |
| True |
| |
| .. _`Subversion`: http://subversion.tigris.org/ |
| |
| svn path related API reference |
| ----------------------------------------- |
| |
| .. autoclass:: py._path.svnwc.SvnWCCommandPath |
| :members: |
| :inherited-members: |
| |
| .. autoclass:: py._path.svnurl.SvnCommandPath |
| :members: |
| :inherited-members: |
| |
| .. autoclass:: py._path.svnwc.SvnAuth |
| :members: |
| :inherited-members: |
| |
| Common vs. specific API, Examples |
| ======================================== |
| |
| All Path objects support a common set of operations, suitable |
| for many use cases and allowing to transparently switch the |
| path object within an application (e.g. from "local" to "svnwc"). |
| The common set includes functions such as `path.read()` to read all data |
| from a file, `path.write()` to write data, `path.listdir()` to get a list |
| of directory entries, `path.check()` to check if a node exists |
| and is of a particular type, `path.join()` to get |
| to a (grand)child, `path.visit()` to recursively walk through a node's |
| children, etc. Only things that are not common on 'normal' filesystems (yet), |
| such as handling metadata (e.g. the Subversion "properties") require |
| using specific APIs. |
| |
| A quick 'cookbook' of small examples that will be useful 'in real life', |
| which also presents parts of the 'common' API, and shows some non-common |
| methods: |
| |
| Searching `.txt` files |
| -------------------------------- |
| |
| Search for a particular string inside all files with a .txt extension in a |
| specific directory. |
| |
| .. sourcecode:: pycon |
| |
| >>> dirpath = temppath.ensure('testdir', dir=True) |
| >>> dirpath.join('textfile1.txt').write('foo bar baz') |
| >>> dirpath.join('textfile2.txt').write('frob bar spam eggs') |
| >>> subdir = dirpath.ensure('subdir', dir=True) |
| >>> subdir.join('textfile1.txt').write('foo baz') |
| >>> subdir.join('textfile2.txt').write('spam eggs spam foo bar spam') |
| >>> results = [] |
| >>> for fpath in dirpath.visit('*.txt'): |
| ... if 'bar' in fpath.read(): |
| ... results.append(fpath.basename) |
| >>> results.sort() |
| >>> results |
| ['textfile1.txt', 'textfile2.txt', 'textfile2.txt'] |
| |
| Working with Paths |
| ---------------------------- |
| |
| This example shows the ``py.path`` features to deal with |
| filesystem paths Note that the filesystem is never touched, |
| all operations are performed on a string level (so the paths |
| don't have to exist, either): |
| |
| .. sourcecode:: pycon |
| |
| >>> p1 = py.path.local('/foo/bar') |
| >>> p2 = p1.join('baz/qux') |
| >>> p2 == py.path.local('/foo/bar/baz/qux') |
| True |
| >>> sep = py.path.local.sep |
| >>> p2.relto(p1).replace(sep, '/') # os-specific path sep in the string |
| 'baz/qux' |
| >>> p2.bestrelpath(p1).replace(sep, '/') |
| '../..' |
| >>> p2.join(p2.bestrelpath(p1)) == p1 |
| True |
| >>> p3 = p1 / 'baz/qux' # the / operator allows joining, too |
| >>> p2 == p3 |
| True |
| >>> p4 = p1 + ".py" |
| >>> p4.basename == "bar.py" |
| True |
| >>> p4.ext == ".py" |
| True |
| >>> p4.purebasename == "bar" |
| True |
| |
| This should be possible on every implementation of ``py.path``, so |
| regardless of whether the implementation wraps a UNIX filesystem, a Windows |
| one, or a database or object tree, these functions should be available (each |
| with their own notion of path seperators and dealing with conversions, etc.). |
| |
| Checking path types |
| ------------------------------- |
| |
| Now we will show a bit about the powerful 'check()' method on paths, which |
| allows you to check whether a file exists, what type it is, etc.: |
| |
| .. sourcecode:: pycon |
| |
| >>> file1 = temppath.join('file1') |
| >>> file1.check() # does it exist? |
| False |
| >>> file1 = file1.ensure(file=True) # 'touch' the file |
| >>> file1.check() |
| True |
| >>> file1.check(dir=True) # is it a dir? |
| False |
| >>> file1.check(file=True) # or a file? |
| True |
| >>> file1.check(ext='.txt') # check the extension |
| False |
| >>> textfile = temppath.ensure('text.txt', file=True) |
| >>> textfile.check(ext='.txt') |
| True |
| >>> file1.check(basename='file1') # we can use all the path's properties here |
| True |
| |
| Setting svn-properties |
| -------------------------------- |
| |
| As an example of 'uncommon' methods, we'll show how to read and write |
| properties in an ``py.path.svnwc`` instance: |
| |
| .. sourcecode:: pycon |
| |
| .. >>> if not py.test.config.option.urlcheck: raise ValueError('skipchunk') |
| >>> wc.propget('foo') |
| '' |
| >>> wc.propset('foo', 'bar') |
| >>> wc.propget('foo') |
| 'bar' |
| >>> len(wc.status().prop_modified) # our own props |
| 1 |
| >>> msg = wc.revert() # roll back our changes |
| >>> len(wc.status().prop_modified) |
| 0 |
| |
| SVN authentication |
| ---------------------------- |
| |
| Some uncommon functionality can also be provided as extensions, such as SVN |
| authentication: |
| |
| .. sourcecode:: pycon |
| |
| .. >>> if not py.test.config.option.urlcheck: raise ValueError('skipchunk') |
| >>> auth = py.path.SvnAuth('anonymous', 'user', cache_auth=False, |
| ... interactive=False) |
| >>> wc.auth = auth |
| >>> wc.update() # this should work |
| >>> path = wc.ensure('thisshouldnotexist.txt') |
| >>> try: |
| ... path.commit('testing') |
| ... except py.process.cmdexec.Error, e: |
| ... pass |
| >>> 'authorization failed' in str(e) |
| True |
| |
| Known problems / limitations |
| =================================== |
| |
| * The SVN path objects require the "svn" command line, |
| there is currently no support for python bindings. |
| Parsing the svn output can lead to problems, particularly |
| regarding if you have a non-english "locales" setting. |
| |
| * While the path objects basically work on windows, |
| there is no attention yet on making unicode paths |
| work or deal with the famous "8.3" filename issues. |
| |
| |