Skip to content

Commit 4e19096

Browse files
committed
fix: replace insecure /tmp usage with tempfile module in tests
1 parent 1d2d306 commit 4e19096

File tree

3 files changed

+117
-85
lines changed

3 files changed

+117
-85
lines changed

tests/test_messagebox.py

Lines changed: 26 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
# pylint: disable=import-outside-toplevel,protected-access
2+
import tempfile
23
from unittest.mock import MagicMock, patch
34

45
import pytest
@@ -604,22 +605,32 @@ def test_custom_messagebox_icon_file_success(root):
604605
"""Test successful icon file loading path in _get_icon_label."""
605606
from tkface.dialog.messagebox import CustomMessageBox, MessageBoxConfig
606607

607-
with (
608-
patch("tkinter.Toplevel.wait_window"),
609-
patch("tkinter.PhotoImage") as mock_photo,
610-
patch("tkinter.Label") as mock_label,
611-
patch("tkinter.Button"),
612-
):
613-
mock_photo.return_value = MagicMock(name="Image")
614-
CustomMessageBox(
615-
master=root,
616-
config=MessageBoxConfig(message="Test", icon="/tmp/icon.png"),
608+
with tempfile.NamedTemporaryFile(suffix=".png", delete=False) as temp_file:
609+
temp_icon_path = temp_file.name
610+
611+
try:
612+
with (
613+
patch("tkinter.Toplevel.wait_window"),
614+
patch("tkinter.PhotoImage") as mock_photo,
615+
patch("tkinter.Label") as mock_label,
616+
patch("tkinter.Button"),
617+
):
618+
mock_photo.return_value = MagicMock(name="Image")
619+
CustomMessageBox(
620+
master=root,
621+
config=MessageBoxConfig(message="Test", icon=temp_icon_path),
622+
)
623+
# Ensure a Label was created with the image returned by PhotoImage
624+
assert any(
625+
("image" in call.kwargs) and (call.kwargs["image"] is mock_photo.return_value)
626+
for call in mock_label.call_args_list
617627
)
618-
# Ensure a Label was created with the image returned by PhotoImage
619-
assert any(
620-
("image" in call.kwargs) and (call.kwargs["image"] is mock_photo.return_value)
621-
for call in mock_label.call_args_list
622-
)
628+
finally:
629+
import os
630+
try:
631+
os.unlink(temp_icon_path)
632+
except OSError:
633+
pass
623634

624635

625636
def test_classmethod_show_created_root(root):

tests/test_pathbrowser.py

Lines changed: 23 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -650,17 +650,18 @@ def test_pathbrowser_initialization(self, root):
650650

651651
def test_pathbrowser_initialization_with_params(self, root):
652652
"""Test PathBrowser initialization with parameters."""
653-
browser = PathBrowser(
654-
root,
655-
select="dir",
656-
multiple=True,
657-
initialdir="/tmp",
658-
filetypes=[("Text files", "*.txt")]
659-
)
660-
assert browser.config.select == "dir"
661-
assert browser.config.multiple is True
662-
assert browser.config.initialdir == "/tmp"
663-
assert browser.config.filetypes == [("Text files", "*.txt")]
653+
with tempfile.TemporaryDirectory() as temp_dir:
654+
browser = PathBrowser(
655+
root,
656+
select="dir",
657+
multiple=True,
658+
initialdir=temp_dir,
659+
filetypes=[("Text files", "*.txt")]
660+
)
661+
assert browser.config.select == "dir"
662+
assert browser.config.multiple is True
663+
assert browser.config.initialdir == temp_dir
664+
assert browser.config.filetypes == [("Text files", "*.txt")]
664665

665666
def test_pathbrowser_save_mode(self, root):
666667
"""Test PathBrowser in save mode."""
@@ -669,16 +670,17 @@ def test_pathbrowser_save_mode(self, root):
669670

670671
def test_get_selection_save_mode(self, root, dict_like_mock):
671672
"""Test get_selection in save mode."""
672-
browser = PathBrowser(root, save_mode=True)
673-
# Mock the selected_var
674-
browser.selected_var = dict_like_mock
675-
browser.selected_var.get.return_value = "test.txt"
676-
browser.state.current_dir = "/tmp"
677-
678-
selection = browser.get_selection()
679-
# Handle Windows path separators
680-
expected_path = os.path.join("/tmp", "test.txt")
681-
assert selection == [expected_path]
673+
with tempfile.TemporaryDirectory() as temp_dir:
674+
browser = PathBrowser(root, save_mode=True)
675+
# Mock the selected_var
676+
browser.selected_var = dict_like_mock
677+
browser.selected_var.get.return_value = "test.txt"
678+
browser.state.current_dir = temp_dir
679+
680+
selection = browser.get_selection()
681+
# Handle Windows path separators
682+
expected_path = os.path.join(temp_dir, "test.txt")
683+
assert selection == [expected_path]
682684

683685
def test_get_selection_normal_mode(self, root):
684686
"""Test get_selection in normal mode."""

tests/test_pathbrowser_view.py

Lines changed: 68 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
- show_context_menu
99
"""
1010

11+
import tempfile
1112
import tkinter as tk
1213
from pathlib import Path
1314
from types import SimpleNamespace
@@ -97,50 +98,56 @@ def test_update_selected_display_no_selection(self, browser_with_state):
9798
assert mock_status.called
9899

99100
def test_update_selected_display_single_file(self, browser_with_state):
100-
browser_with_state.state.selected_items = ["/tmp/a.txt"]
101-
browser_with_state.selected_var = Mock()
102-
browser_with_state.selected_var.set = Mock()
103-
with patch.object(browser_with_state, "_update_status"):
104-
with patch.object(
105-
browser_with_state.file_info_manager,
106-
"get_cached_file_info",
107-
return_value=SimpleNamespace(is_dir=False, name="a.txt"),
108-
):
109-
view.update_selected_display(browser_with_state)
110-
browser_with_state.selected_var.set.assert_called_with("a.txt")
101+
with tempfile.TemporaryDirectory() as temp_dir:
102+
temp_file_path = f"{temp_dir}/a.txt"
103+
browser_with_state.state.selected_items = [temp_file_path]
104+
browser_with_state.selected_var = Mock()
105+
browser_with_state.selected_var.set = Mock()
106+
with patch.object(browser_with_state, "_update_status"):
107+
with patch.object(
108+
browser_with_state.file_info_manager,
109+
"get_cached_file_info",
110+
return_value=SimpleNamespace(is_dir=False, name="a.txt"),
111+
):
112+
view.update_selected_display(browser_with_state)
113+
browser_with_state.selected_var.set.assert_called_with("a.txt")
111114

112115
def test_update_selected_display_multiple_files_compact(self, browser_with_state):
113-
browser_with_state.state.selected_items = ["/tmp/a.txt", "/tmp/b.txt", "/tmp/c.txt", "/tmp/d.txt"]
114-
browser_with_state.selected_var = Mock()
115-
browser_with_state.selected_var.set = Mock()
116-
# Return non-dir with distinct names
117-
def _get_info(path):
118-
name = Path(path).name
119-
m = Mock()
120-
m.is_dir = False
121-
m.name = name
122-
return m
123-
with patch.object(browser_with_state, "_update_status"):
116+
with tempfile.TemporaryDirectory() as temp_dir:
117+
temp_files = [f"{temp_dir}/a.txt", f"{temp_dir}/b.txt", f"{temp_dir}/c.txt", f"{temp_dir}/d.txt"]
118+
browser_with_state.state.selected_items = temp_files
119+
browser_with_state.selected_var = Mock()
120+
browser_with_state.selected_var.set = Mock()
121+
# Return non-dir with distinct names
122+
def _get_info(path):
123+
name = Path(path).name
124+
m = Mock()
125+
m.is_dir = False
126+
m.name = name
127+
return m
128+
with patch.object(browser_with_state, "_update_status"):
129+
with patch.object(
130+
browser_with_state.file_info_manager,
131+
"get_cached_file_info",
132+
side_effect=_get_info,
133+
):
134+
view.update_selected_display(browser_with_state)
135+
# Should show first with +n more
136+
browser_with_state.selected_var.set.assert_called_with("a.txt (+3 more)")
137+
138+
def test_update_selected_display_dirs_only(self, browser_with_state):
139+
with tempfile.TemporaryDirectory() as temp_dir:
140+
temp_dirs = [f"{temp_dir}/dirA", f"{temp_dir}/dirB"]
141+
browser_with_state.state.selected_items = temp_dirs
142+
browser_with_state.selected_var = Mock()
143+
browser_with_state.selected_var.set = Mock()
124144
with patch.object(
125145
browser_with_state.file_info_manager,
126146
"get_cached_file_info",
127-
side_effect=_get_info,
147+
return_value=Mock(is_dir=True, name="dirA"),
128148
):
129149
view.update_selected_display(browser_with_state)
130-
# Should show first with +n more
131-
browser_with_state.selected_var.set.assert_called_with("a.txt (+3 more)")
132-
133-
def test_update_selected_display_dirs_only(self, browser_with_state):
134-
browser_with_state.state.selected_items = ["/tmp/dirA", "/tmp/dirB"]
135-
browser_with_state.selected_var = Mock()
136-
browser_with_state.selected_var.set = Mock()
137-
with patch.object(
138-
browser_with_state.file_info_manager,
139-
"get_cached_file_info",
140-
return_value=Mock(is_dir=True, name="dirA"),
141-
):
142-
view.update_selected_display(browser_with_state)
143-
browser_with_state.selected_var.set.assert_called_with("")
150+
browser_with_state.selected_var.set.assert_called_with("")
144151

145152

146153
class TestUpdateDirectoryStatus:
@@ -182,9 +189,11 @@ def name(self): # for formatting in error branch
182189
class TestShowContextMenu:
183190
def test_show_context_menu_tree_expand_collapse(self, browser_with_state):
184191
# Prepare tree selection with a directory node
185-
browser_with_state.tree = Mock()
186-
browser_with_state.tree.selection.return_value = ["/tmp/dir"]
187-
browser_with_state.tree.item.return_value = True
192+
with tempfile.TemporaryDirectory() as temp_dir:
193+
temp_dir_path = f"{temp_dir}/dir"
194+
browser_with_state.tree = Mock()
195+
browser_with_state.tree.selection.return_value = [temp_dir_path]
196+
browser_with_state.tree.item.return_value = True
188197
with patch.object(
189198
browser_with_state.file_info_manager,
190199
"get_file_info",
@@ -204,11 +213,13 @@ def test_show_context_menu_tree_expand_collapse(self, browser_with_state):
204213
mock_menu.post.assert_called_once()
205214

206215
def test_show_context_menu_file_menu(self, browser_with_state):
207-
browser_with_state.file_tree = Mock()
208-
browser_with_state.file_tree.selection.return_value = ["/tmp/a.txt"]
209-
event = Mock()
210-
event.x_root = 0
211-
event.y_root = 0
216+
with tempfile.TemporaryDirectory() as temp_dir:
217+
temp_file_path = f"{temp_dir}/a.txt"
218+
browser_with_state.file_tree = Mock()
219+
browser_with_state.file_tree.selection.return_value = [temp_file_path]
220+
event = Mock()
221+
event.x_root = 0
222+
event.y_root = 0
212223
with patch("tkinter.Menu") as mock_menu_cls:
213224
mock_menu = Mock()
214225
mock_menu_cls.return_value = mock_menu
@@ -465,7 +476,9 @@ def test_load_files_large_directory_progress(self, browser_with_state, tmp_path)
465476
class TestUpdateSelectionStatus:
466477
def test_update_selection_status_single_folder(self, browser_with_state):
467478
"""Test status update for single folder selection."""
468-
browser_with_state.state.selected_items = ["/tmp/dir"]
479+
with tempfile.TemporaryDirectory() as temp_dir:
480+
temp_dir_path = f"{temp_dir}/dir"
481+
browser_with_state.state.selected_items = [temp_dir_path]
469482
browser_with_state.status_var = Mock()
470483

471484
mock_file_info = Mock()
@@ -485,7 +498,9 @@ def test_update_selection_status_single_folder(self, browser_with_state):
485498

486499
def test_update_selection_status_multiple_folders(self, browser_with_state):
487500
"""Test status update for multiple folder selection."""
488-
browser_with_state.state.selected_items = ["/tmp/dir1", "/tmp/dir2"]
501+
with tempfile.TemporaryDirectory() as temp_dir:
502+
temp_dirs = [f"{temp_dir}/dir1", f"{temp_dir}/dir2"]
503+
browser_with_state.state.selected_items = temp_dirs
489504
browser_with_state.status_var = Mock()
490505

491506
mock_file_info = Mock()
@@ -729,7 +744,9 @@ def test_load_files_permission_error_dialog(self, browser_with_state):
729744
class TestUpdateSelectionStatusAdditional:
730745
def test_update_selection_status_single_file_with_size(self, browser_with_state):
731746
"""Test status update for single file with size."""
732-
browser_with_state.state.selected_items = ["/tmp/file.txt"]
747+
with tempfile.TemporaryDirectory() as temp_dir:
748+
temp_file_path = f"{temp_dir}/file.txt"
749+
browser_with_state.state.selected_items = [temp_file_path]
733750
browser_with_state.status_var = Mock()
734751

735752
mock_file_info = Mock()
@@ -750,7 +767,9 @@ def test_update_selection_status_single_file_with_size(self, browser_with_state)
750767

751768
def test_update_selection_status_multiple_files_with_size(self, browser_with_state):
752769
"""Test status update for multiple files with size."""
753-
browser_with_state.state.selected_items = ["/tmp/file1.txt", "/tmp/file2.txt"]
770+
with tempfile.TemporaryDirectory() as temp_dir:
771+
temp_files = [f"{temp_dir}/file1.txt", f"{temp_dir}/file2.txt"]
772+
browser_with_state.state.selected_items = temp_files
754773
browser_with_state.status_var = Mock()
755774

756775
mock_file_info = Mock()

0 commit comments

Comments
 (0)