Guide avancé¶
Tu n'as besoin de rien de tout ça pour un usage quotidien. Utilise ces outils quand il te faut des marqueurs de projet sur mesure, des aides pour les tests, des réglages de déploiement ou du débogage approfondi.
Marqueurs sur mesure : find_root()¶
find_root() cherche une racine selon tes propres critères, sans rien mettre
en cache et sans toucher à la racine de la session. Construis les critères avec
has_file, has_dir ou has_glob. Un dossier correspond s'il satisfait l'un
d'eux.
from herepath import find_root, has_file, has_dir, has_glob
find_root(has_file("Makefile")) # cherche un Makefile
find_root(has_file("Makefile"), has_dir(".git")) # Makefile OU dossier .git
find_root(has_glob("*.toml"), start="sous/dossier") # part d'ailleurs
C'est l'équivalent du rprojroot::find_root de R, pour les utilisateurs qui
veulent du contrôle sans changer le comportement de here().
Les trois constructeurs de critères
| Constructeur | Correspond à un dossier qui contient... |
|---|---|
has_file("nom") |
un fichier nommé nom |
has_dir("nom") |
un sous-dossier nommé nom |
has_glob("*.ext") |
au moins un fichier correspondant au motif |
Changer les marqueurs par défaut : set_criteria()¶
Si ton organisation utilise un marqueur maison (par exemple
company_project.json), tu peux remplacer les critères de détection pour toute
la session :
from herepath import set_criteria, reset_criteria, has_file, has_dir
set_criteria(has_file("company_project.json"), has_dir("src"))
here() # utilise maintenant ces marqueurs
reset_criteria() # revient aux marqueurs par défaut
set_criteria remplace, il n'ajoute pas
set_criteria remplace les défauts ; il ne s'ajoute pas. Si tu veux
garder .here ou .git, inclus-les dans ton appel :
set_criteria() et reset_criteria() vident la racine en cache, donc le
changement prend effet au prochain appel à here().
Dans les tests : using_root()¶
Ce gestionnaire de contexte fixe la racine le temps d'un bloc, puis remet l'état précédent en sortie. Idéal pour les tests.
from herepath import using_root, here
def test_lecture(tmp_path):
with using_root(tmp_path):
assert here("data") == tmp_path / "data"
# la racine d'avant est rétablie ici
Mono-thread uniquement
using_root sauvegarde et restaure un état global au processus. C'est
prévu pour du code mono-thread (tests, notebooks). Ne modifie pas la racine
depuis un autre thread (reset(), i_am(), un autre using_root()) pendant
qu'un bloc est actif : la restauration en sortie écraserait le changement
concurrent. Si tu as besoin d'une racine par thread ou par tâche, gère-la
toi-même.
Forcer la racine : HEREPATH_ROOT¶
En Docker, en CI ou en déploiement, la détection automatique peut ne pas s'appliquer. Tu peux alors imposer la racine avec une variable d'environnement :
Si la valeur n'est pas un dossier existant, here() lève une ValueError tout de
suite, pour que la mauvaise configuration se voie. Un appel explicite à i_am()
reste prioritaire.
Ordre de priorité
Quand here() résout la racine, il vérifie, dans l'ordre :
- Une déclaration explicite
i_am()/using_root()/set_here(). - La variable d'environnement
HEREPATH_ROOT. - La détection automatique via les critères actifs.
- Le repli sur le répertoire de travail courant.
Déboguer une détection : dr_here(trace=True)¶
Quand herepath choisit la mauvaise racine, demande la trace complète de la
recherche :
here() starts at /projet.
- This directory contains a file `pyproject.toml`
...
Searching from:
/projet/notebooks
Checking:
/projet/notebooks
/projet <- contains a file `pyproject.toml`
Matched:
/projet
Tu vois exactement quels dossiers ont été examinés et lequel a gagné. Pratique à coller dans un ticket GitHub.
Quand ne pas utiliser herepath¶
herepath est fait pour le code que tu lances depuis un projet : scripts,
notebooks, analyses. Il n'est pas fait pour une bibliothèque installée, car
une fois le paquet installé, l'arborescence des sources n'existe plus. Pour lire
des données livrées avec un paquet installé, utilise
importlib.resources
à la place.
Bonus : un sélecteur de fichiers avec pyfilechoose¶
pyfilechoose est un autre petit paquet (même auteur) qui porte le
file.choose() de R en Python : il ouvre une fenêtre pour choisir un fichier et
renvoie son chemin. Il se marie bien avec herepath, parce que son paramètre
initialdir accepte un dossier de départ, et here() fournit justement ça : un
dossier stable du projet.
from herepath import here
from pyfilechoose import file_choose, files_choose
# la fenêtre s'ouvre directement dans le dossier data/ du projet
chemin = file_choose(initialdir=here("data"))
# plusieurs fichiers, en partant de la racine du projet
chemins = files_choose(initialdir=here())
L'idée : herepath décide où regarder (un dossier fiable du projet), et
pyfilechoose laisse l'utilisateur choisir quoi dedans.
Warning
pyfilechoose ouvre une fenêtre graphique (via tkinter). Réserve-le à un
usage interactif (scripts, notebooks), pas à un serveur ou à la CI.
Différences avec le paquet R¶
herepath est un portage fidèle du here de R : même philosophie, mêmes quatre
fonctions de base (here, i_am, set_here, dr_here). Si tu connais le R, tu
es en terrain connu. Mais il y a des différences : certaines imposées par Python,
d'autres que herepath ajoute volontairement.
| Aspect | R here |
herepath |
|---|---|---|
| Type de retour | chaîne de caractères | objet pathlib.Path |
| Remplace | file.path() |
os.path.join() |
| Quand la racine est résolue | au chargement du paquet (library(here)) |
au premier appel à here() (paresseux) |
| Moteur de détection | délègue à rprojroot |
son propre système Criterion, sans dépendance |
| Message au démarrage | oui (affiché à l'attache) | non (import silencieux), mais i_am() confirme |
Les trois différences qui comptent vraiment :
- Type de retour. R renvoie des chaînes,
herepathrenvoie desPath. Plus pratique avecopen(),pandas, etc. Faisstr()si tu veux une chaîne. - Moment de la résolution. En R, la racine est fixée au chargement du paquet.
Python n'a pas ce point d'accroche, donc
herepathrésout au premier appel. - Les marqueurs de racine.
herepathremplace les marqueurs R par des marqueurs Python :
R here |
herepath |
|
|---|---|---|
| Communs | .here, .vscode, _quarto.yml, .git/.svn |
idem, plus .idea, .hg, *.Rproj (compat) |
| Spécifiques | DESCRIPTION, renv.lock, remake.yml, .projectile |
pyproject.toml, setup.py, setup.cfg, Pipfile, poetry.lock, environment.yml |
Note
herepath exclut volontairement requirements.txt, trop souvent dupliqué
dans docs/ ou tests/, ce qui ancrerait la racine au mauvais endroit.
Ce que herepath ajoute et que le here de R n'a pas :
reset(), etfind_root()avechas_file/has_dir/has_glob(en R, ça vit dansrprojroot, pas danshere).set_criteria()/reset_criteria()pour changer les marqueurs.using_root()pour les tests.- La variable d'environnement
HEREPATH_ROOT. - Une commande CLI
herepath. - Le mode
dr_here(trace=True). - La sécurité multi-thread (un verrou).
Donc : la même API de base que le R, adaptée à Python (retour Path, marqueurs
Python, résolution paresseuse), avec moins de dépendances et quelques commodités
en plus.