flyshell 1.0.10__tar.gz → 1.0.11__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.10/src/flyshell.egg-info → flyshell-1.0.11}/PKG-INFO +1 -1
  2. {flyshell-1.0.10 → flyshell-1.0.11}/src/flyshell/builtin/diskops.py +158 -8
  3. {flyshell-1.0.10 → flyshell-1.0.11}/src/flyshell/constants.py +2 -2
  4. {flyshell-1.0.10 → flyshell-1.0.11}/src/flyshell/core/directory.py +2 -0
  5. {flyshell-1.0.10 → flyshell-1.0.11}/src/flyshell/main.py +12 -7
  6. {flyshell-1.0.10 → flyshell-1.0.11/src/flyshell.egg-info}/PKG-INFO +1 -1
  7. {flyshell-1.0.10 → flyshell-1.0.11}/LICENSE +0 -0
  8. {flyshell-1.0.10 → flyshell-1.0.11}/README.md +0 -0
  9. {flyshell-1.0.10 → flyshell-1.0.11}/pyproject.toml +0 -0
  10. {flyshell-1.0.10 → flyshell-1.0.11}/setup.cfg +0 -0
  11. {flyshell-1.0.10 → flyshell-1.0.11}/src/flyshell/__init__.py +0 -0
  12. {flyshell-1.0.10 → flyshell-1.0.11}/src/flyshell/abstract/__init__.py +0 -0
  13. {flyshell-1.0.10 → flyshell-1.0.11}/src/flyshell/abstract/base_cmd.py +0 -0
  14. {flyshell-1.0.10 → flyshell-1.0.11}/src/flyshell/abstract/base_plugin.py +0 -0
  15. {flyshell-1.0.10 → flyshell-1.0.11}/src/flyshell/abstract/parent_cmd.py +0 -0
  16. {flyshell-1.0.10 → flyshell-1.0.11}/src/flyshell/builtin/__init__.py +0 -0
  17. {flyshell-1.0.10 → flyshell-1.0.11}/src/flyshell/builtin/fs.py +0 -0
  18. {flyshell-1.0.10 → flyshell-1.0.11}/src/flyshell/builtin/system.py +0 -0
  19. {flyshell-1.0.10 → flyshell-1.0.11}/src/flyshell/builtin/utils.py +0 -0
  20. {flyshell-1.0.10 → flyshell-1.0.11}/src/flyshell/core/__init__.py +0 -0
  21. {flyshell-1.0.10 → flyshell-1.0.11}/src/flyshell/core/auth.py +0 -0
  22. {flyshell-1.0.10 → flyshell-1.0.11}/src/flyshell/core/console.py +0 -0
  23. {flyshell-1.0.10 → flyshell-1.0.11}/src/flyshell/core/data.py +0 -0
  24. {flyshell-1.0.10 → flyshell-1.0.11}/src/flyshell/core/loader.py +0 -0
  25. {flyshell-1.0.10 → flyshell-1.0.11}/src/flyshell.egg-info/SOURCES.txt +0 -0
  26. {flyshell-1.0.10 → flyshell-1.0.11}/src/flyshell.egg-info/dependency_links.txt +0 -0
  27. {flyshell-1.0.10 → flyshell-1.0.11}/src/flyshell.egg-info/entry_points.txt +0 -0
  28. {flyshell-1.0.10 → flyshell-1.0.11}/src/flyshell.egg-info/requires.txt +0 -0
  29. {flyshell-1.0.10 → flyshell-1.0.11}/src/flyshell.egg-info/top_level.txt +0 -0
  30. {flyshell-1.0.10 → flyshell-1.0.11}/tests/test_auth.py +0 -0
  31. {flyshell-1.0.10 → flyshell-1.0.11}/tests/test_data.py +0 -0
  32. {flyshell-1.0.10 → flyshell-1.0.11}/tests/test_directory.py +0 -0
  33. {flyshell-1.0.10 → flyshell-1.0.11}/tests/test_loader.py +0 -0
  34. {flyshell-1.0.10 → flyshell-1.0.11}/tests/test_security.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: flyshell
3
- Version: 1.0.10
3
+ Version: 1.0.11
4
4
  Summary: A modular, zero-dependency command-line environment in Python.
5
5
  License: MIT
6
6
  Requires-Python: >=3.10
@@ -32,7 +32,10 @@ class Cat(BaseCmd):
32
32
  skip_next = True
33
33
  continue
34
34
  else:
35
- return (1, f"\nCommand Error: '{token}' requires a positive integer limit.\n")
35
+ return (
36
+ 1,
37
+ f"\nCommand Error: '{token}' requires a positive integer limit.\n",
38
+ )
36
39
  filtered_args.append(token)
37
40
  if not filtered_args:
38
41
  return (1, "\nCommand Error: Target file not specified.\n")
@@ -62,7 +65,10 @@ class Cat(BaseCmd):
62
65
  output_lines.append(f"\nEnd of '{target_path.name}'\n")
63
66
  return (0, "\n".join(output_lines))
64
67
  except PermissionError:
65
- return (1, f"\nSystem Error: Permission denied. Cannot read '{raw_target}'\n")
68
+ return (
69
+ 1,
70
+ f"\nSystem Error: Permission denied. Cannot read '{raw_target}'\n",
71
+ )
66
72
  except Exception as e:
67
73
  return (1, f"\nSystem Error: Failed to read file '{raw_target}' ({e})\n")
68
74
 
@@ -120,18 +126,24 @@ class MkDir(BaseCmd):
120
126
  return (1, f"\nSystem Error: Unable to create directory '{target}' ({e})\n")
121
127
 
122
128
 
123
- class RmDir(BaseCmd):
124
- name = "rmdir"
125
- description = "Remove the specified directory"
129
+ class Rm(BaseCmd):
130
+ name = "rm"
131
+ description = "Remove files from the filesystem"
126
132
  min_args = 1
127
- options = "Target directory"
128
- aliases = []
133
+ options = "Target file"
134
+ aliases = ["del"]
129
135
 
130
136
  def execute(self, args):
131
137
  force = ("-f" in args) or ("--force" in args)
132
- path_tokens = [arg for arg in args if arg not in ("-f", "--force")]
138
+ recursive = ("-r" in args) or ("--recursive" in args)
139
+ flags = {"-f", "--force", "-r", "--recursive"}
140
+ path_tokens = [arg for arg in args if arg not in flags]
141
+ if not path_tokens:
142
+ return (1, "\nCommand Error: No target file or directory specified.\n")
133
143
  raw_target = " ".join(path_tokens).strip("\"'")
134
144
  target_path = Path(raw_target).expanduser().resolve()
145
+ if not target_path.exists():
146
+ return (1, f"\nSystem Error: Target '{raw_target}' not found.\n")
135
147
  if target_path == target_path.parent or str(target_path) == target_path.anchor:
136
148
  return (
137
149
  1,
@@ -173,6 +185,102 @@ class RmDir(BaseCmd):
173
185
  c.PACKAGE_ROOT.resolve(),
174
186
  c.PROJECT_ROOT.resolve(),
175
187
  ]
188
+ for protected in flyshell_dirs:
189
+ if target_path == protected or target_path.is_relative_to(protected):
190
+ return (
191
+ 1,
192
+ "\nSecurity Error: Flyshell has blocked this action.\n"
193
+ f"Target '{raw_target}' contains or belongs to Flyshell system files.\n"
194
+ "If you wish to delete Flyshell, use the host.\n",
195
+ )
196
+ is_directory = target_path.is_dir()
197
+ if is_directory and not recursive:
198
+ return (
199
+ 1,
200
+ f"\nCommand Error: '{raw_target}' is a directory.\n"
201
+ "Use '-r' or '--recursive' to remove directories.\n",
202
+ )
203
+ if not force:
204
+ target_type = "directory and all its contents" if is_directory else "file"
205
+ prompt_msg = f"\nAre you sure you want to permanently delete {target_type} '{raw_target}'? [y/n]: "
206
+ try:
207
+ confirm = input(prompt_msg).strip().lower()
208
+ except (KeyboardInterrupt, EOFError):
209
+ return (1, "\nDeletion cancelled by user.\n")
210
+ if confirm != "y":
211
+ return (0, "\nOperation cancelled. No files were deleted.\n")
212
+ try:
213
+ if is_directory:
214
+ shutil.rmtree(target_path)
215
+ return (0, f"\nSUCCESS! Deleted directory '{raw_target}' and all its contents.\n")
216
+ else:
217
+ os.remove(target_path)
218
+ return (0, f"\nSUCCESS! Deleted file '{raw_target}'\n")
219
+ except PermissionError:
220
+ return (1, f"\nSystem Error: Permission denied. Cannot remove '{raw_target}'\n")
221
+ except OSError as e:
222
+ return (1, f"\nSystem Error: Unable to remove '{raw_target}' ({e.strerror})\n")
223
+ except Exception as e:
224
+ return (1, f"\nSystem Error: Unexpected error removing '{raw_target}' ({e})\n")
225
+
226
+
227
+ class RmDir(BaseCmd):
228
+ name = "rmdir"
229
+ description = "Remove the specified directory"
230
+ min_args = 1
231
+ options = "Target directory"
232
+ aliases = []
233
+
234
+ def execute(self, args):
235
+ force = ("-f" in args) or ("--force" in args)
236
+ path_tokens = [arg for arg in args if arg not in ("-f", "--force")]
237
+ raw_target = " ".join(path_tokens).strip("\"'")
238
+ target_path = Path(raw_target).expanduser().resolve()
239
+ if target_path == target_path.parent or str(target_path) == target_path.anchor:
240
+ return (
241
+ 1,
242
+ "\nSecurity Error: Flyshell has blocked this action.\n"
243
+ "You cannot delete the root filesystem directory.\n",
244
+ )
245
+ critical_system_dirs = [
246
+ Path.home().parent.resolve(),
247
+ Path.home().resolve(),
248
+ ]
249
+ if c.HOST_OS == "Windows":
250
+ system_drive = os.environ.get("SystemDrive", "C:")
251
+ critical_system_dirs.extend(
252
+ [
253
+ Path(f"{system_drive}\\Windows").resolve(),
254
+ Path(f"{system_drive}\\Program Files").resolve(),
255
+ Path(f"{system_drive}\\Program Files (x86)").resolve(),
256
+ ]
257
+ )
258
+ else:
259
+ critical_system_dirs.extend(
260
+ [
261
+ Path("/bin").resolve(),
262
+ Path("/etc").resolve(),
263
+ Path("/usr").resolve(),
264
+ Path("/var").resolve(),
265
+ ]
266
+ )
267
+ if target_path in critical_system_dirs:
268
+ return (
269
+ 1,
270
+ "\nSecurity Error: Flyshell has blocked this action.\n"
271
+ f"Target '{raw_target}' is a protected operating system directory.\n",
272
+ )
273
+ if target_path == Path(os.getcwd()).resolve():
274
+ return (
275
+ 1,
276
+ "\nSystem Error: Cannot remove current working directory.\n"
277
+ "Switch to a different directory using 'cd' first.\n",
278
+ )
279
+ flyshell_dirs = [
280
+ c.APP_DIR.resolve(),
281
+ c.PACKAGE_ROOT.resolve(),
282
+ c.PROJECT_ROOT.resolve(),
283
+ ]
176
284
  for protected in flyshell_dirs:
177
285
  if target_path == protected or target_path.is_relative_to(protected):
178
286
  return (
@@ -209,3 +317,45 @@ class RmDir(BaseCmd):
209
317
  1,
210
318
  f"\nSystem Error: Unexpected error removing '{raw_target}' ({e})\n",
211
319
  )
320
+
321
+
322
+ class Touch(BaseCmd):
323
+ name = "touch"
324
+ description = "Create a new empty file or update timestamps of an existing file"
325
+ min_args = 1
326
+ options = "Target file"
327
+ aliases = []
328
+
329
+ def execute(self, args):
330
+ raw_target = " ".join(args).strip("\"'")
331
+ target_path = Path(raw_target).expanduser().resolve()
332
+ if target_path.is_dir():
333
+ return (
334
+ 1,
335
+ f"\nCommand Error: '{raw_target}' is a directory, not a file.\n",
336
+ )
337
+ if not target_path.parent.exists():
338
+ return (
339
+ 1,
340
+ f"\nSystem Error: Cannot create file '{raw_target}'. Parent directory does not exist.\n",
341
+ )
342
+ try:
343
+ if target_path.exists():
344
+ target_path.touch()
345
+ return (
346
+ 0,
347
+ f"\nSUCCESS! Updated timestamp for existing file '{raw_target}'\n",
348
+ )
349
+ else:
350
+ target_path.touch(exist_ok=False)
351
+ return (0, f"\nSUCCESS! Created file '{raw_target}'\n")
352
+ except PermissionError:
353
+ return (
354
+ 1,
355
+ f"\nSystem Error: Permission denied. Cannot access '{raw_target}'.\n",
356
+ )
357
+ except Exception as e:
358
+ return (
359
+ 1,
360
+ f"\nSystem Error: Failed to touch file '{raw_target}' ({e})\n",
361
+ )
@@ -7,8 +7,8 @@ import os
7
7
  import platform
8
8
  import time
9
9
 
10
- BUILD = 109
11
- VERSION = "1.0.10"
10
+ BUILD = 110
11
+ VERSION = "1.0.11"
12
12
 
13
13
 
14
14
  def _resolve_app_dir() -> Path:
@@ -61,9 +61,11 @@ INSTALLED_COMMANDS: list[BaseCmd] = [
61
61
  diskops.MkDir(),
62
62
  system.OpenFile(),
63
63
  utils.Reboot(),
64
+ diskops.Rm(),
64
65
  diskops.RmDir(),
65
66
  utils.Sleep(),
66
67
  system.SysExe(),
68
+ diskops.Touch(),
67
69
  ]
68
70
  COMMAND_REGISTRY: dict[str, BaseCmd] = {}
69
71
  for cmd_obj in INSTALLED_COMMANDS:
@@ -1,20 +1,24 @@
1
1
  # src\flyshell\main.py
2
2
 
3
- from flyshell import constants as c
4
-
5
3
  from pathlib import Path
6
4
  import importlib.util
7
5
  import os
8
6
  import sys
9
7
 
10
- if str(c.SRC_DIR) not in sys.path:
11
- sys.path.insert(0, str(c.SRC_DIR))
12
-
13
8
 
14
9
  def boot_check():
15
10
  print("\nFlyshell will now check that your modules exist.")
16
11
  present = []
17
12
  missing = []
13
+ try:
14
+ from flyshell import constants as c
15
+
16
+ if str(c.SRC_DIR) not in sys.path:
17
+ sys.path.insert(0, str(c.SRC_DIR))
18
+ except ImportError:
19
+ print(
20
+ "\nCRITICAL BOOT ERROR: Failed to initialise system due to corrupted or missing files.\n"
21
+ )
18
22
  for obj in c.REQUIRED_COMPONENTS:
19
23
  path = Path(c.PACKAGE_ROOT / obj)
20
24
  if path.exists():
@@ -58,11 +62,12 @@ def boot_check():
58
62
 
59
63
  def main():
60
64
  os.system("")
61
- print(c.CLEAR_SCREEN, end="")
65
+ print("\033[H\033[2J", end="")
62
66
  print("\nLaunch process initiated. Flyshell is checking it is able to launch...")
63
67
  try:
64
68
  if boot_check():
65
- from flyshell.core import auth, console, data, loader
69
+ from flyshell import constants as c
70
+ from flyshell.core import auth, console, loader
66
71
 
67
72
  if c.HOST_OS in ["Windows", "Darwin", "Linux"]:
68
73
  if sys.version_info < c.SUPPORTED_PYTHON:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: flyshell
3
- Version: 1.0.10
3
+ Version: 1.0.11
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