Skip to content

Commit

Permalink
Merge pull request #25 from chendaniely/package_src_test
Browse files Browse the repository at this point in the history
I think this is all i need for #22
  • Loading branch information
chendaniely authored Mar 30, 2021
2 parents af825c9 + 1464198 commit 4bbd99e
Show file tree
Hide file tree
Showing 6 changed files with 138 additions and 137 deletions.
3 changes: 2 additions & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@
author="Daniel Chen",
author_email="[email protected]",
url="https://github.com/chendaniely/pyprojroot",
packages=setuptools.find_packages(),
packages=setuptools.find_packages(where="src"),
package_dir={"": "src"},
package_data={"pyprojroot": ["py.typed"]},
classifiers=[
"Programming Language :: Python :: 3",
Expand Down
File renamed without changes.
162 changes: 81 additions & 81 deletions pyprojroot/criterion.py → src/pyprojroot/criterion.py
Original file line number Diff line number Diff line change
@@ -1,81 +1,81 @@
"""
This module is inspired by the `rprojroot` library for R.
See https://github.com/r-lib/rprojroot.
It is intended for interactive or programmatic only.
"""

import pathlib as _pathlib
import typing
from os import PathLike as _PathLike

# TODO: It would be nice to have a class that encapsulates these checks,
# so that we can implement methods like |, !, &, ^ operators

# TODO: Refactor in a way that allows creation of reasons


def as_root_criterion(criterion) -> typing.Callable:
if callable(criterion):
return criterion

# criterion must be a Collection, rather than just Iterable
if isinstance(criterion, _PathLike):
criterion = [criterion]
criterion = list(criterion)

def f(path: _pathlib.Path) -> bool:
for c in criterion:
if isinstance(c, _PathLike):
if (path / c).exists():
return True
else:
if c(path):
return True
return False

return f


def has_file(file: _PathLike) -> typing.Callable:
"""
Check that specified file exists in path.
Note that a directory with that name will not match.
"""

def f(path: _pathlib.Path) -> bool:
return (path / file).is_file()

return f


def has_dir(file: _PathLike) -> typing.Callable:
"""
Check that specified directory exists.
Note that a regular file with that name will not match.
"""

def f(path: _pathlib.Path) -> bool:
return (path / file).is_dir()

return f


def matches_glob(pat: str) -> typing.Callable:
"""
Check that glob has at least one match.
"""

def f(path: _pathlib.Path) -> bool:
matches = path.glob(pat)
try:
# Only need to get one item from generator
next(matches)
except StopIteration:
return False
else:
return True

return f
"""
This module is inspired by the `rprojroot` library for R.
See https://github.com/r-lib/rprojroot.
It is intended for interactive or programmatic only.
"""

import pathlib as _pathlib
import typing
from os import PathLike as _PathLike

# TODO: It would be nice to have a class that encapsulates these checks,
# so that we can implement methods like |, !, &, ^ operators

# TODO: Refactor in a way that allows creation of reasons


def as_root_criterion(criterion) -> typing.Callable:
if callable(criterion):
return criterion

# criterion must be a Collection, rather than just Iterable
if isinstance(criterion, _PathLike):
criterion = [criterion]
criterion = list(criterion)

def f(path: _pathlib.Path) -> bool:
for c in criterion:
if isinstance(c, _PathLike):
if (path / c).exists():
return True
else:
if c(path):
return True
return False

return f


def has_file(file: _PathLike) -> typing.Callable:
"""
Check that specified file exists in path.
Note that a directory with that name will not match.
"""

def f(path: _pathlib.Path) -> bool:
return (path / file).is_file()

return f


def has_dir(file: _PathLike) -> typing.Callable:
"""
Check that specified directory exists.
Note that a regular file with that name will not match.
"""

def f(path: _pathlib.Path) -> bool:
return (path / file).is_dir()

return f


def matches_glob(pat: str) -> typing.Callable:
"""
Check that glob has at least one match.
"""

def f(path: _pathlib.Path) -> bool:
matches = path.glob(pat)
try:
# Only need to get one item from generator
next(matches)
except StopIteration:
return False
else:
return True

return f
110 changes: 55 additions & 55 deletions pyprojroot/here.py → src/pyprojroot/here.py
Original file line number Diff line number Diff line change
@@ -1,55 +1,55 @@
"""
This module is inspired by the `here` library for R.
See https://github.com/r-lib/here.
It is intended for interactive use only.
"""

import pathlib as _pathlib
import warnings as _warnings
from os import PathLike as _PathLike

from . import criterion
from .root import find_root, find_root_with_reason

CRITERIA = [
criterion.has_file(".here"),
criterion.has_dir(".git"),
criterion.matches_glob("*.Rproj"),
criterion.has_file("requirements.txt"),
criterion.has_file("setup.py"),
criterion.has_dir(".dvc"),
criterion.has_dir(".spyproject"),
criterion.has_file("pyproject.toml"),
criterion.has_dir(".idea"),
criterion.has_dir(".vscode"),
]


def get_here():
# TODO: This should only find_root once per session
start = _pathlib.Path.cwd()
path, reason = find_root_with_reason(CRITERIA, start=start)
return path, reason


# TODO: Implement set_here


def here(relative_project_path: _PathLike = "", warn_missing=False) -> _pathlib.Path:
"""
Returns the path relative to the projects root directory.
:param relative_project_path: relative path from project root
:param project_files: list of files to track inside the project
:param warn_missing: warn user if path does not exist (default=False)
:return: pathlib path
"""
path, reason = get_here()
# TODO: Show reason when requested

if relative_project_path:
path = path / relative_project_path

if warn_missing and not path.exists():
_warnings.warn(f"Path doesn't exist: {path!s}")
return path
"""
This module is inspired by the `here` library for R.
See https://github.com/r-lib/here.
It is intended for interactive use only.
"""

import pathlib as _pathlib
import warnings as _warnings
from os import PathLike as _PathLike

from . import criterion
from .root import find_root, find_root_with_reason

CRITERIA = [
criterion.has_file(".here"),
criterion.has_dir(".git"),
criterion.matches_glob("*.Rproj"),
criterion.has_file("requirements.txt"),
criterion.has_file("setup.py"),
criterion.has_dir(".dvc"),
criterion.has_dir(".spyproject"),
criterion.has_file("pyproject.toml"),
criterion.has_dir(".idea"),
criterion.has_dir(".vscode"),
]


def get_here():
# TODO: This should only find_root once per session
start = _pathlib.Path.cwd()
path, reason = find_root_with_reason(CRITERIA, start=start)
return path, reason


# TODO: Implement set_here


def here(relative_project_path: _PathLike = "", warn_missing=False) -> _pathlib.Path:
"""
Returns the path relative to the projects root directory.
:param relative_project_path: relative path from project root
:param project_files: list of files to track inside the project
:param warn_missing: warn user if path does not exist (default=False)
:return: pathlib path
"""
path, reason = get_here()
# TODO: Show reason when requested

if relative_project_path:
path = path / relative_project_path

if warn_missing and not path.exists():
_warnings.warn(f"Path doesn't exist: {path!s}")
return path
File renamed without changes.
File renamed without changes.

0 comments on commit 4bbd99e

Please sign in to comment.