X3IANZNCU5AF7H3YGJ4EUOIP3TKSQNZKVEY7I36NZY7NLI7R6YXQC
DCOF764JDXAREHUOIUZ5LCO47QEOPHSS2KKAYQGV7PDHOWDG5WDAC
QYSR4PDNVTQOISVLQMO5M7MYBEG37SV6Y7JGM6QPC3CA2BJAYPYQC
5FLTMCXWFLP6MI36R73NDC5ZZGKRB66IXOWY7ZTESTLC7M357H2QC
HZ4SV4CG73RCVZ3B4FX3VQA44JEW546NYJWOQF6VGEVRGDR5TAUAC
T7CTIGVFEE6SQAQTZ3PENHCH5RRFJ3EBWXGHVALXA7BSI4ZY2NUAC
DTNETCKQOYKWBQCHFC3EUTRFBHB4E3VZVCBRN6OFD6KWTBR3W5RQC
N7DHDONTAB6UEU4PHQR7BNSUQFAA4JBIVSTKDQ7V7OF3CLOEWXOQC
BN7PSYS5IMGH4CXNCQZGOWBETO7KY4TKICB4ESZEZVXVGLOPVV7QC
from pathlib import Path
from ..scripts.path_finder import PathFinder
def test_find_first_does_not_exist(tmp_path: Path):
path_finder = PathFinder([tmp_path])
assert not tmp_path.joinpath("needle.txt").exists()
assert path_finder.find_first("needle") is None
assert path_finder.find_first("needle", parent_name="anything") is None
def test_find_first_parent_exists_needle_does_not(tmp_path: Path):
tmp_path.joinpath("parent").mkdir()
nest_one = tmp_path.joinpath("parent/nest_one")
nest_two = tmp_path.joinpath("parent/nest_two")
nest_one.mkdir()
nest_two.mkdir()
path_finder = PathFinder([nest_one])
assert path_finder.find_first("needle") is None
assert path_finder.find_first("needle", parent_name="nest_two") is None
def test_find_first_success_needle_in_parent_nested(tmp_path):
search_dir = tmp_path.joinpath("thing/nested/bin")
bundle_dir = search_dir.parent.parent.joinpath("bundle_dir")
search_dir.mkdir(parents=True)
bundle_dir.mkdir(parents=True)
bundle_dir.joinpath("Bundle.app").write_text("app here 😎")
actual = PathFinder(paths=[search_dir]).find_first(
"Bundle.app", parent_name="bundle_dir"
)
assert actual is not None and actual.exists()
def test_find_first_needle_in_path(tmp_path: Path):
path_dir = tmp_path.joinpath("thing/nested/bin")
path_dir.mkdir(parents=True)
(path_dir / "file.txt").write_text("hi there :)")
actual = PathFinder(paths=[path_dir]).find_first("file.txt")
assert actual is not None and actual.exists()
def test_find_first_depends_on_sort_order_of_paths(tmp_path: Path):
no_match = tmp_path.joinpath("nomatch")
no_match.mkdir()
match_one = tmp_path.joinpath("one/file.txt")
match_two = tmp_path.joinpath("two/file.txt")
match_one.parent.mkdir()
match_two.parent.mkdir()
match_one.write_text("hi from match_one :)")
match_two.write_text("hi from match_two :)")
assert (
PathFinder([no_match, match_one, match_two]).find_first("file.txt") == match_one
)
assert (
PathFinder([no_match, match_two, match_one]).find_first("file.txt") == match_two
)
def test_find_many(tmp_path: Path):
no_match = tmp_path.joinpath("nomatch")
no_match.mkdir()
match_one = tmp_path.joinpath("one/file.txt")
match_two = tmp_path.joinpath("two/file.txt")
match_one.parent.mkdir()
match_two.parent.mkdir()
match_one.write_text("hi from match_one :)")
match_two.write_text("hi from match_two :)")
path_finder = PathFinder([no_match.parent, match_one.parent, match_two])
assert list(path_finder.find("file.txt")) == [match_one, match_two]
def test_find_many_paths_contain_result(tmp_path: Path):
"""if given full path PathFinder.find should return it."""
no_match = tmp_path.joinpath("nomatch")
no_match.mkdir()
match_one = tmp_path.joinpath("one/file.txt")
match_two = tmp_path.joinpath("two/file.txt")
match_one.parent.mkdir()
match_two.parent.mkdir()
match_one.write_text("hi from match_one :)")
match_two.write_text("hi from match_two :)")
path_finder = PathFinder([no_match, match_one, match_two])
assert list(path_finder.find("file.txt")) == [match_one, match_two]
import os
import sys
from dataclasses import dataclass
from pathlib import Path
from typing import Generator, Optional
@dataclass
class PathFinder:
paths: list[Path]
@classmethod
def from_env(cls) -> "PathFinder":
path = os.getenv("PATH")
if not path:
raise RuntimeError("PATH environment variable is not set.")
return cls(list(map(Path, path.split(":"))))
def find_first(self, name: str, parent_name: str = "") -> Optional[Path]:
return next(self.find(name, parent_name=parent_name), None)
def find(self, name: str, parent_name: str = "") -> Generator[Path, None, None]:
for path in self.paths:
if not path.is_dir():
path = path.parent
if parent_name:
parents = (parent.joinpath(parent_name) for parent in path.parents)
path = next((parent for parent in parents if parent.exists()), path)
result_path = path.joinpath(name)
if result_path.exists():
yield result_path
if __name__ == "__main__":
if 2 > len(sys.argv) < 3:
print("USAGE:path_finder name [parent_name]", file=sys.stderr)
sys.exit(1)
_, name, *rest = sys.argv
if rest:
parent_name = rest[0]
else:
parent_name = ""
if path_finder := PathFinder.from_env().find_first(name, parent_name=parent_name):
print(path_finder)
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-yaml
- id: check-added-large-files
- id: destroyed-symlinks
- id: mixed-line-ending
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-yaml
- id: check-added-large-files
- id: destroyed-symlinks
- id: mixed-line-ending
- repo: https://github.com/syntaqx/git-hooks
rev: v0.0.17
hooks:
# NOTE: these require shellcheck and shfmt to be installed in the environment
# they should be installd by lorri -> direnv -> nix-shell automatically
# checkout ~/dotfiles/shell.nix
- id: shellcheck
- id: shfmt
- repo: https://github.com/executablebooks/mdformat
rev: 0.7.8
hooks:
- id: mdformat
- id: nixpkgs-fmt
name: nixpkgs-fmt
description: Format nix code with nixpkgs-fmt.
entry: nixpkgs-fmt
language: system
files: \.nix$
always_run: true
minimum_pre_commit_version: 1.14.2
- id: nixpkgs-fmt
name: nixpkgs-fmt
description: Format nix code with nixpkgs-fmt.
entry: nixpkgs-fmt
language: system
files: \.nix$
always_run: true
minimum_pre_commit_version: 1.14.2
- id: mdl-markdown-linter
name: markdown-linter
description: ruby gem to lint markdown files
entry: mdl -g
language: system
types: [markdown]
minimum_pre_commit_version: 1.14.2
- id: mdl-markdown-linter
name: markdown-linter
description: ruby gem to lint markdown files
entry: mdl -g
language: system
types: [markdown]
minimum_pre_commit_version: 1.14.2
- id: python-format-black
name: python-black
description: format python with black
entry: black
language: system
types: [python]
- id: python-sort-imports
name: python-isort
description: format python imports with isort
entry: isort
language: system
types: [python]
- id: python-lint-flake8
name: python-flake8
description: python flake8
entry: flake8
language: system
types: [python]
- id: python-type-check-pyright
name: python-type-check-pyright
description: python type check pyright
entry: pyright
args: [./]
language: system
types: [python]
pass_filenames: false
always_run: true
- id: python-pytest
name: python-pytest
description: python pytest
entry: pytest
language: system
types: [python]
pass_filenames: false
always_run: true
#!/usr/bin/env sh
_cwd=$(pwd)
_pyroot=$(find . -name pyproject.toml | sed 's/\/pyproject.toml//')
cd "$_pyroot" || exit
eval "$@"
cd "$_cwd" || exit
__pycache__/