pysh-shell 0.1.0__py3-none-any.whl
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.
- pysh/__init__.py +13 -0
- pysh/__main__.py +14 -0
- pysh/cli.py +16 -0
- pysh/shell.py +112 -0
- pysh_shell-0.1.0.dist-info/METADATA +74 -0
- pysh_shell-0.1.0.dist-info/RECORD +9 -0
- pysh_shell-0.1.0.dist-info/WHEEL +4 -0
- pysh_shell-0.1.0.dist-info/entry_points.txt +2 -0
- pysh_shell-0.1.0.dist-info/licenses/LICENSE +11 -0
pysh/__init__.py
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
#
|
|
3
|
+
# Project: PYSH - Python-first interactive shell for Debian and Unix-like systems
|
|
4
|
+
# File: src/pysh/__init__.py
|
|
5
|
+
#
|
|
6
|
+
# Copyright (c) 2026 Siergej Sobolewski
|
|
7
|
+
#
|
|
8
|
+
# Licensed under the GNU General Public License v3.0 or later.
|
|
9
|
+
# See the LICENSE file in the project root for full license text.
|
|
10
|
+
|
|
11
|
+
__version__ = "0.1.0"
|
|
12
|
+
__author__ = "Sergei Sobolewski"
|
|
13
|
+
__all__ = ["main"]
|
pysh/__main__.py
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
#
|
|
3
|
+
# Project: PYSH - Python-first interactive shell for Debian and Unix-like systems
|
|
4
|
+
# File: src/pysh/__main__.py
|
|
5
|
+
#
|
|
6
|
+
# Copyright (c) 2026 Siergej Sobolewski
|
|
7
|
+
#
|
|
8
|
+
# Licensed under the GNU General Public License v3.0 or later.
|
|
9
|
+
# See the LICENSE file in the project root for full license text.
|
|
10
|
+
|
|
11
|
+
from pysh.cli import main
|
|
12
|
+
|
|
13
|
+
if __name__ == "__main__":
|
|
14
|
+
raise SystemExit(main())
|
pysh/cli.py
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
#
|
|
3
|
+
# Project: PYSH - Python-first interactive shell for Debian and Unix-like systems
|
|
4
|
+
# File: src/pysh/cli.py
|
|
5
|
+
#
|
|
6
|
+
# Copyright (c) 2026 Siergej Sobolewski
|
|
7
|
+
#
|
|
8
|
+
# Licensed under the GNU General Public License v3.0 or later.
|
|
9
|
+
# See the LICENSE file in the project root for full license text.
|
|
10
|
+
from pysh.shell import PyShell
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def main() -> int:
|
|
14
|
+
"""Run PySH interactive shell."""
|
|
15
|
+
shell = PyShell()
|
|
16
|
+
return shell.run()
|
pysh/shell.py
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
#
|
|
3
|
+
# Project: PYSH - Python-first interactive shell for Debian and Unix-like systems
|
|
4
|
+
# File: src/pysh/shell.py
|
|
5
|
+
#
|
|
6
|
+
# Copyright (c) 2026 Siergej Sobolewski
|
|
7
|
+
#
|
|
8
|
+
# Licensed under the GNU General Public License v3.0 or later.
|
|
9
|
+
# See the LICENSE file in the project root for full license text.
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
import os
|
|
13
|
+
import shlex
|
|
14
|
+
import subprocess
|
|
15
|
+
from pathlib import Path
|
|
16
|
+
from typing import Any
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class PyShell:
|
|
20
|
+
"""Python-first interactive shell with Unix command fallback."""
|
|
21
|
+
|
|
22
|
+
def __init__(self) -> None:
|
|
23
|
+
self.namespace: dict[str, Any] = {
|
|
24
|
+
"Path": Path,
|
|
25
|
+
"os": os,
|
|
26
|
+
"shlex": shlex,
|
|
27
|
+
"subprocess": subprocess,
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
def run(self) -> int:
|
|
31
|
+
"""Start the interactive shell loop."""
|
|
32
|
+
while True:
|
|
33
|
+
try:
|
|
34
|
+
line = input(self._prompt()).strip()
|
|
35
|
+
except EOFError:
|
|
36
|
+
print()
|
|
37
|
+
return 0
|
|
38
|
+
except KeyboardInterrupt:
|
|
39
|
+
print()
|
|
40
|
+
continue
|
|
41
|
+
|
|
42
|
+
if not line:
|
|
43
|
+
continue
|
|
44
|
+
|
|
45
|
+
if line in {"exit", "quit"}:
|
|
46
|
+
return 0
|
|
47
|
+
|
|
48
|
+
status = self.execute(line)
|
|
49
|
+
if status != 0:
|
|
50
|
+
self.namespace["_status"] = status
|
|
51
|
+
|
|
52
|
+
def execute(self, line: str) -> int:
|
|
53
|
+
"""Execute one shell line."""
|
|
54
|
+
if line.startswith(":"):
|
|
55
|
+
return self._run_python(line[1:].strip())
|
|
56
|
+
|
|
57
|
+
try:
|
|
58
|
+
parts = shlex.split(line)
|
|
59
|
+
except ValueError as exc:
|
|
60
|
+
print(f"pysh: parse error: {exc}")
|
|
61
|
+
return 2
|
|
62
|
+
|
|
63
|
+
if not parts:
|
|
64
|
+
return 0
|
|
65
|
+
|
|
66
|
+
if parts[0] == "cd":
|
|
67
|
+
return self._cd(parts[1:])
|
|
68
|
+
|
|
69
|
+
return self._run_external(line)
|
|
70
|
+
|
|
71
|
+
def _prompt(self) -> str:
|
|
72
|
+
"""Build the interactive prompt."""
|
|
73
|
+
cwd = Path.cwd()
|
|
74
|
+
return f"pysh:{cwd}$ "
|
|
75
|
+
|
|
76
|
+
def _cd(self, args: list[str]) -> int:
|
|
77
|
+
"""Change current working directory."""
|
|
78
|
+
target = args[0] if args else str(Path.home())
|
|
79
|
+
target = os.path.expanduser(target)
|
|
80
|
+
|
|
81
|
+
try:
|
|
82
|
+
os.chdir(target)
|
|
83
|
+
return 0
|
|
84
|
+
except OSError as exc:
|
|
85
|
+
print(f"cd: {exc}")
|
|
86
|
+
return 1
|
|
87
|
+
|
|
88
|
+
def _run_python(self, code: str) -> int:
|
|
89
|
+
"""Run Python code inside a persistent namespace."""
|
|
90
|
+
try:
|
|
91
|
+
result = eval(code, self.namespace)
|
|
92
|
+
if result is not None:
|
|
93
|
+
print(repr(result))
|
|
94
|
+
return 0
|
|
95
|
+
except SyntaxError:
|
|
96
|
+
try:
|
|
97
|
+
exec(code, self.namespace)
|
|
98
|
+
return 0
|
|
99
|
+
except Exception as exc:
|
|
100
|
+
print(f"pysh: {type(exc).__name__}: {exc}")
|
|
101
|
+
return 1
|
|
102
|
+
except Exception as exc:
|
|
103
|
+
print(f"pysh: {type(exc).__name__}: {exc}")
|
|
104
|
+
return 1
|
|
105
|
+
|
|
106
|
+
def _run_external(self, command: str) -> int:
|
|
107
|
+
"""Run an external Unix command."""
|
|
108
|
+
try:
|
|
109
|
+
return subprocess.call(command, shell=True)
|
|
110
|
+
except KeyboardInterrupt:
|
|
111
|
+
print()
|
|
112
|
+
return 130
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: pysh-shell
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Python-first interactive shell for Debian and Unix-like systems
|
|
5
|
+
Author: Siergej Sobolewski
|
|
6
|
+
License-Expression: GPL-3.0-or-later
|
|
7
|
+
License-File: LICENSE
|
|
8
|
+
Keywords: cli,debian,python,shell,terminal
|
|
9
|
+
Classifier: Development Status :: 3 - Alpha
|
|
10
|
+
Classifier: Environment :: Console
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
13
|
+
Classifier: Topic :: System :: Shells
|
|
14
|
+
Classifier: Topic :: Terminals
|
|
15
|
+
Requires-Python: >=3.13
|
|
16
|
+
Description-Content-Type: text/markdown
|
|
17
|
+
|
|
18
|
+
<!-- SPDX-License-Identifier: Apache-2.0
|
|
19
|
+
|
|
20
|
+
Project: PYSH - Python-first interactive shell for Debian and Unix-like systems
|
|
21
|
+
File: README.md
|
|
22
|
+
|
|
23
|
+
Copyright (c) 2026 Siergej Sobolewski
|
|
24
|
+
Licensed under the GNU General Public License v3.0 or later.
|
|
25
|
+
See the LICENSE file in the project root for full license text.
|
|
26
|
+
-->
|
|
27
|
+
|
|
28
|
+
# PYSH
|
|
29
|
+
|
|
30
|
+
## Python-first interactive shell for Debian and Unix-like systems
|
|
31
|
+
|
|
32
|
+
PYSH is a modern, Python-first interactive shell designed for Debian and Unix-like systems. It combines the power of Python with the convenience of a traditional shell, providing users with a seamless command-line experience.
|
|
33
|
+
|
|
34
|
+
## Features
|
|
35
|
+
|
|
36
|
+
## Run locally
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
python3 -m pysh
|
|
40
|
+
````
|
|
41
|
+
|
|
42
|
+
## Development install
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
python3.13 -m venv .venv
|
|
46
|
+
source .venv/bin/activate
|
|
47
|
+
pip install -e ".[dev]"
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Usage
|
|
51
|
+
|
|
52
|
+
Unix command:
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
ls -la
|
|
56
|
+
git status
|
|
57
|
+
cd ~/Code
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Python command:
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
:Path.cwd()
|
|
64
|
+
:x = 10
|
|
65
|
+
:x * 2
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## Build package
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
python -m pip install build twine
|
|
72
|
+
python -m build
|
|
73
|
+
twine check dist/*
|
|
74
|
+
```
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
pysh/__init__.py,sha256=HHC1MIPlScn9NSG4JBTJtjIqVS_Ieraov8QXiZxzcmM,399
|
|
2
|
+
pysh/__main__.py,sha256=WE-qpY-ODHEC00xUKLYoGxI4eEiJ1pdnyydS3sY_KgY,408
|
|
3
|
+
pysh/cli.py,sha256=RAZ9jmyc7582hC8qlBVaBcS2HoL7hAU3IWpWi343Tn8,454
|
|
4
|
+
pysh/shell.py,sha256=Sdtyw69GV9Xj0Y5rLGbYLTfa86oiGeb1uiO2eNNSzbs,3091
|
|
5
|
+
pysh_shell-0.1.0.dist-info/METADATA,sha256=s6wCj9Gw9PtO5ncJVgpP9959q3pxfagCYwwFPvxl0Hs,1567
|
|
6
|
+
pysh_shell-0.1.0.dist-info/WHEEL,sha256=QccIxa26bgl1E6uMy58deGWi-0aeIkkangHcxk2kWfw,87
|
|
7
|
+
pysh_shell-0.1.0.dist-info/entry_points.txt,sha256=L35jA72j1OW4P-07CY5jWrao6ofcrOsSygcjN_-UIEE,39
|
|
8
|
+
pysh_shell-0.1.0.dist-info/licenses/LICENSE,sha256=rOA-PReIlEJRz7noG5rximt8PEirHCHNaADo885tz8A,378
|
|
9
|
+
pysh_shell-0.1.0.dist-info/RECORD,,
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
GNU GENERAL PUBLIC LICENSE
|
|
2
|
+
Version 3, 29 June 2007
|
|
3
|
+
|
|
4
|
+
Copyright (C) 2026 Siergej Sobolewski
|
|
5
|
+
|
|
6
|
+
This program is free software: you can redistribute it and/or modify
|
|
7
|
+
it under the terms of the GNU General Public License as published by
|
|
8
|
+
the Free Software Foundation, either version 3 of the License, or
|
|
9
|
+
(at your option) any later version.
|
|
10
|
+
|
|
11
|
+
See: https://www.gnu.org/licenses/gpl-3.0.txt
|