Last updated:
0 purchases
pth 0.3.0
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.
For personal and professional use. You cannot resell or redistribute these repositories in their original state.
There are no reviews.