Skip to content
This repository has been archived by the owner on Sep 12, 2020. It is now read-only.

jvrana/OPath

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

travis build Coverage Status PyPI version License: MIT

Build/Coverage Status

Branch Build Coverage
master master build Master Coverage Status
development development build Development Coverage Status

πŸ“ ODir πŸ“

Dealing with paths and directories isn't rocket science, but it can be a pain. ODir allows you to build directory trees by treating your directory tree as a first-class object.

Github can be found here: https://github.com/jvrana/opath

Documentation can be found here https://opath.readthedocs.io/en/latest/

without ODir

# define paths
top = os.path.abspath('top')
middle = os.path.join(str(top), 'middle')
bottom = os.path.join(str(middle), 'bottom')
os.makedirs(bottom)
with open(os.path.join(bottom, 'bottomlog.txt', 'w') as f:
    f.write("some log information")

with ODir

# define paths
env = ODir('top').add('middle').add('bottom').root
env.bottom.write('log.txt', 'w', 'some log information')

Installation

Installation via pip is the easiest way...

pip install opath

Alternatives

Projects like pathlib or path.py encapsulating paths into objects and may be better suited for you purposes.

However, ODir provides some useful features for managing large directory tree structures.

  • building directory and file structure trees as an abstract tree
  • quick access to deeply nested directories and files using custom attribute names
  • directories and files are treated as nested attributes in python objects

Examples

live_example

Its very easy to create, move, or delete directory trees. For example, the following builds the directory skeleton for this repo.

demo

from opath import *

# create folder structure
env = ODir('opath')
env.add('opath', alias='core')
env.core.add('tests')
env.tests.add('env')
env.tests.add('env2')

# make the directory
env.set_dir(Path(__file__).absolute().parent)
env.mkdirs()

# write some files
env.write('README.md', 'w', '# ODir\nThis is a test readme file')
env.core.write("__init__.py", "w", "__version__ = \"1.0\"")

Other things you can do:

Abstracting the directory structure lets your create, remove, copy, move directory trees easily.

rmdirs_example

All paths are easily accessible.

print(env.test.abspath) # absolute path
print(env.test.path) # relative path

You can even read and write files intuitively.

# writes file to 'test' folder
env.test.write('test.txt', 'w', 'some data')

# reads test file
env.test.read('test.txt', 'r')

 # open file and read lines
env.test.open('test.txt', 'r').readlines()

All iterables are chainable making it easy to do complex things. Pretty cool!

# recurseively write a log file to all subfolders of 'core'
env.core.descendents.write('log.txt', 'w', 'some log file')

# read all files named 'log.txt' for subfolders in 'test'
env.test.children.read('log.txt', 'r')

# readlines files named 'log.txt' for subfolders in 'test'
env.test.children.open('log.txt', 'r').readlines()

# recursively get stats on folders
d = env.descendents()
zip(d, d.stat().st_mtime)

Better documentation about chaining methods is soon to come along with recipes.

Basic usage

Use add to create folders.

from opath import *

env = ODir('bin')
env.add('subfolder1')
env.add('subfolder2')
env.print()

>>>
*bin
|   *subfolder1
|   *subfolder2

Functions return ODir objects and so can be chained together.

env = ODir('bin')
env.add('subfolder1').add('subsubfolder')
env.print()

>>>
*bin
|   *subfolder1
|   |   *subsubfolder

Files can be written quickly

env = ODir('bin')
env.add('subfolder1').add('subsubfolder')
env.subsubfolder.write('My Data', 'w')

Or a OFile can be added:

env = ODir('bin')
env.add_file('myfile.txt', attr='myfile')
env.myfile.write('this is my data', 'w')

Folders create accesible ODir attributes automatically. Alternative attribute names can be set using 'alias='

env = ODir('bin')
env.add('subfolder1')
env.subfolder1.add('misc')
env.subfolder1.misc.add('.hidden', alias='hidden')
env.subfolder1.misc.hidden.add('hiddenbin')
env.print()

*bin
|   *subfolder1
|   |   *misc
|   |   |   *.hidden ("hidden")
|   |   |   |   *hiddenbin

By default, attributes are pushed back the the root directory. The following is equivalent to above.

env = ODir('bin')
env.add('subfolder1')
env.subfolder1.add('misc')
env.misc.add('.hidden', alias='hidden')
env.hidden.add('hiddenbin')
env.print()

*bin
|   *subfolder1
|   |   *misc
|   |   |   *.hidden ("hidden")
|   |   |   |   *hiddenbin

Making, moving, copying, and deleting directories

The location of the root folder can be set by set_bin

env.set_bin('../bin')

Directories can be created, deleted, copied or moved using mkdirs, cpdirs, mvdirs, rmdirs

env.mkdirs()
env_copy = env.cpdirs()
# you can do stuff with env_copy independently
env.mvdirs('~/Document')
env_copy.rmdirs()

Advanced usage

All iterables return special list-like objects that can be chained in one-liners.

env.descendents() # returns a ChainList object

# find all txt files
env.descendents(include_self=True).glob("*.txt")

# recursively change permissions for directories
env.abspaths.chmod(0o444)