Skip to content

Commit b692589

Browse files
WillSoltasWill Soltaspre-commit-ci[bot]
authored
Migrated file_ops.py and scene_file_writer.py from os.path to Pathlib (#2642)
* Migrated file_ops.py and scene_file_writer.py from os.path to Pathlib (github issue #45) * Updated scene_file_writer.py to handle WindowsPaths * Updated scene_file_writer.py to handle WindowsPaths * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Updated file_ops.py to handle WindowsPaths * Updated scene_file_writer.py to handle WindowsPaths * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Fixed Merge Conflict: Added Type Hints in file_ops.py * Changed test_file_ops to use Pathlib in accordance with file_ops.py usage * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci Co-authored-by: Will Soltas <[email protected]> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
1 parent ea7455d commit b692589

File tree

3 files changed

+51
-55
lines changed

3 files changed

+51
-55
lines changed

manim/scene/scene_file_writer.py

Lines changed: 29 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -111,9 +111,8 @@ def init_output_directories(self, scene_name):
111111
"images_dir", module_name=module_name, scene_name=scene_name
112112
),
113113
)
114-
self.image_file_path = os.path.join(
115-
image_dir,
116-
add_extension_if_not_present(self.output_name, ".png"),
114+
self.image_file_path = image_dir / add_extension_if_not_present(
115+
self.output_name, ".png"
117116
)
118117

119118
if write_to_movie():
@@ -122,14 +121,10 @@ def init_output_directories(self, scene_name):
122121
"video_dir", module_name=module_name, scene_name=scene_name
123122
),
124123
)
125-
126-
self.movie_file_path = os.path.join(
127-
movie_dir,
128-
add_extension_if_not_present(
129-
self.output_name,
130-
config["movie_file_extension"],
131-
),
124+
self.movie_file_path = movie_dir / add_extension_if_not_present(
125+
self.output_name, config["movie_file_extension"]
132126
)
127+
133128
# TODO: /dev/null would be good in case sections_output_dir is used without bein set (doesn't work on Windows), everyone likes defensive programming, right?
134129
self.sections_output_dir = ""
135130
if config.save_sections:
@@ -149,7 +144,7 @@ def init_output_directories(self, scene_name):
149144
self.gif_file_path
150145
)
151146

152-
self.gif_file_path = os.path.join(movie_dir, self.gif_file_path)
147+
self.gif_file_path = movie_dir / self.gif_file_path
153148

154149
self.partial_movie_directory = guarantee_existence(
155150
config.get_dir(
@@ -213,9 +208,9 @@ def add_partial_movie_file(self, hash_animation):
213208
self.partial_movie_files.append(None)
214209
self.sections[-1].partial_movie_files.append(None)
215210
else:
216-
new_partial_movie_file = os.path.join(
217-
self.partial_movie_directory,
218-
f"{hash_animation}{config['movie_file_extension']}",
211+
new_partial_movie_file = str(
212+
self.partial_movie_directory
213+
/ f"{hash_animation}{config['movie_file_extension']}"
219214
)
220215
self.partial_movie_files.append(new_partial_movie_file)
221216
self.sections[-1].partial_movie_files.append(new_partial_movie_file)
@@ -380,7 +375,8 @@ def write_opengl_frame(self, renderer):
380375
renderer.get_raw_frame_buffer_object_data(),
381376
)
382377
elif is_png_format() and not config["dry_run"]:
383-
target_dir, extension = os.path.splitext(self.image_file_path)
378+
target_dir = self.image_file_path.parent / self.image_file_path.stem
379+
extension = self.image_file_path.suffix
384380
self.output_image(
385381
renderer.get_image(),
386382
target_dir,
@@ -389,7 +385,8 @@ def write_opengl_frame(self, renderer):
389385
)
390386

391387
def output_image_from_array(self, frame_data):
392-
target_dir, extension = os.path.splitext(self.image_file_path)
388+
target_dir = self.image_file_path.parent / self.image_file_path.stem
389+
extension = self.image_file_path.suffix
393390
self.output_image(
394391
Image.fromarray(frame_data),
395392
target_dir,
@@ -442,8 +439,8 @@ def finish(self):
442439
else:
443440
self.clean_cache()
444441
elif is_png_format() and not config["dry_run"]:
445-
target_dir, _ = os.path.splitext(self.image_file_path)
446-
logger.info("\n%i images ready at %s\n", self.frame_count, target_dir)
442+
target_dir = self.image_file_path.parent / self.image_file_path.stem
443+
logger.info("\n%i images ready at %s\n", self.frame_count, str(target_dir))
447444
if self.subcaptions:
448445
self.write_subcaption_file()
449446

@@ -524,11 +521,11 @@ def is_already_cached(self, hash_invocation):
524521
"""
525522
if not hasattr(self, "partial_movie_directory") or not write_to_movie():
526523
return False
527-
path = os.path.join(
528-
self.partial_movie_directory,
529-
f"{hash_invocation}{config['movie_file_extension']}",
524+
path = (
525+
self.partial_movie_directory
526+
/ f"{hash_invocation}{config['movie_file_extension']}"
530527
)
531-
return os.path.exists(path)
528+
return path.exists()
532529

533530
def combine_files(
534531
self,
@@ -537,17 +534,15 @@ def combine_files(
537534
create_gif=False,
538535
includes_sound=False,
539536
):
540-
file_list = os.path.join(
541-
self.partial_movie_directory,
542-
"partial_movie_file_list.txt",
543-
)
537+
file_list = str(self.partial_movie_directory / "partial_movie_file_list.txt")
544538
logger.debug(
545539
f"Partial movie files to combine ({len(input_files)} files): %(p)s",
546540
{"p": input_files[:5]},
547541
)
548542
with open(file_list, "w", encoding="utf-8") as fp:
549543
fp.write("# This file is used internally by FFMPEG.\n")
550544
for pf_path in input_files:
545+
pf_path = str(pf_path)
551546
if os.name == "nt":
552547
pf_path = pf_path.replace("\\", "/")
553548
fp.write(f"file 'file:{pf_path}'\n")
@@ -578,7 +573,7 @@ def combine_files(
578573
if not includes_sound:
579574
commands += ["-an"]
580575

581-
commands += [output_file]
576+
commands += [str(output_file)]
582577

583578
combine_process = subprocess.Popen(commands)
584579
combine_process.wait()
@@ -598,6 +593,7 @@ def combine_to_movie(self):
598593
movie_file_path = self.movie_file_path
599594
if is_gif_format():
600595
movie_file_path = self.gif_file_path
596+
movie_file_path = str(movie_file_path)
601597
logger.info("Combining to Movie file.")
602598
self.combine_files(
603599
partial_movie_files,
@@ -675,8 +671,8 @@ def combine_to_section_videos(self) -> None:
675671
def clean_cache(self):
676672
"""Will clean the cache by removing the oldest partial_movie_files."""
677673
cached_partial_movies = [
678-
os.path.join(self.partial_movie_directory, file_name)
679-
for file_name in os.listdir(self.partial_movie_directory)
674+
(self.partial_movie_directory / file_name)
675+
for file_name in self.partial_movie_directory.iterdir()
680676
if file_name != "partial_movie_file_list.txt"
681677
]
682678
if len(cached_partial_movies) > config["max_files_cached"]:
@@ -689,7 +685,7 @@ def clean_cache(self):
689685
)[:number_files_to_delete]
690686
# oldest_file_path = min(cached_partial_movies, key=os.path.getatime)
691687
for file_to_delete in oldest_files_to_delete:
692-
os.remove(file_to_delete)
688+
file_to_delete.unlink()
693689
logger.info(
694690
f"The partial movie directory is full (> {config['max_files_cached']} files). Therefore, manim has removed the {number_files_to_delete} oldest file(s)."
695691
" You can change this behaviour by changing max_files_cached in config.",
@@ -698,12 +694,12 @@ def clean_cache(self):
698694
def flush_cache_directory(self):
699695
"""Delete all the cached partial movie files"""
700696
cached_partial_movies = [
701-
os.path.join(self.partial_movie_directory, file_name)
702-
for file_name in os.listdir(self.partial_movie_directory)
697+
self.partial_movie_directory / file_name
698+
for file_name in self.partial_movie_directory.iterdir()
703699
if file_name != "partial_movie_file_list.txt"
704700
]
705701
for f in cached_partial_movies:
706-
os.remove(f)
702+
f.unlink()
707703
logger.info(
708704
f"Cache flushed. {len(cached_partial_movies)} file(s) deleted in %(par_dir)s.",
709705
{"par_dir": self.partial_movie_directory},

manim/utils/file_ops.py

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -135,27 +135,27 @@ def add_version_before_extension(file_name: Path) -> Path:
135135

136136

137137
def guarantee_existence(path: Path) -> Path:
138-
if not os.path.exists(path):
139-
os.makedirs(path)
140-
return Path(os.path.abspath(path))
138+
if not path.exists():
139+
path.mkdir(parents=True)
140+
return path.resolve(strict=True)
141141

142142

143143
def guarantee_empty_existence(path: Path) -> Path:
144-
if os.path.exists(path):
145-
shutil.rmtree(path)
146-
os.makedirs(path)
147-
return Path(os.path.abspath(path))
144+
if path.exists():
145+
shutil.rmtree(str(path))
146+
path.mkdir(parents=True)
147+
return path.resolve(strict=True)
148148

149149

150150
def seek_full_path_from_defaults(
151-
file_name: Path, default_dir: str, extensions: str
151+
file_name: str, default_dir: Path, extensions: list[str]
152152
) -> Path:
153-
possible_paths = [file_name]
153+
possible_paths = [Path(file_name)]
154154
possible_paths += [
155155
Path(default_dir) / f"{file_name}{extension}" for extension in ["", *extensions]
156156
]
157157
for path in possible_paths:
158-
if os.path.exists(path):
158+
if path.exists():
159159
return path
160160
error = f"From: {os.getcwd()}, could not find {file_name} at either of these locations: {possible_paths}"
161161
raise OSError(error)
@@ -175,14 +175,14 @@ def modify_atime(file_path) -> None:
175175
def open_file(file_path, in_browser=False):
176176
current_os = platform.system()
177177
if current_os == "Windows":
178-
os.startfile(file_path if not in_browser else os.path.dirname(file_path))
178+
os.startfile(file_path if not in_browser else file_path.parent)
179179
else:
180180
if current_os == "Linux":
181181
commands = ["xdg-open"]
182-
file_path = file_path if not in_browser else os.path.dirname(file_path)
182+
file_path = file_path if not in_browser else file_path.parent
183183
elif current_os.startswith("CYGWIN"):
184184
commands = ["cygstart"]
185-
file_path = file_path if not in_browser else os.path.dirname(file_path)
185+
file_path = file_path if not in_browser else file_path.parent
186186
elif current_os == "Darwin":
187187
if is_gif_format():
188188
commands = ["ffplay", "-loglevel", config["ffmpeg_loglevel"].lower()]

tests/test_file_ops.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,32 @@
11
from __future__ import annotations
22

3-
import os
3+
from pathlib import Path
44

55
from manim import *
66

77
from .assert_utils import assert_dir_exists, assert_file_not_exists
88
from .utils.video_tester import *
99

1010

11-
def test_guarantee_existence(tmp_path):
12-
test_dir = os.path.join(tmp_path, "test")
11+
def test_guarantee_existence(tmp_path: Path):
12+
test_dir = tmp_path / "test"
1313
guarantee_existence(test_dir)
1414
# test if file dir got created
1515
assert_dir_exists(test_dir)
16-
with open(os.path.join(test_dir, "test.txt"), "x") as f:
16+
with open(test_dir / "test.txt", "x") as f:
1717
pass
1818
# test if file didn't get deleted
1919
guarantee_existence(test_dir)
2020

2121

22-
def test_guarantee_empty_existence(tmp_path):
23-
test_dir = os.path.join(tmp_path, "test")
24-
os.mkdir(test_dir)
25-
with open(os.path.join(test_dir, "test.txt"), "x"):
22+
def test_guarantee_empty_existence(tmp_path: Path):
23+
test_dir = tmp_path / "test"
24+
test_dir.mkdir()
25+
with open(test_dir / "test.txt", "x"):
2626
pass
2727

2828
guarantee_empty_existence(test_dir)
2929
# test if dir got created
3030
assert_dir_exists(test_dir)
3131
# test if dir got cleaned
32-
assert_file_not_exists(os.path.join(test_dir, "test.txt"))
32+
assert_file_not_exists(test_dir / "test.txt")

0 commit comments

Comments
 (0)