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
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
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
|