Simple and brief path traversal and filesystem access library.
Project description
Note: This is in very alpha state.
Simple and brief path traversal and filesystem access library. This library is a bit different that other path manipulation libraries:
Path are subclasses of strings. You can use them anyhere you would use a string.
Almost everything from os.path is available as a property with the same name except:
os.path.relpath is a method
os.path.getsize becomes a property named size
os.path.getatime becomes a property named atime
os.path.getctime becomes a property named ctime
os.path.getmtime becomes a property named mtime
os.path.split becomes a method name splitpath as split is already a string method
os.path.join becomes a method name joinpath as join is already a string method
os.path.commonprefix is not implemented
os.path.basename becomes a property named name
os.path.dirname becomes a property named dir
os.listdir becomes a property named list
os.walk becomes a property named tree
Calling a Path object calls open() on the path. Takes any argument open would take (except the filename ofcourse).
Transparent support for files in .zip files.
Basically it is designed for extreme brevity. It shares Unipath’s str-subclassing approach and and it has seamless zip support (like Twisted’s ZipPath).
Usage
Getting started:
>>> import pth >>> pth # the module is a function! <function pth at ...> >>> p = pth("a.txt") >>> p <Path 'a.txt'> >>> p <Path 'a.txt'>
API
>>> p = pth('tests') >>> p <Path 'tests'>
Joining paths:
>>> p/"a"/"b"/"c"/"d" <Path 'tests/a/b/c/d'> >>> p/"/root" <Path '/root'>
Properties:
>>> p.abspath <Path '/.../tests'> >>> p2 = p/'b.txt' >>> p2 <Path 'tests/b.txt'> >>> p.exists True >>> p2.isfile True >>> p2() <...'tests/b.txt'...mode...'r'...> >>> pth('bogus-doesnt-exist')() Traceback (most recent call last): ... pth.PathMustBeFile: [Errno 2] No such file or directory: ...
Looping over children, including files in .zip files:
>>> for i in sorted([i for i in p.tree]): print(i) tests/a tests/a/a.txt tests/b.txt tests/test.zip tests/test.zip/1 tests/test.zip/1/1.txt tests/test.zip/B.TXT tests/test.zip/a.txt >>> for i in sorted([i for i in p.files]): print(i) tests/b.txt >>> for i in sorted([i for i in p.dirs]): print(i) tests/a tests/test.zip >>> for i in sorted([i for i in p.list]): print(i) tests/a tests/b.txt tests/test.zip >>> list(pth('bogus-doesnt-exist').tree) Traceback (most recent call last): ... pth.PathMustBeDirectory: <Path 'bogus-doesnt-exist'> is not a directory nor a zip !
Trying to access inexisting property:
>>> p.bogus Traceback (most recent call last): ... AttributeError: 'Path' object has no attribute 'bogus'
Automatic wrapping of zips:
>>> p/'test.zip' <ZipPath 'tests/test.zip' / ''>
Other properties:
>>> p.abspath <Path '/.../tests'> >>> p.abs <Path '/.../tests'> >>> p.basename <Path 'tests'> >>> p.abs.basename <Path 'tests'> >>> p.name <Path 'tests'> >>> p.dirname <Path ''> >>> p.dir <Path ''> >>> p.exists True >>> pth('~root').expanduser <Path '/root'> >>> pth('~/stuff').expanduser <Path '/home/.../stuff'> >>> p.expandvars <Path 'tests'> >>> type(p.atime) <... 'float'> >>> type(p.ctime) <... 'float'> >>> type(p.size) <... 'int'> >>> p.isabs False >>> p.abs.isabs True >>> p.isdir True >>> p.isfile False >>> p.islink False >>> p.ismount False >>> p.lexists True >>> p.normcase <Path 'tests'> >>> p.normpath <Path 'tests'> >>> p.realpath <Path '/.../tests'> >>> p.splitpath (<Path ''>, <Path 'tests'>) >>> pth('a/b/c/d').splitpath (<Path 'a/b/c'>, <Path 'd'>) >>> pth('a/b/c/d').parts [<Path 'a'>, <Path 'b'>, <Path 'c'>, <Path 'd'>] >>> pth('/a/b/c/d').parts [<Path '/'>, <Path 'a'>, <Path 'b'>, <Path 'c'>, <Path 'd'>] >>> pth(*pth('/a/b/c/d').parts) <Path '/a/b/c/d'> >>> p.splitdrive ('', <Path 'tests'>) >>> p.drive '' >>> [i for i in (p/'xxx').tree] Traceback (most recent call last): ... pth.PathMustBeDirectory: <Path 'tests/xxx'> is not a directory nor a zip ! >>> (p/'xxx').isfile False >>> (p/'xxx')() Traceback (most recent call last): ... pth.PathMustBeFile: ... 2... >>> p() Traceback (most recent call last): ... pth.PathMustBeFile: <Path 'tests'> is not a file ! >>> pth('a.txt').splitext (<Path 'a'>, '.txt') >>> pth('a.txt').ext '.txt'
Zip stuff:
>>> z = pth('tests/test.zip') >>> z <ZipPath 'tests/test.zip' / ''> >>> z.abspath <ZipPath '/.../tests/test.zip' / ''> >>> z.abs <ZipPath '/.../tests/test.zip' / ''> >>> z.basename # transforms in normal path cauze zip is not accessible in current dir <Path 'test.zip'> >>> z.abs.basename # transforms in normal path cauze zip is not accessible in current dir <Path 'test.zip'> >>> import os >>> os.chdir('tests') >>> z.basename <ZipPath 'test.zip' / ''> >>> z.name <ZipPath 'test.zip' / ''> >>> os.chdir('..') >>> z.dirname <Path 'tests'> >>> z.abs.dirname <Path '/.../tests'> >>> z.dir <Path 'tests'> >>> z.exists True >>> pth('~root').expanduser <Path '/root'> >>> pth('~/stuff').expanduser <Path '/home/.../stuff'> >>> z.expandvars <ZipPath 'tests/test.zip' / ''> >>> type(z.atime) Traceback (most recent call last): ... AttributeError: Not available here. >>> type(z.ctime) <... 'float'> >>> type(z.size) <... 'int'> >>> z.isabs False >>> z.abs.isabs True >>> z.isdir True >>> z.isfile False >>> z.islink False >>> z.ismount False >>> z.lexists Traceback (most recent call last): ... AttributeError: Not available here. >>> for i in z.tree: print((str(i), repr(i))) ('tests/test.zip/1',...... "<ZipPath 'tests/test.zip' / '1/'>") ('tests/test.zip/1/1.txt', "<ZipPath 'tests/test.zip' / '1/1.txt'>") ('tests/test.zip/B.TXT',..."<ZipPath 'tests/test.zip' / 'B.TXT'>") ('tests/test.zip/a.txt',..."<ZipPath 'tests/test.zip' / 'a.txt'>") >>> for i in z.files: print((str(i), repr(i))) ('tests/test.zip/B.TXT',..."<ZipPath 'tests/test.zip' / 'B.TXT'>") ('tests/test.zip/a.txt',..."<ZipPath 'tests/test.zip' / 'a.txt'>") >>> for i in z.dirs: print((str(i), repr(i))) ('tests/test.zip/1',...... "<ZipPath 'tests/test.zip' / '1/'>") >>> for i in z.list: print((str(i), repr(i))) ('tests/test.zip/1',...... "<ZipPath 'tests/test.zip' / '1/'>") ('tests/test.zip/B.TXT',..."<ZipPath 'tests/test.zip' / 'B.TXT'>") ('tests/test.zip/a.txt',..."<ZipPath 'tests/test.zip' / 'a.txt'>") >>> (z/'B.TXT') <ZipPath 'tests/test.zip' / 'B.TXT'> >>> str(z/'B.TXT') 'tests/test.zip/B.TXT' >>> (z/'B.TXT').dirname <ZipPath 'tests/test.zip' / ''> >>> (z/'B.TXT').rel(z) <Path 'B.TXT'> >>> z.rel(z/'B.TXT') <Path '..'> >>> (z/'B.TXT').exists True >>> (z/'B.TXT').normcase <ZipPath 'tests/test.zip' / 'B.TXT'> >>> (z/'B.TXT').normpath <ZipPath 'tests/test.zip' / 'B.TXT'> >>> (z/'B.TXT').name <Path 'B.TXT'> >>> (z/'B.TXT').name <Path 'B.TXT'> >>> z.normcase <ZipPath 'tests/test.zip' / ''> >>> z.normpath <ZipPath 'tests/test.zip' / ''> >>> z.realpath <ZipPath '/.../tests/test.zip' / ''> >>> z.splitpath (<Path 'tests'>, <Path 'test.zip'>) >>> z.splitdrive ('', <ZipPath 'tests/test.zip' / ''>) >>> z.drive '' >>> pth('a.txt').splitext (<Path 'a'>, '.txt') >>> pth('a.txt').ext '.txt'
Working with files in a .zip:
>>> p = z/'B.TXT' >>> p.abspath <ZipPath '/.../tests/test.zip' / 'B.TXT'> >>> p.abs <ZipPath '/.../tests/test.zip' / 'B.TXT'> >>> p.basename <Path 'B.TXT'> >>> p.abs.basename <Path 'B.TXT'> >>> p.name <Path 'B.TXT'> >>> p.dirname <ZipPath 'tests/test.zip' / ''> >>> p.dir <ZipPath 'tests/test.zip' / ''> >>> p.exists True >>> type(p.atime) Traceback (most recent call last): ... AttributeError: Not available here. >>> type(p.ctime) <... 'float'> >>> type(p.size) <... 'int'> >>> p.isabs False >>> p.abs.isabs True >>> p.isdir False >>> p.isfile True >>> p.islink False >>> p.ismount False >>> p.lexists Traceback (most recent call last): ... AttributeError: Not available here. >>> p.normcase <ZipPath 'tests/test.zip' / 'B.TXT'> >>> p.normpath <ZipPath 'tests/test.zip' / 'B.TXT'> >>> p.realpath <ZipPath '/.../tests/test.zip' / 'B.TXT'> >>> p.splitpath (<ZipPath 'tests/test.zip' / ''>, <Path 'B.TXT'>) >>> pth.ZipPath.from_string('tests/test.zip/1/1.txt') <ZipPath 'tests/test.zip' / '1/1.txt'> >>> p.splitdrive ('', <ZipPath 'tests/test.zip' / 'B.TXT'>) >>> p.drive '' >>> p.splitext (<ZipPath 'tests/test.zip' / 'B'>, '.TXT') >>> p.ext '.TXT' >>> p.joinpath('tete') <ZipPath 'tests/test.zip' / 'B.TXT/tete'> >>> p.joinpath('tete').exists False >>> p.joinpath('tete').isdir False >>> p.joinpath('tete').isfile False >>> p.joinpath('tete').ctime Traceback (most recent call last): ... pth.PathDoesNotExist: "There is no item named 'B.TXT/tete' in the archive" >>> p.joinpath('tete').size Traceback (most recent call last): ... pth.PathDoesNotExist: "There is no item named 'B.TXT/tete' in the archive" >>> p.relpath('tests') <Path 'test.zip/B.TXT'> >>> p.joinpath('tete')('rb') Traceback (most recent call last): ... pth.PathMustBeFile: <ZipPath 'tests/test.zip' / 'B.TXT/tete'> is not a file ! >>> p('r') <zipfile.ZipExtFile ...> >>> [i for i in p.tree] Traceback (most recent call last): ... pth.PathMustBeDirectory: <ZipPath 'tests/test.zip' / 'B.TXT'> is not a directory ! >>> z('rb') Traceback (most recent call last): ... pth.PathMustBeFile: <ZipPath 'tests/test.zip' / ''> is not a file !
Iterating though the contents of the zip:
>>> [i for i in z.tree] [<ZipPath 'tests/test.zip' / '1/'>, <ZipPath 'tests/test.zip' / '1/1.txt'>, <ZipPath 'tests/test.zip' / 'B.TXT'>, <ZipPath 'tests/test.zip' / 'a.txt'>] >>> [i for i in z.files] [<ZipPath 'tests/test.zip' / 'B.TXT'>, <ZipPath 'tests/test.zip' / 'a.txt'>] >>> [i for i in z.dirs] [<ZipPath 'tests/test.zip' / '1/'>]
Note that there’s this inconsistency with joining absolute paths:
>>> z/pth('/root') <Path '/root'>
Vs:
>>> z/'/root' <ZipPath 'tests/test.zip' / '/root'>
TODO: Make this nicer.
>>> pth.ZipPath('tests', '', '') <Path 'tests'> >>> pth.ZipPath.from_string('/bogus/path/to/stuff/bla/bla/bla') <Path '/bogus/path/to/stuff/bla/bla/bla'> >>> pth.ZipPath.from_string('bogus') <Path 'bogus'> >>> pth.ZipPath.from_string('tests/test.zip/bogus/path/to/stuff/bla/bla/bla') <ZipPath 'tests/test.zip' / 'bogus/path/to/stuff/bla/bla/bla'> >>> pth.ZipPath.from_string('tests/1/bogus/path/to/stuff/bla/bla/bla') <Path 'tests/1/bogus/path/to/stuff/bla/bla/bla'> >>> pth.ZipPath.from_string('tests') <Path 'tests'> >>> pth.ZipPath.from_string('tests/bogus') <Path 'tests/bogus'>
And there’s a temporary path:
>>> t = pth.TempPath() >>> t <TempPath '/tmp/...'> >>> with t: ... with (t/"booo.txt")('w+') as f: ... _ = f.write("test") ... print([i for i in t.tree]) [<Path '/tmp/.../booo.txt'>] >>> t.exists False
Changelog
0.1.0 (2014-06-10)
First release on PyPI.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
File details
Details for the file pth-0.3.0.tar.gz
.
File metadata
- Download URL: pth-0.3.0.tar.gz
- Upload date:
- Size: 16.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 206e5f104d8f4949b66c6f418d30e585546ef8cdd08428a556ddc43f25c07cd4 |
|
MD5 | 02e3cfe0e74f06292cf9729c4de30f78 |
|
BLAKE2b-256 | 6f6831fda6cb2092373ce5ba460139b0ee37814411927e3a6f5e9847679b6ef7 |
File details
Details for the file pth-0.3.0-py2.py3-none-any.whl
.
File metadata
- Download URL: pth-0.3.0-py2.py3-none-any.whl
- Upload date:
- Size: 10.3 kB
- Tags: Python 2, Python 3
- Uploaded using Trusted Publishing? No
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 1c7f7b1456ec8a97ac2ea71b1f1ceb7d35fcdcd07c8845fda5585b8fb157aa97 |
|
MD5 | 9c00d19f1ae7fa2c5c352b08b81d11b2 |
|
BLAKE2b-256 | 880a0c01ca43eace546a12bc2fd2ab95588c1a87c3fec853d169ff57c1a60168 |