ChangeDirectory¶
But de l’exercice¶
Le but de l’exercice est d’écrire un context manager cd dans un fichier changedirectory.py dont le but est de changer temporairement le répértoire courant d'execution.
Et voila le script de tests unitaires : test_changedirectory.py
Contexte¶
Il est très courant dans des scripts de devoir changer de repertoire courant d'execution, ne serait-ce que temporairement. Il faut donc, dans ces cas, faire en sorte de conserver le dossier courant, changer le dossier pour celui qui est voulu. Une fois le traitement effectué, il faudra donc revenir au dossier sauvé.
Je vous propose ici de faire ce traitement mais de maniere beaucoup plus intelligente et surtout reutilisable en changeant simplement une ligne, grace a un context manager.
Exercice de base¶
Ecrire un context manager (appelé cd) capable de changer de repertoire de travail temporairement.
Admettons que nous aillons créé un fichier de cette manière:
>>> import pathlib
>>> subdir = pathlib.Path('tmp_directory')
>>> subdir.mkdir()
>>> (subdir / 'text_file.txt').write_text('hello world!')
12
Testons donc cd pour accéder à ce fichier:
>>> with cd(subdir):
... print(pathlib.Path('text_file.txt').read_text())
...
hello world!
>>> pathlib.Path('text_file.txt').is_file()
False
Bien entendu, il faudra faire en sorte que l'on retourne dans le répértoire d'origine, même en cas de levée d'exception.
Il faut aussi faire en sorte que le context manager soit réentrant: on doit pouvoir utiliser cd même si nous sommes déjà dans un bloc géré par un autre cd.
>>> with cd(".."):
... with cd(subdir):
... print(pathlib.Path('text_file.txt').read_text())
...
hello world!
Il faudra faire attention à ce que le changement de répértoire ait lieu, non pas à la création, mais à l'utilisation du context manager dans un block with.
>>> change_cwd = cd(subdir)
>>> pathlib.Path('text_file.txt').is_file()
False
>>> with change_cwd:
... pathlib.Path('text_file.txt').is_file()
...
True
>>> pathlib.Path('cwd_file.txt').is_file()
False
Bonus numéro 1¶
Faire en sorte que le répértoire donné en argument soit optionnel. S'il n'est pas donné, alors il faudra créer un dossier temporaire et se deplacer dedans.
>>> print(pathlib.Path.cwd())
/home/moi
>>> with cd():
... print(pathlib.Path.cwd())
...
/tmp/tmp_cd_13954a
>>> print(pathlib.Path.cwd())
/home/moi
Lors de la sortie du block with il faudra nettoyer le répértoire créé ainsi que les fichiers qui pourraient rester à l'intérieur.
Bonus numéro 2¶
Faire en sorte que cd soit compatible avec la synthax with ... as ....
L'objet ainsi retourné devra mettre à disposition deux attributs:
* old_cwd: le répértoire de travail courant lors de l'entrée dans le context
* new_cwd: le répértoire donné à cd lors de sa construction
>>> with cd() as dir_ctx:
... print("Previous working dir:", dir_ctx.old_cwd)
... print("CWD:", dir_ctx.new_cwd)
...
Previous working dir: /home/moi
CWD: /tmp/tmp_cd_3954ab
Bonus numéro 3¶
Ajouter deux methodes enter et leave à notre objet cd afin de pouvoir l'utiliser sans bloc with ....
>>> pathlib.Path('text_file.txt').is_file()
False
>>> dir_ctx = cd(subdir)
>>> dir_ctx.enter()
>>> print(pathlib.Path('text_file.txt').read_text())
hello world!
>>> dir_ctx.leave()
>>> pathlib.Path('text_file.txt').is_file()
False
Aide¶
Si vraiment vous êtes bloqué·e·s, vous pouvez regarder ces articles :
- Ecrire un ContextManager
- Changer de repertoire courant
- Definir un ContextManager de gestion de resource en une fonction
- Creer un repertoire temporaire
- Effacer un repertoire
- Comment être compatible avec
with...as