Skip to content

Commit

Permalink
Merge pull request #4 from joshpsawyer/version-0.2.0
Browse files Browse the repository at this point in the history
version 0.2.0
  • Loading branch information
joshpsawyer authored Feb 23, 2020
2 parents 69e7f8d + e403bb4 commit 0742c46
Show file tree
Hide file tree
Showing 5 changed files with 116 additions and 31 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# pyhere

[![Build Status](https://travis-ci.com/joshpsawyer/pyhere.svg?branch=master)](https://travis-ci.com/joshpsawyer/pyhere)
[![Latest pypi version](https://img.shields.io/pypi/v/pyhere)](https://pypi.org/project/pyhere/)

A Python 2.x / 3.x equivalent of R's [`here`][1] package, drawing inspiration from [chendaniely][2]'s [`pyprojroot`][3] package, but more closely mirroring the functionality within R's `here`. Relative file referencing has never been easier!

Expand Down
3 changes: 2 additions & 1 deletion pyhere/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from .pyhere import here
from .pyhere import set_here
from .pyhere import find_root
from .pyhere import root_indicators

__version__ = "0.1.0"
__version__ = "0.2.0"
66 changes: 52 additions & 14 deletions pyhere/pyhere.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,20 +22,23 @@
".ropeproject" # rope
]

# credit to ThiefMaster on stack overflow for a simple touch function
# https://stackoverflow.com/questions/12654772/create-empty-file-using-python
def touch(path):
if type(path) is str:
basedir = Path(path)
else:
basedir = path

basedir.parent.mkdir(parents=True, exist_ok=True)
def here(*args):
"""
Finds a project's root directory and then iteratively appends all passed
arguments to it, construction a path relative to the root directory.
with open(path, 'a'):
os.utime(path, None)
Parameters
----------
*args : Path or str
The path additions to be attached to the root directory.
def here(*args):
Returns
-------
Path
A path directory pointing to the passed arguments relative to the
project's root directory.
"""
heredir = find_root()

for arg in args:
Expand All @@ -44,12 +47,44 @@ def here(*args):
return heredir

def set_here(wd = None):
"""
Creates a .here file at the passed directory.
Parameters
----------
wd : Path object or string
The directory that a .here file will be created in. If none is set,
uses Path.cwd()
"""
if wd is None:
wd = Path.cwd()
elif type(wd) is str:
wd = Path(wd)

touch(wd / ".here")
wd.parent.mkdir(parents=True, exist_ok=True)
wd.joinpath(".here").touch()


def find_root(path = None):
"""
Find's the root of a python project.
Traverses directories upwards, iteratively searching for root_indicators.
If no match is found, the system root is returned and a warning is thrown.
Parameters
----------
path : Path, str or None
The starting directory to begin the search. If none is set, uses
Path.cwd()
Returns
-------
Path
Either the path where a root_indicator was found or the system root.
"""
if path is None:
return find_root(Path.cwd())
else:
Expand All @@ -59,8 +94,11 @@ def find_root(path = None):

next_path = path / ".."

# if we've hit the system root
if (next_path.resolve() != path.resolve()):
return find_root(next_path)
else:
warnings.warn("No project indicator found - returning root system directory")
warnings.warn(
"No project indicator found - returning root system directory"
)
return path
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

setuptools.setup(
name="pyhere",
version="0.1.0",
version="0.2.0",
author="Josh P. Sawyer",
author_email="[email protected]",
license="MIT",
Expand Down
75 changes: 60 additions & 15 deletions tests/test_here.py
Original file line number Diff line number Diff line change
@@ -1,34 +1,79 @@
# -*- coding: utf-8 -*-
from os import chdir
import sys
import pytest

from pyhere import __version__
from pyhere import here
from pyhere import set_here
from pyhere import find_root
from pyhere import root_indicators

# this test is to ensure I don't mess up versioning
def test_version():
assert __version__ == "0.1.0"
assert __version__ == "0.2.0"

def test_here(tmp_path):
# create dummy project
f1 = tmp_path / "proj" / "src"
f1.mkdir(parents=True, exist_ok=True)

f2 = tmp_path / "proj" / "data"
f2.mkdir(parents=True, exist_ok=True)

def test_touch():
assert True
# create a .here file at the project root
tmp_path.joinpath("proj").joinpath(".here").touch()

def test_here():
assert True
# create a fake data file
f2.joinpath("data.csv").touch()

# set working dir to the src directory
if sys.version_info[0] == 2:
chdir(str(f1))
else:
chdir(f1)

def test_set_here():
assert True
herepath = here("data", "data.csv")

def test_find_root(tmp_path):
r_indicator = ".here"
assert herepath.resolve() == f2.joinpath("data.csv").resolve()

def test_set_here(tmp_path):
# create dummy project
f1 = tmp_path / "proj" / "proj_dir"
f1.mkdir(parents=True, exist_ok=True)

# create .here in tmp_path
set_here()
cwd_path = tmp_path.cwd()
assert cwd_path.joinpath(".here").exists()

# create .here in /proj/proj_dir
set_here(f1)
assert f1.joinpath(".here").exists()

# create .here in /proj/
set_here(str(tmp_path / "proj"))
assert tmp_path.joinpath("proj").joinpath(".here").exists()

@pytest.mark.parametrize(
"r_indicator",
root_indicators,
)
def test_find_root_from_indicator(tmp_path, r_indicator):
# create /proj/r_indicator
f1 = tmp_path / "proj"
f1 = tmp_path / "proj" / r_indicator
f1.mkdir(parents=True, exist_ok=True)

f2 = f1 / "src"
# create a different directory, /proj/src/test.txt
f2 = f1 / "src" / "test.txt"
f2.mkdir(parents=True, exist_ok=True)
f2 = f2 / "test"

# verify they point to the same project root
assert find_root(f1).resolve() == find_root(f2).resolve()

assert True


def test_find_sys_root(tmp_path):
# create some nested directories
f1 = tmp_path / "proj" / "another_path"

# verify that they all recurse to the system root
assert find_root(tmp_path).resolve() == find_root(f1).resolve()

0 comments on commit 0742c46

Please sign in to comment.