flyshell 1.0.11__tar.gz → 1.0.12__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.
Files changed (34) hide show
  1. {flyshell-1.0.11/src/flyshell.egg-info → flyshell-1.0.12}/PKG-INFO +1 -1
  2. {flyshell-1.0.11 → flyshell-1.0.12}/src/flyshell/builtin/diskops.py +164 -15
  3. {flyshell-1.0.11 → flyshell-1.0.12}/src/flyshell/constants.py +2 -2
  4. {flyshell-1.0.11 → flyshell-1.0.12}/src/flyshell/core/directory.py +2 -0
  5. {flyshell-1.0.11 → flyshell-1.0.12/src/flyshell.egg-info}/PKG-INFO +1 -1
  6. {flyshell-1.0.11 → flyshell-1.0.12}/LICENSE +0 -0
  7. {flyshell-1.0.11 → flyshell-1.0.12}/README.md +0 -0
  8. {flyshell-1.0.11 → flyshell-1.0.12}/pyproject.toml +0 -0
  9. {flyshell-1.0.11 → flyshell-1.0.12}/setup.cfg +0 -0
  10. {flyshell-1.0.11 → flyshell-1.0.12}/src/flyshell/__init__.py +0 -0
  11. {flyshell-1.0.11 → flyshell-1.0.12}/src/flyshell/abstract/__init__.py +0 -0
  12. {flyshell-1.0.11 → flyshell-1.0.12}/src/flyshell/abstract/base_cmd.py +0 -0
  13. {flyshell-1.0.11 → flyshell-1.0.12}/src/flyshell/abstract/base_plugin.py +0 -0
  14. {flyshell-1.0.11 → flyshell-1.0.12}/src/flyshell/abstract/parent_cmd.py +0 -0
  15. {flyshell-1.0.11 → flyshell-1.0.12}/src/flyshell/builtin/__init__.py +0 -0
  16. {flyshell-1.0.11 → flyshell-1.0.12}/src/flyshell/builtin/fs.py +0 -0
  17. {flyshell-1.0.11 → flyshell-1.0.12}/src/flyshell/builtin/system.py +0 -0
  18. {flyshell-1.0.11 → flyshell-1.0.12}/src/flyshell/builtin/utils.py +0 -0
  19. {flyshell-1.0.11 → flyshell-1.0.12}/src/flyshell/core/__init__.py +0 -0
  20. {flyshell-1.0.11 → flyshell-1.0.12}/src/flyshell/core/auth.py +0 -0
  21. {flyshell-1.0.11 → flyshell-1.0.12}/src/flyshell/core/console.py +0 -0
  22. {flyshell-1.0.11 → flyshell-1.0.12}/src/flyshell/core/data.py +0 -0
  23. {flyshell-1.0.11 → flyshell-1.0.12}/src/flyshell/core/loader.py +0 -0
  24. {flyshell-1.0.11 → flyshell-1.0.12}/src/flyshell/main.py +0 -0
  25. {flyshell-1.0.11 → flyshell-1.0.12}/src/flyshell.egg-info/SOURCES.txt +0 -0
  26. {flyshell-1.0.11 → flyshell-1.0.12}/src/flyshell.egg-info/dependency_links.txt +0 -0
  27. {flyshell-1.0.11 → flyshell-1.0.12}/src/flyshell.egg-info/entry_points.txt +0 -0
  28. {flyshell-1.0.11 → flyshell-1.0.12}/src/flyshell.egg-info/requires.txt +0 -0
  29. {flyshell-1.0.11 → flyshell-1.0.12}/src/flyshell.egg-info/top_level.txt +0 -0
  30. {flyshell-1.0.11 → flyshell-1.0.12}/tests/test_auth.py +0 -0
  31. {flyshell-1.0.11 → flyshell-1.0.12}/tests/test_data.py +0 -0
  32. {flyshell-1.0.11 → flyshell-1.0.12}/tests/test_directory.py +0 -0
  33. {flyshell-1.0.11 → flyshell-1.0.12}/tests/test_loader.py +0 -0
  34. {flyshell-1.0.11 → flyshell-1.0.12}/tests/test_security.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: flyshell
3
- Version: 1.0.11
3
+ Version: 1.0.12
4
4
  Summary: A modular, zero-dependency command-line environment in Python.
5
5
  License: MIT
6
6
  Requires-Python: >=3.10
@@ -73,6 +73,69 @@ class Cat(BaseCmd):
73
73
  return (1, f"\nSystem Error: Failed to read file '{raw_target}' ({e})\n")
74
74
 
75
75
 
76
+ class Copy(BaseCmd):
77
+ name = "cp"
78
+ description = "Copy files or directories to a new destination"
79
+ min_args = 2
80
+ options = "Source, then destination"
81
+ aliases = ["copy"]
82
+
83
+ def execute(self, args):
84
+ force = ("-f" in args) or ("--force" in args)
85
+ flags = {"-f", "--force"}
86
+ path_tokens = [arg for arg in args if arg not in flags]
87
+ if len(path_tokens) < 2:
88
+ return (
89
+ 1,
90
+ "\nCommand Error: 'cp' requires both a source and destination path.\n",
91
+ )
92
+ raw_src = path_tokens[0].strip("\"'")
93
+ raw_dst = path_tokens[1].strip("\"'")
94
+ src_path = Path(raw_src).expanduser().resolve()
95
+ dst_path = Path(raw_dst).expanduser().resolve()
96
+ if not src_path.exists():
97
+ return (1, f"\nSystem Error: Source '{raw_src}' not found.\n")
98
+ if dst_path.exists() and dst_path.is_dir():
99
+ final_dst = dst_path / src_path.name
100
+ else:
101
+ final_dst = dst_path
102
+ if final_dst.exists() and not force:
103
+ try:
104
+ confirm = (
105
+ input(
106
+ f"\nDestination '{final_dst.name}' already exists. Overwrite? [y/n]: "
107
+ )
108
+ .strip()
109
+ .lower()
110
+ )
111
+ except KeyboardInterrupt:
112
+ return (1, "\nCopy cancelled by user.\n")
113
+ if confirm != "y":
114
+ return (0, "\nOperation cancelled. No files were copied.\n")
115
+ try:
116
+ if src_path.is_dir():
117
+ shutil.copytree(src_path, final_dst, dirs_exist_ok=force)
118
+ return (
119
+ 0,
120
+ f"\nSUCCESS! Copied directory '{src_path.name}' -> '{final_dst}'\n",
121
+ )
122
+ else:
123
+ shutil.copy2(src_path, final_dst)
124
+ return (
125
+ 0,
126
+ f"\nSUCCESS! Copied file '{src_path.name}' -> '{final_dst}'\n",
127
+ )
128
+ except PermissionError:
129
+ return (
130
+ 1,
131
+ f"\nSystem Error: Permission denied. Cannot copy to '{final_dst}'\n",
132
+ )
133
+ except shutil.SameFileError:
134
+ return (1, "\nSystem Error: Source and destination are the same.\n")
135
+ except Exception as e:
136
+ return (1, f"\nSystem Error: Failed to copy '{raw_src}' ({e})\n")
137
+
138
+
76
139
  class Dir(BaseCmd):
77
140
  name = "dir"
78
141
  description = "List all files in the current working directory"
@@ -126,6 +189,76 @@ class MkDir(BaseCmd):
126
189
  return (1, f"\nSystem Error: Unable to create directory '{target}' ({e})\n")
127
190
 
128
191
 
192
+ class Move(BaseCmd):
193
+ name = "mv"
194
+ description = "Move or relocate files and directories"
195
+ min_args = 2
196
+ options = "Source, then destination"
197
+ aliases = ["move"]
198
+
199
+ def execute(self, args):
200
+ force = ("-f" in args) or ("--force" in args)
201
+ flags = {"-f", "--force"}
202
+ path_tokens = [arg for arg in args if arg not in flags]
203
+ if len(path_tokens) < 2:
204
+ return (
205
+ 1,
206
+ "\nCommand Error: 'mv' requires both a source and a destination path.\n",
207
+ )
208
+ raw_src = path_tokens[0].strip("\"'")
209
+ raw_dst = path_tokens[1].strip("\"'")
210
+ src_path = Path(raw_src).expanduser().resolve()
211
+ dst_path = Path(raw_dst).expanduser().resolve()
212
+ if not src_path.exists():
213
+ return (1, f"\nSystem Error: Source '{raw_src}' not found.\n")
214
+ if src_path == src_path.parent or str(src_path) == src_path.anchor:
215
+ return (
216
+ 1,
217
+ "\nSecurity Error: Flyshell has blocked moving the root filesystem.\n",
218
+ )
219
+ flyshell_dirs = [
220
+ c.APP_DIR.resolve(),
221
+ c.PACKAGE_ROOT.resolve(),
222
+ c.PROJECT_ROOT.resolve(),
223
+ ]
224
+ for protected in flyshell_dirs:
225
+ if src_path == protected or src_path.is_relative_to(protected):
226
+ return (
227
+ 1,
228
+ "\nSecurity Error: Flyshell has blocked this action.\n"
229
+ f"Source '{raw_src}' contains or belongs to Flyshell system files.\n",
230
+ )
231
+ if dst_path.exists() and dst_path.is_dir():
232
+ final_dst = dst_path / src_path.name
233
+ else:
234
+ final_dst = dst_path
235
+ if final_dst.exists() and not force:
236
+ try:
237
+ confirm = (
238
+ input(
239
+ f"\nDestination '{final_dst.name}' already exists. Overwrite? [y/n]: "
240
+ )
241
+ .strip()
242
+ .lower()
243
+ )
244
+ except KeyboardInterrupt:
245
+ return (1, "\nMove cancelled by user.\n")
246
+ if confirm != "y":
247
+ return (0, "\nOperation cancelled. No files were moved.\n")
248
+ try:
249
+ shutil.move(str(src_path), str(final_dst))
250
+ return (0, f"\nSUCCESS! Moved '{src_path.name}' -> '{final_dst}'\n")
251
+ except PermissionError:
252
+ return (
253
+ 1,
254
+ f"\nSystem Error: Permission denied. Cannot move to '{final_dst}'\n",
255
+ )
256
+ except shutil.SameFileError:
257
+ return (1, "\nSystem Error: Source and destination are the same.\n")
258
+ except Exception as e:
259
+ return (1, f"\nSystem Error: Failed to move '{raw_src}' ({e})\n")
260
+
261
+
129
262
  class Rm(BaseCmd):
130
263
  name = "rm"
131
264
  description = "Remove files from the filesystem"
@@ -156,18 +289,22 @@ class Rm(BaseCmd):
156
289
  ]
157
290
  if c.HOST_OS == "Windows":
158
291
  system_drive = os.environ.get("SystemDrive", "C:")
159
- critical_system_dirs.extend([
160
- Path(f"{system_drive}\\Windows").resolve(),
161
- Path(f"{system_drive}\\Program Files").resolve(),
162
- Path(f"{system_drive}\\Program Files (x86)").resolve(),
163
- ])
292
+ critical_system_dirs.extend(
293
+ [
294
+ Path(f"{system_drive}\\Windows").resolve(),
295
+ Path(f"{system_drive}\\Program Files").resolve(),
296
+ Path(f"{system_drive}\\Program Files (x86)").resolve(),
297
+ ]
298
+ )
164
299
  else:
165
- critical_system_dirs.extend([
166
- Path("/bin").resolve(),
167
- Path("/etc").resolve(),
168
- Path("/usr").resolve(),
169
- Path("/var").resolve(),
170
- ])
300
+ critical_system_dirs.extend(
301
+ [
302
+ Path("/bin").resolve(),
303
+ Path("/etc").resolve(),
304
+ Path("/usr").resolve(),
305
+ Path("/var").resolve(),
306
+ ]
307
+ )
171
308
  if target_path in critical_system_dirs:
172
309
  return (
173
310
  1,
@@ -212,16 +349,28 @@ class Rm(BaseCmd):
212
349
  try:
213
350
  if is_directory:
214
351
  shutil.rmtree(target_path)
215
- return (0, f"\nSUCCESS! Deleted directory '{raw_target}' and all its contents.\n")
352
+ return (
353
+ 0,
354
+ f"\nSUCCESS! Deleted directory '{raw_target}' and all its contents.\n",
355
+ )
216
356
  else:
217
357
  os.remove(target_path)
218
358
  return (0, f"\nSUCCESS! Deleted file '{raw_target}'\n")
219
359
  except PermissionError:
220
- return (1, f"\nSystem Error: Permission denied. Cannot remove '{raw_target}'\n")
360
+ return (
361
+ 1,
362
+ f"\nSystem Error: Permission denied. Cannot remove '{raw_target}'\n",
363
+ )
221
364
  except OSError as e:
222
- return (1, f"\nSystem Error: Unable to remove '{raw_target}' ({e.strerror})\n")
365
+ return (
366
+ 1,
367
+ f"\nSystem Error: Unable to remove '{raw_target}' ({e.strerror})\n",
368
+ )
223
369
  except Exception as e:
224
- return (1, f"\nSystem Error: Unexpected error removing '{raw_target}' ({e})\n")
370
+ return (
371
+ 1,
372
+ f"\nSystem Error: Unexpected error removing '{raw_target}' ({e})\n",
373
+ )
225
374
 
226
375
 
227
376
  class RmDir(BaseCmd):
@@ -7,8 +7,8 @@ import os
7
7
  import platform
8
8
  import time
9
9
 
10
- BUILD = 110
11
- VERSION = "1.0.11"
10
+ BUILD = 111
11
+ VERSION = "1.0.12"
12
12
 
13
13
 
14
14
  def _resolve_app_dir() -> Path:
@@ -53,12 +53,14 @@ INSTALLED_COMMANDS: list[BaseCmd] = [
53
53
  system.Cd(),
54
54
  Cmds(),
55
55
  utils.Clear(),
56
+ diskops.Copy(),
56
57
  diskops.Dir(),
57
58
  fs.Fs(),
58
59
  utils.History(),
59
60
  utils.Kill(),
60
61
  auth.Lock(),
61
62
  diskops.MkDir(),
63
+ diskops.Move(),
62
64
  system.OpenFile(),
63
65
  utils.Reboot(),
64
66
  diskops.Rm(),
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: flyshell
3
- Version: 1.0.11
3
+ Version: 1.0.12
4
4
  Summary: A modular, zero-dependency command-line environment in Python.
5
5
  License: MIT
6
6
  Requires-Python: >=3.10
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes