Skip to content

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 :

Solution

Voir la solution