flyshell 1.1.7__tar.gz → 1.1.9__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {flyshell-1.1.7/src/flyshell.egg-info → flyshell-1.1.9}/PKG-INFO +1 -1
- {flyshell-1.1.7 → flyshell-1.1.9}/src/flyshell/constants.py +2 -2
- {flyshell-1.1.7 → flyshell-1.1.9/src/flyshell.egg-info}/PKG-INFO +1 -1
- {flyshell-1.1.7 → flyshell-1.1.9}/src/flyshell.egg-info/SOURCES.txt +3 -1
- flyshell-1.1.9/tests/test_diskops.py +121 -0
- flyshell-1.1.9/tests/test_utils.py +72 -0
- {flyshell-1.1.7 → flyshell-1.1.9}/LICENSE +0 -0
- {flyshell-1.1.7 → flyshell-1.1.9}/README.md +0 -0
- {flyshell-1.1.7 → flyshell-1.1.9}/pyproject.toml +0 -0
- {flyshell-1.1.7 → flyshell-1.1.9}/setup.cfg +0 -0
- {flyshell-1.1.7 → flyshell-1.1.9}/src/flyshell/__init__.py +0 -0
- {flyshell-1.1.7 → flyshell-1.1.9}/src/flyshell/abstract/__init__.py +0 -0
- {flyshell-1.1.7 → flyshell-1.1.9}/src/flyshell/abstract/base_cmd.py +0 -0
- {flyshell-1.1.7 → flyshell-1.1.9}/src/flyshell/abstract/base_plugin.py +0 -0
- {flyshell-1.1.7 → flyshell-1.1.9}/src/flyshell/abstract/parent_cmd.py +0 -0
- {flyshell-1.1.7 → flyshell-1.1.9}/src/flyshell/builtin/__init__.py +0 -0
- {flyshell-1.1.7 → flyshell-1.1.9}/src/flyshell/builtin/diskops.py +0 -0
- {flyshell-1.1.7 → flyshell-1.1.9}/src/flyshell/builtin/fs.py +0 -0
- {flyshell-1.1.7 → flyshell-1.1.9}/src/flyshell/builtin/system.py +0 -0
- {flyshell-1.1.7 → flyshell-1.1.9}/src/flyshell/builtin/utils.py +0 -0
- {flyshell-1.1.7 → flyshell-1.1.9}/src/flyshell/core/__init__.py +0 -0
- {flyshell-1.1.7 → flyshell-1.1.9}/src/flyshell/core/auth.py +0 -0
- {flyshell-1.1.7 → flyshell-1.1.9}/src/flyshell/core/console.py +0 -0
- {flyshell-1.1.7 → flyshell-1.1.9}/src/flyshell/core/data.py +0 -0
- {flyshell-1.1.7 → flyshell-1.1.9}/src/flyshell/core/directory.py +0 -0
- {flyshell-1.1.7 → flyshell-1.1.9}/src/flyshell/core/loader.py +0 -0
- {flyshell-1.1.7 → flyshell-1.1.9}/src/flyshell/main.py +0 -0
- {flyshell-1.1.7 → flyshell-1.1.9}/src/flyshell.egg-info/dependency_links.txt +0 -0
- {flyshell-1.1.7 → flyshell-1.1.9}/src/flyshell.egg-info/entry_points.txt +0 -0
- {flyshell-1.1.7 → flyshell-1.1.9}/src/flyshell.egg-info/requires.txt +0 -0
- {flyshell-1.1.7 → flyshell-1.1.9}/src/flyshell.egg-info/top_level.txt +0 -0
- {flyshell-1.1.7 → flyshell-1.1.9}/tests/test_auth.py +0 -0
- {flyshell-1.1.7 → flyshell-1.1.9}/tests/test_data.py +0 -0
- {flyshell-1.1.7 → flyshell-1.1.9}/tests/test_directory.py +0 -0
- {flyshell-1.1.7 → flyshell-1.1.9}/tests/test_loader.py +0 -0
- {flyshell-1.1.7 → flyshell-1.1.9}/tests/test_security.py +0 -0
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
# tests\test_diskops.py
|
|
2
|
+
|
|
3
|
+
from flyshell.builtin import diskops
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def test_touch_creates_file_and_updates_timestamp(tmp_path):
|
|
7
|
+
cmd = diskops.Touch()
|
|
8
|
+
target = tmp_path / "test.txt"
|
|
9
|
+
code, msg = cmd.execute([str(target)])
|
|
10
|
+
assert code == 0
|
|
11
|
+
assert "Created file" in msg
|
|
12
|
+
assert target.exists()
|
|
13
|
+
code, msg = cmd.execute([str(target)])
|
|
14
|
+
assert code == 0
|
|
15
|
+
assert "Updated timestamp" in msg
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def test_touch_missing_parent_directory(tmp_path):
|
|
19
|
+
cmd = diskops.Touch()
|
|
20
|
+
target = tmp_path / "nonexistent_dir" / "test.txt"
|
|
21
|
+
code, msg = cmd.execute([str(target)])
|
|
22
|
+
assert code == 1
|
|
23
|
+
assert "Parent directory does not exist" in msg
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def test_cat_reads_content_with_limit_and_numbers(tmp_path):
|
|
27
|
+
file_path = tmp_path / "sample.txt"
|
|
28
|
+
file_path.write_text("line 1\nline 2\nline 3\nline 4\n")
|
|
29
|
+
cmd = diskops.Cat()
|
|
30
|
+
code, msg = cmd.execute([str(file_path)])
|
|
31
|
+
assert code == 0
|
|
32
|
+
assert "line 1" in msg and "line 4" in msg
|
|
33
|
+
code, msg = cmd.execute(["-n", "-l", "2", str(file_path)])
|
|
34
|
+
assert code == 0
|
|
35
|
+
assert "1 | line 1" in msg
|
|
36
|
+
assert "2 | line 2" in msg
|
|
37
|
+
assert "line 3" not in msg
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def test_cat_nonexistent_and_empty_file(tmp_path):
|
|
41
|
+
cmd = diskops.Cat()
|
|
42
|
+
code, msg = cmd.execute([str(tmp_path / "missing.txt")])
|
|
43
|
+
assert code == 1
|
|
44
|
+
assert "not found" in msg
|
|
45
|
+
empty_file = tmp_path / "empty.txt"
|
|
46
|
+
empty_file.write_text("")
|
|
47
|
+
code, msg = cmd.execute([str(empty_file)])
|
|
48
|
+
assert code == 1
|
|
49
|
+
assert "is empty" in msg
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def test_mkdir_standard_and_parents(tmp_path):
|
|
53
|
+
cmd = diskops.MkDir()
|
|
54
|
+
target = tmp_path / "new_folder"
|
|
55
|
+
code, msg = cmd.execute([str(target)])
|
|
56
|
+
assert code == 0
|
|
57
|
+
assert target.is_dir()
|
|
58
|
+
code, msg = cmd.execute([str(target)])
|
|
59
|
+
assert code == 1
|
|
60
|
+
assert "already exists" in msg
|
|
61
|
+
nested = tmp_path / "parent" / "child"
|
|
62
|
+
code, msg = cmd.execute(["-p", str(nested)])
|
|
63
|
+
assert code == 0
|
|
64
|
+
assert nested.is_dir()
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def test_rename_file(tmp_path):
|
|
68
|
+
src = tmp_path / "old.txt"
|
|
69
|
+
src.write_text("data")
|
|
70
|
+
cmd = diskops.Rename()
|
|
71
|
+
code, msg = cmd.execute([str(src), "new.txt"])
|
|
72
|
+
assert code == 0
|
|
73
|
+
assert not src.exists()
|
|
74
|
+
assert (tmp_path / "new.txt").exists()
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def test_copy_file_and_directory(tmp_path):
|
|
78
|
+
src_file = tmp_path / "source.txt"
|
|
79
|
+
src_file.write_text("payload")
|
|
80
|
+
dst_file = tmp_path / "dest.txt"
|
|
81
|
+
cmd = diskops.Copy()
|
|
82
|
+
code, msg = cmd.execute([str(src_file), str(dst_file)])
|
|
83
|
+
assert code == 0
|
|
84
|
+
assert dst_file.read_text() == "payload"
|
|
85
|
+
src_dir = tmp_path / "src_dir"
|
|
86
|
+
src_dir.mkdir()
|
|
87
|
+
(src_dir / "item.txt").write_text("inner")
|
|
88
|
+
dst_dir = tmp_path / "dst_dir"
|
|
89
|
+
code, msg = cmd.execute([str(src_dir), str(dst_dir)])
|
|
90
|
+
assert code == 0
|
|
91
|
+
assert (dst_dir / "item.txt").exists()
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def test_rm_file_and_directory_recursive(tmp_path):
|
|
95
|
+
target_file = tmp_path / "del.txt"
|
|
96
|
+
target_file.write_text("bye")
|
|
97
|
+
cmd = diskops.Rm()
|
|
98
|
+
code, msg = cmd.execute(["-f", str(target_file)])
|
|
99
|
+
assert code == 0
|
|
100
|
+
assert not target_file.exists()
|
|
101
|
+
target_dir = tmp_path / "sub_dir"
|
|
102
|
+
target_dir.mkdir()
|
|
103
|
+
code, msg = cmd.execute(["-f", str(target_dir)])
|
|
104
|
+
assert code == 1
|
|
105
|
+
assert "is a directory" in msg
|
|
106
|
+
code, msg = cmd.execute(["-f", "-r", str(target_dir)])
|
|
107
|
+
assert code == 0
|
|
108
|
+
assert not target_dir.exists()
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def test_rmdir_empty_and_non_empty(tmp_path):
|
|
112
|
+
target_dir = tmp_path / "removable"
|
|
113
|
+
target_dir.mkdir()
|
|
114
|
+
cmd = diskops.RmDir()
|
|
115
|
+
(target_dir / "file.txt").write_text("data")
|
|
116
|
+
code, msg = cmd.execute([str(target_dir)])
|
|
117
|
+
assert code == 1
|
|
118
|
+
assert "not empty" in msg
|
|
119
|
+
code, msg = cmd.execute(["-f", str(target_dir)])
|
|
120
|
+
assert code == 0
|
|
121
|
+
assert not target_dir.exists()
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# tests\test_utils.py
|
|
2
|
+
|
|
3
|
+
from flyshell.builtin import utils
|
|
4
|
+
from flyshell.core import data
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def test_echo_output_and_escape_characters():
|
|
8
|
+
cmd = utils.Echo()
|
|
9
|
+
code, msg = cmd.execute(["Hello", "World"])
|
|
10
|
+
assert code == 0
|
|
11
|
+
assert "Hello World" in msg
|
|
12
|
+
code, msg = cmd.execute([r"Line1\nLine2"])
|
|
13
|
+
assert code == 0
|
|
14
|
+
assert "Line1\nLine2" in msg
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def test_clear_returns_escape_code():
|
|
18
|
+
cmd = utils.Clear()
|
|
19
|
+
code, msg = cmd.execute([])
|
|
20
|
+
assert code == 0
|
|
21
|
+
assert msg == "\033[H\033[2J"
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def test_sleep_validations():
|
|
25
|
+
cmd = utils.Sleep()
|
|
26
|
+
code, msg = cmd.execute(["not_a_number"])
|
|
27
|
+
assert code == 1
|
|
28
|
+
assert "Invalid argument" in msg
|
|
29
|
+
code, msg = cmd.execute([])
|
|
30
|
+
assert code == 1
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def test_history_limit_and_all_args(tmp_path, monkeypatch):
|
|
34
|
+
test_db = tmp_path / "test.db"
|
|
35
|
+
monkeypatch.setattr(
|
|
36
|
+
data,
|
|
37
|
+
"get_history",
|
|
38
|
+
lambda limit=None, filename=test_db: (
|
|
39
|
+
data.get_history.__wrapped__(limit=limit, filename=test_db)
|
|
40
|
+
if hasattr(data.get_history, "__wrapped__")
|
|
41
|
+
else [
|
|
42
|
+
entry
|
|
43
|
+
for entry in (
|
|
44
|
+
lambda conn: [
|
|
45
|
+
{"command": r[0], "timestamp": r[1]}
|
|
46
|
+
for r in conn.execute(
|
|
47
|
+
"SELECT command, timestamp FROM cmd_history ORDER BY id DESC LIMIT ?"
|
|
48
|
+
if limit and limit > 0
|
|
49
|
+
else "SELECT command, timestamp FROM cmd_history ORDER BY id ASC",
|
|
50
|
+
(limit,) if limit and limit > 0 else (),
|
|
51
|
+
).fetchall()
|
|
52
|
+
]
|
|
53
|
+
)(data._get_connection(test_db))
|
|
54
|
+
][::-1] if limit and limit > 0 else [
|
|
55
|
+
{"command": r[0], "timestamp": r[1]}
|
|
56
|
+
for r in data._get_connection(test_db).execute(
|
|
57
|
+
"SELECT command, timestamp FROM cmd_history ORDER BY id ASC"
|
|
58
|
+
).fetchall()
|
|
59
|
+
]
|
|
60
|
+
),
|
|
61
|
+
)
|
|
62
|
+
data.append_history("cmd1", "2026-01-01T00:00:00Z", filename=test_db)
|
|
63
|
+
data.append_history("cmd2", "2026-01-01T00:01:00Z", filename=test_db)
|
|
64
|
+
cmd = utils.History()
|
|
65
|
+
code, msg = cmd.execute(["1"])
|
|
66
|
+
assert code == 0
|
|
67
|
+
assert "cmd2" in msg
|
|
68
|
+
assert "cmd1" not in msg
|
|
69
|
+
code, msg = cmd.execute(["all"])
|
|
70
|
+
assert code == 0
|
|
71
|
+
assert "cmd1" in msg
|
|
72
|
+
assert "cmd2" in msg
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|