python-tty 0.1.2rc2__tar.gz → 0.1.5__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.
- python_tty-0.1.5/.github/workflows/python-publish.yml +115 -0
- python_tty-0.1.5/.gitignore +317 -0
- {python_tty-0.1.2rc2/src/python_tty.egg-info → python_tty-0.1.5}/PKG-INFO +5 -1
- python_tty-0.1.5/demos/file_manager/__init__.py +12 -0
- python_tty-0.1.5/demos/file_manager/commands/__init__.py +188 -0
- python_tty-0.1.5/demos/file_manager/commands/root_commands.py +51 -0
- python_tty-0.1.5/demos/file_manager/consoles/__init__.py +75 -0
- python_tty-0.1.5/demos/file_manager/consoles/root.py +31 -0
- python_tty-0.1.5/demos/file_manager/core/__init__.py +0 -0
- python_tty-0.1.5/demos/file_manager/core/file_manager.py +92 -0
- python_tty-0.1.5/demos/file_manager/exceptions/__init__.py +0 -0
- python_tty-0.1.5/demos/file_manager/main.py +4 -0
- python_tty-0.1.5/demos/file_manager/setup.py +14 -0
- python_tty-0.1.5/demos/file_manager/utils/__init__.py +0 -0
- python_tty-0.1.5/demos/file_manager/utils/table.py +124 -0
- python_tty-0.1.5/docs/LOG.md +351 -0
- python_tty-0.1.5/docs/context.md +2995 -0
- python_tty-0.1.5/pyproject.toml +5 -0
- python_tty-0.1.2rc2/src/python_tty.egg-info/requires.txt → python_tty-0.1.5/requirements.txt +2 -0
- {python_tty-0.1.2rc2 → python_tty-0.1.5}/setup.py +6 -1
- python_tty-0.1.5/src/python_tty/__init__.py +25 -0
- python_tty-0.1.5/src/python_tty/audit/__init__.py +7 -0
- python_tty-0.1.5/src/python_tty/audit/sink.py +141 -0
- {python_tty-0.1.2rc2/src/python_tty/utils → python_tty-0.1.5/src/python_tty/audit}/ui_logger.py +3 -4
- {python_tty-0.1.2rc2 → python_tty-0.1.5}/src/python_tty/commands/examples/root_commands.py +2 -3
- {python_tty-0.1.2rc2 → python_tty-0.1.5}/src/python_tty/commands/mixins.py +3 -4
- python_tty-0.1.5/src/python_tty/config/__init__.py +16 -0
- python_tty-0.1.5/src/python_tty/config/config.py +92 -0
- {python_tty-0.1.2rc2 → python_tty-0.1.5}/src/python_tty/console_factory.py +52 -3
- {python_tty-0.1.2rc2 → python_tty-0.1.5}/src/python_tty/consoles/core.py +5 -5
- {python_tty-0.1.2rc2 → python_tty-0.1.5}/src/python_tty/consoles/manager.py +5 -5
- {python_tty-0.1.2rc2 → python_tty-0.1.5}/src/python_tty/consoles/registry.py +33 -0
- python_tty-0.1.5/src/python_tty/exceptions/console_exception.py +12 -0
- {python_tty-0.1.2rc2 → python_tty-0.1.5}/src/python_tty/executor/executor.py +115 -16
- python_tty-0.1.5/src/python_tty/frontends/__init__.py +0 -0
- python_tty-0.1.5/src/python_tty/frontends/rpc/__init__.py +0 -0
- python_tty-0.1.5/src/python_tty/frontends/web/__init__.py +0 -0
- python_tty-0.1.5/src/python_tty/meta/__init__.py +96 -0
- python_tty-0.1.5/src/python_tty/runtime/__init__.py +29 -0
- python_tty-0.1.5/src/python_tty/runtime/events.py +147 -0
- python_tty-0.1.5/src/python_tty/runtime/provider.py +62 -0
- python_tty-0.1.2rc2/src/python_tty/ui/output.py → python_tty-0.1.5/src/python_tty/runtime/router.py +53 -11
- {python_tty-0.1.2rc2 → python_tty-0.1.5}/src/python_tty/utils/__init__.py +1 -3
- {python_tty-0.1.2rc2 → python_tty-0.1.5/src/python_tty.egg-info}/PKG-INFO +5 -1
- {python_tty-0.1.2rc2 → python_tty-0.1.5}/src/python_tty.egg-info/SOURCES.txt +30 -4
- python_tty-0.1.5/src/python_tty.egg-info/requires.txt +6 -0
- python_tty-0.1.5/tests/__init__.py +0 -0
- python_tty-0.1.2rc2/pyproject.toml +0 -3
- python_tty-0.1.2rc2/src/python_tty/__init__.py +0 -15
- python_tty-0.1.2rc2/src/python_tty/config/__init__.py +0 -9
- python_tty-0.1.2rc2/src/python_tty/config/config.py +0 -35
- python_tty-0.1.2rc2/src/python_tty/ui/__init__.py +0 -13
- python_tty-0.1.2rc2/src/python_tty/ui/events.py +0 -55
- {python_tty-0.1.2rc2 → python_tty-0.1.5}/LICENSE +0 -0
- {python_tty-0.1.2rc2 → python_tty-0.1.5}/MANIFEST.in +0 -0
- {python_tty-0.1.2rc2 → python_tty-0.1.5}/NOTICE +0 -0
- {python_tty-0.1.2rc2 → python_tty-0.1.5}/README.md +0 -0
- {python_tty-0.1.2rc2 → python_tty-0.1.5}/README_zh.md +0 -0
- {python_tty-0.1.2rc2/src/python_tty/frontends → python_tty-0.1.5/demos}/__init__.py +0 -0
- {python_tty-0.1.2rc2/src/python_tty/meta → python_tty-0.1.5/demos/chat_room}/__init__.py +0 -0
- {python_tty-0.1.2rc2/src/python_tty → python_tty-0.1.5/demos/file_manager}/exceptions/console_exception.py +0 -0
- {python_tty-0.1.2rc2 → python_tty-0.1.5}/setup.cfg +0 -0
- {python_tty-0.1.2rc2 → python_tty-0.1.5}/src/python_tty/commands/__init__.py +0 -0
- {python_tty-0.1.2rc2 → python_tty-0.1.5}/src/python_tty/commands/core.py +0 -0
- {python_tty-0.1.2rc2 → python_tty-0.1.5}/src/python_tty/commands/decorators.py +0 -0
- {python_tty-0.1.2rc2 → python_tty-0.1.5}/src/python_tty/commands/examples/__init__.py +0 -0
- {python_tty-0.1.2rc2 → python_tty-0.1.5}/src/python_tty/commands/examples/sub_commands.py +0 -0
- {python_tty-0.1.2rc2 → python_tty-0.1.5}/src/python_tty/commands/general.py +0 -0
- {python_tty-0.1.2rc2 → python_tty-0.1.5}/src/python_tty/commands/registry.py +0 -0
- {python_tty-0.1.2rc2 → python_tty-0.1.5}/src/python_tty/consoles/__init__.py +0 -0
- {python_tty-0.1.2rc2 → python_tty-0.1.5}/src/python_tty/consoles/decorators.py +0 -0
- {python_tty-0.1.2rc2 → python_tty-0.1.5}/src/python_tty/consoles/examples/__init__.py +0 -0
- {python_tty-0.1.2rc2 → python_tty-0.1.5}/src/python_tty/consoles/examples/root_console.py +0 -0
- {python_tty-0.1.2rc2 → python_tty-0.1.5}/src/python_tty/consoles/examples/sub_console.py +0 -0
- {python_tty-0.1.2rc2 → python_tty-0.1.5}/src/python_tty/consoles/loader.py +0 -0
- {python_tty-0.1.2rc2 → python_tty-0.1.5}/src/python_tty/exceptions/__init__.py +0 -0
- {python_tty-0.1.2rc2 → python_tty-0.1.5}/src/python_tty/executor/__init__.py +0 -0
- {python_tty-0.1.2rc2 → python_tty-0.1.5}/src/python_tty/executor/models.py +0 -0
- {python_tty-0.1.2rc2 → python_tty-0.1.5}/src/python_tty/utils/table.py +0 -0
- {python_tty-0.1.2rc2 → python_tty-0.1.5}/src/python_tty/utils/tokenize.py +0 -0
- {python_tty-0.1.2rc2 → python_tty-0.1.5}/src/python_tty.egg-info/dependency_links.txt +0 -0
- {python_tty-0.1.2rc2 → python_tty-0.1.5}/src/python_tty.egg-info/top_level.txt +0 -0
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
name: Build & Publish
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- "v*"
|
|
7
|
+
|
|
8
|
+
# workflow 级最小权限;发布 job 再单独提升 id-token
|
|
9
|
+
permissions:
|
|
10
|
+
contents: read
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
build:
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
outputs:
|
|
16
|
+
is_prerelease: ${{ steps.tag.outputs.is_prerelease }}
|
|
17
|
+
steps:
|
|
18
|
+
- uses: actions/checkout@v4
|
|
19
|
+
with:
|
|
20
|
+
fetch-depth: 0
|
|
21
|
+
|
|
22
|
+
- uses: actions/setup-python@v5
|
|
23
|
+
with:
|
|
24
|
+
python-version: "3.11"
|
|
25
|
+
|
|
26
|
+
- name: Upgrade packaging tools
|
|
27
|
+
run: |
|
|
28
|
+
python -m pip install -U pip setuptools wheel
|
|
29
|
+
|
|
30
|
+
- id: tag
|
|
31
|
+
name: Classify tag
|
|
32
|
+
shell: bash
|
|
33
|
+
run: |
|
|
34
|
+
set -euo pipefail
|
|
35
|
+
TAG="${GITHUB_REF_NAME}"
|
|
36
|
+
# 仅基于 tag 名判断(不含 refs/tags 前缀)
|
|
37
|
+
# 允许:
|
|
38
|
+
# vX.Y.Z
|
|
39
|
+
# vX.Y.ZaN / vX.Y.ZbN / vX.Y.ZrcN
|
|
40
|
+
# vX.Y.Z.devN 或 vX.Y.ZdevN(两种都兼容)
|
|
41
|
+
if [[ "$TAG" =~ ^v[0-9]+\.[0-9]+\.[0-9]+((a|b|rc)[0-9]+|(\.dev|dev)[0-9]+)$ ]]; then
|
|
42
|
+
echo "is_prerelease=true" >> "$GITHUB_OUTPUT"
|
|
43
|
+
else
|
|
44
|
+
echo "is_prerelease=false" >> "$GITHUB_OUTPUT"
|
|
45
|
+
fi
|
|
46
|
+
|
|
47
|
+
- name: Build dists
|
|
48
|
+
run: |
|
|
49
|
+
python -m pip install -U build
|
|
50
|
+
python -m build
|
|
51
|
+
- name: Verify version matches tag
|
|
52
|
+
shell: bash
|
|
53
|
+
run: |
|
|
54
|
+
set -euo pipefail
|
|
55
|
+
TAG_VERSION="${GITHUB_REF_NAME#v}"
|
|
56
|
+
|
|
57
|
+
python -m pip install -U pip
|
|
58
|
+
python -m pip install dist/*.whl
|
|
59
|
+
|
|
60
|
+
PKG_VERSION="$(python -c "import importlib.metadata as m; print(m.version('python-tty'))")"
|
|
61
|
+
|
|
62
|
+
echo "tag: $TAG_VERSION"
|
|
63
|
+
echo "pkg: $PKG_VERSION"
|
|
64
|
+
|
|
65
|
+
if [ "$TAG_VERSION" != "$PKG_VERSION" ]; then
|
|
66
|
+
echo "ERROR: Tag version ($TAG_VERSION) != package version ($PKG_VERSION)"
|
|
67
|
+
exit 1
|
|
68
|
+
fi
|
|
69
|
+
|
|
70
|
+
- name: Upload dist artifact
|
|
71
|
+
uses: actions/upload-artifact@v4
|
|
72
|
+
with:
|
|
73
|
+
name: dist
|
|
74
|
+
path: dist/*
|
|
75
|
+
|
|
76
|
+
publish_testpypi:
|
|
77
|
+
needs: build
|
|
78
|
+
if: needs.build.outputs.is_prerelease == 'true'
|
|
79
|
+
runs-on: ubuntu-latest
|
|
80
|
+
environment:
|
|
81
|
+
name: testpypi
|
|
82
|
+
permissions:
|
|
83
|
+
id-token: write
|
|
84
|
+
contents: read
|
|
85
|
+
steps:
|
|
86
|
+
- uses: actions/download-artifact@v4
|
|
87
|
+
with:
|
|
88
|
+
name: dist
|
|
89
|
+
path: dist
|
|
90
|
+
|
|
91
|
+
- name: Publish to TestPyPI (Trusted Publishing)
|
|
92
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
93
|
+
with:
|
|
94
|
+
repository-url: https://test.pypi.org/legacy/
|
|
95
|
+
skip-existing: true
|
|
96
|
+
verbose: true
|
|
97
|
+
|
|
98
|
+
publish_pypi:
|
|
99
|
+
needs: build
|
|
100
|
+
if: needs.build.outputs.is_prerelease != 'true'
|
|
101
|
+
runs-on: ubuntu-latest
|
|
102
|
+
environment:
|
|
103
|
+
name: pypi
|
|
104
|
+
url: https://pypi.org/p/python-tty
|
|
105
|
+
permissions:
|
|
106
|
+
id-token: write
|
|
107
|
+
contents: read
|
|
108
|
+
steps:
|
|
109
|
+
- uses: actions/download-artifact@v4
|
|
110
|
+
with:
|
|
111
|
+
name: dist
|
|
112
|
+
path: dist
|
|
113
|
+
|
|
114
|
+
- name: Publish to PyPI (Trusted Publishing)
|
|
115
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,317 @@
|
|
|
1
|
+
# Byte-compiled / optimized / DLL files
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[codz]
|
|
4
|
+
*$py.class
|
|
5
|
+
|
|
6
|
+
# C extensions
|
|
7
|
+
*.so
|
|
8
|
+
|
|
9
|
+
# Distribution / packaging
|
|
10
|
+
.Python
|
|
11
|
+
build/
|
|
12
|
+
develop-eggs/
|
|
13
|
+
dist/
|
|
14
|
+
downloads/
|
|
15
|
+
eggs/
|
|
16
|
+
.eggs/
|
|
17
|
+
lib/
|
|
18
|
+
lib64/
|
|
19
|
+
parts/
|
|
20
|
+
sdist/
|
|
21
|
+
var/
|
|
22
|
+
wheels/
|
|
23
|
+
share/python-wheels/
|
|
24
|
+
*.egg-info/
|
|
25
|
+
.installed.cfg
|
|
26
|
+
*.egg
|
|
27
|
+
MANIFEST
|
|
28
|
+
virEnv/
|
|
29
|
+
|
|
30
|
+
# PyInstaller
|
|
31
|
+
# Usually these files are written by a python script from a template
|
|
32
|
+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
|
33
|
+
*.manifest
|
|
34
|
+
*.spec
|
|
35
|
+
|
|
36
|
+
# Installer logs
|
|
37
|
+
pip-log.txt
|
|
38
|
+
pip-delete-this-directory.txt
|
|
39
|
+
|
|
40
|
+
# Unit test / coverage reports
|
|
41
|
+
htmlcov/
|
|
42
|
+
.tox/
|
|
43
|
+
.nox/
|
|
44
|
+
.coverage
|
|
45
|
+
.coverage.*
|
|
46
|
+
.cache
|
|
47
|
+
nosetests.xml
|
|
48
|
+
coverage.xml
|
|
49
|
+
*.cover
|
|
50
|
+
*.py.cover
|
|
51
|
+
.hypothesis/
|
|
52
|
+
.pytest_cache/
|
|
53
|
+
cover/
|
|
54
|
+
|
|
55
|
+
# Translations
|
|
56
|
+
*.mo
|
|
57
|
+
*.pot
|
|
58
|
+
|
|
59
|
+
# Django stuff:
|
|
60
|
+
*.log
|
|
61
|
+
local_settings.py
|
|
62
|
+
db.sqlite3
|
|
63
|
+
db.sqlite3-journal
|
|
64
|
+
|
|
65
|
+
# Flask stuff:
|
|
66
|
+
instance/
|
|
67
|
+
.webassets-cache
|
|
68
|
+
|
|
69
|
+
# Scrapy stuff:
|
|
70
|
+
.scrapy
|
|
71
|
+
|
|
72
|
+
# Sphinx documentation
|
|
73
|
+
docs/_build/
|
|
74
|
+
|
|
75
|
+
# PyBuilder
|
|
76
|
+
.pybuilder/
|
|
77
|
+
target/
|
|
78
|
+
|
|
79
|
+
# Jupyter Notebook
|
|
80
|
+
.ipynb_checkpoints
|
|
81
|
+
|
|
82
|
+
# IPython
|
|
83
|
+
profile_default/
|
|
84
|
+
ipython_config.py
|
|
85
|
+
|
|
86
|
+
# pyenv
|
|
87
|
+
# For a library or package, you might want to ignore these files since the code is
|
|
88
|
+
# intended to run in multiple environments; otherwise, check them in:
|
|
89
|
+
# .python-version
|
|
90
|
+
|
|
91
|
+
# pipenv
|
|
92
|
+
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
|
93
|
+
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
|
94
|
+
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
|
95
|
+
# install all needed dependencies.
|
|
96
|
+
# Pipfile.lock
|
|
97
|
+
|
|
98
|
+
# UV
|
|
99
|
+
# Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
|
|
100
|
+
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
|
101
|
+
# commonly ignored for libraries.
|
|
102
|
+
# uv.lock
|
|
103
|
+
|
|
104
|
+
# poetry
|
|
105
|
+
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
|
106
|
+
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
|
107
|
+
# commonly ignored for libraries.
|
|
108
|
+
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
|
109
|
+
# poetry.lock
|
|
110
|
+
# poetry.toml
|
|
111
|
+
|
|
112
|
+
# pdm
|
|
113
|
+
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
|
114
|
+
# pdm recommends including project-wide configuration in pdm.toml, but excluding .pdm-python.
|
|
115
|
+
# https://pdm-project.org/en/latest/usage/project/#working-with-version-control
|
|
116
|
+
# pdm.lock
|
|
117
|
+
# pdm.toml
|
|
118
|
+
.pdm-python
|
|
119
|
+
.pdm-build/
|
|
120
|
+
|
|
121
|
+
# pixi
|
|
122
|
+
# Similar to Pipfile.lock, it is generally recommended to include pixi.lock in version control.
|
|
123
|
+
# pixi.lock
|
|
124
|
+
# Pixi creates a virtual environment in the .pixi directory, just like venv module creates one
|
|
125
|
+
# in the .venv directory. It is recommended not to include this directory in version control.
|
|
126
|
+
.pixi
|
|
127
|
+
|
|
128
|
+
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
|
129
|
+
__pypackages__/
|
|
130
|
+
|
|
131
|
+
# Celery stuff
|
|
132
|
+
celerybeat-schedule
|
|
133
|
+
celerybeat.pid
|
|
134
|
+
|
|
135
|
+
# Redis
|
|
136
|
+
*.rdb
|
|
137
|
+
*.aof
|
|
138
|
+
*.pid
|
|
139
|
+
|
|
140
|
+
# RabbitMQ
|
|
141
|
+
mnesia/
|
|
142
|
+
rabbitmq/
|
|
143
|
+
rabbitmq-data/
|
|
144
|
+
|
|
145
|
+
# ActiveMQ
|
|
146
|
+
activemq-data/
|
|
147
|
+
|
|
148
|
+
# SageMath parsed files
|
|
149
|
+
*.sage.py
|
|
150
|
+
|
|
151
|
+
# Environments
|
|
152
|
+
.env
|
|
153
|
+
.envrc
|
|
154
|
+
.venv
|
|
155
|
+
env/
|
|
156
|
+
venv/
|
|
157
|
+
ENV/
|
|
158
|
+
env.bak/
|
|
159
|
+
venv.bak/
|
|
160
|
+
|
|
161
|
+
# Spyder project settings
|
|
162
|
+
.spyderproject
|
|
163
|
+
.spyproject
|
|
164
|
+
|
|
165
|
+
# Rope project settings
|
|
166
|
+
.ropeproject
|
|
167
|
+
|
|
168
|
+
# mkdocs documentation
|
|
169
|
+
/site
|
|
170
|
+
|
|
171
|
+
# mypy
|
|
172
|
+
.mypy_cache/
|
|
173
|
+
.dmypy.json
|
|
174
|
+
dmypy.json
|
|
175
|
+
|
|
176
|
+
# Pyre type checker
|
|
177
|
+
.pyre/
|
|
178
|
+
|
|
179
|
+
# pytype static type analyzer
|
|
180
|
+
.pytype/
|
|
181
|
+
|
|
182
|
+
# Cython debug symbols
|
|
183
|
+
cython_debug/
|
|
184
|
+
|
|
185
|
+
# PyCharm
|
|
186
|
+
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
|
187
|
+
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
|
188
|
+
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
|
189
|
+
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
|
190
|
+
# .idea/
|
|
191
|
+
|
|
192
|
+
# Abstra
|
|
193
|
+
# Abstra is an AI-powered process automation framework.
|
|
194
|
+
# Ignore directories containing user credentials, local state, and settings.
|
|
195
|
+
# Learn more at https://abstra.io/docs
|
|
196
|
+
.abstra/
|
|
197
|
+
|
|
198
|
+
# Visual Studio Code
|
|
199
|
+
# Visual Studio Code specific template is maintained in a separate VisualStudioCode.gitignore
|
|
200
|
+
# that can be found at https://github.com/github/gitignore/blob/main/Global/VisualStudioCode.gitignore
|
|
201
|
+
# and can be added to the global gitignore or merged into this file. However, if you prefer,
|
|
202
|
+
# you could uncomment the following to ignore the entire vscode folder
|
|
203
|
+
# .vscode/
|
|
204
|
+
|
|
205
|
+
# Ruff stuff:
|
|
206
|
+
.ruff_cache/
|
|
207
|
+
|
|
208
|
+
# PyPI configuration file
|
|
209
|
+
.pypirc
|
|
210
|
+
|
|
211
|
+
# Marimo
|
|
212
|
+
marimo/_static/
|
|
213
|
+
marimo/_lsp/
|
|
214
|
+
__marimo__/
|
|
215
|
+
|
|
216
|
+
# Streamlit
|
|
217
|
+
.streamlit/secrets.toml
|
|
218
|
+
|
|
219
|
+
.vscode/*
|
|
220
|
+
!.vscode/settings.json
|
|
221
|
+
!.vscode/tasks.json
|
|
222
|
+
!.vscode/launch.json
|
|
223
|
+
!.vscode/extensions.json
|
|
224
|
+
!.vscode/*.code-snippets
|
|
225
|
+
!*.code-workspace
|
|
226
|
+
|
|
227
|
+
# Built Visual Studio Code Extensions
|
|
228
|
+
*.vsix
|
|
229
|
+
|
|
230
|
+
# Covers JetBrains IDEs: IntelliJ, GoLand, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
|
|
231
|
+
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
|
|
232
|
+
|
|
233
|
+
.idea/
|
|
234
|
+
|
|
235
|
+
# User-specific stuff
|
|
236
|
+
.idea/**/workspace.xml
|
|
237
|
+
.idea/**/tasks.xml
|
|
238
|
+
.idea/**/usage.statistics.xml
|
|
239
|
+
.idea/**/dictionaries
|
|
240
|
+
.idea/**/shelf
|
|
241
|
+
|
|
242
|
+
# AWS User-specific
|
|
243
|
+
.idea/**/aws.xml
|
|
244
|
+
|
|
245
|
+
# Generated files
|
|
246
|
+
.idea/**/contentModel.xml
|
|
247
|
+
|
|
248
|
+
# Sensitive or high-churn files
|
|
249
|
+
.idea/**/dataSources/
|
|
250
|
+
.idea/**/dataSources.ids
|
|
251
|
+
.idea/**/dataSources.local.xml
|
|
252
|
+
.idea/**/sqlDataSources.xml
|
|
253
|
+
.idea/**/dynamic.xml
|
|
254
|
+
.idea/**/uiDesigner.xml
|
|
255
|
+
.idea/**/dbnavigator.xml
|
|
256
|
+
|
|
257
|
+
# Gradle
|
|
258
|
+
.idea/**/gradle.xml
|
|
259
|
+
.idea/**/libraries
|
|
260
|
+
|
|
261
|
+
# Gradle and Maven with auto-import
|
|
262
|
+
# When using Gradle or Maven with auto-import, you should exclude module files,
|
|
263
|
+
# since they will be recreated, and may cause churn. Uncomment if using
|
|
264
|
+
# auto-import.
|
|
265
|
+
# .idea/artifacts
|
|
266
|
+
# .idea/compiler.xml
|
|
267
|
+
# .idea/jarRepositories.xml
|
|
268
|
+
# .idea/modules.xml
|
|
269
|
+
# .idea/*.iml
|
|
270
|
+
# .idea/modules
|
|
271
|
+
# *.iml
|
|
272
|
+
# *.ipr
|
|
273
|
+
|
|
274
|
+
# CMake
|
|
275
|
+
cmake-build-*/
|
|
276
|
+
|
|
277
|
+
# Mongo Explorer plugin
|
|
278
|
+
.idea/**/mongoSettings.xml
|
|
279
|
+
|
|
280
|
+
# File-based project format
|
|
281
|
+
*.iws
|
|
282
|
+
|
|
283
|
+
# IntelliJ
|
|
284
|
+
out/
|
|
285
|
+
|
|
286
|
+
# mpeltonen/sbt-idea plugin
|
|
287
|
+
.idea_modules/
|
|
288
|
+
|
|
289
|
+
# JIRA plugin
|
|
290
|
+
atlassian-ide-plugin.xml
|
|
291
|
+
|
|
292
|
+
# Cursive Clojure plugin
|
|
293
|
+
.idea/replstate.xml
|
|
294
|
+
|
|
295
|
+
# SonarLint plugin
|
|
296
|
+
.idea/sonarlint/
|
|
297
|
+
.idea/sonarlint.xml # see https://community.sonarsource.com/t/is-the-file-idea-idea-idea-sonarlint-xml-intended-to-be-under-source-control/121119
|
|
298
|
+
|
|
299
|
+
# Crashlytics plugin (for Android Studio and IntelliJ)
|
|
300
|
+
com_crashlytics_export_strings.xml
|
|
301
|
+
crashlytics.properties
|
|
302
|
+
crashlytics-build.properties
|
|
303
|
+
fabric.properties
|
|
304
|
+
|
|
305
|
+
# Editor-based HTTP Client
|
|
306
|
+
.idea/httpRequests
|
|
307
|
+
http-client.private.env.json
|
|
308
|
+
|
|
309
|
+
# Android studio 3.1+ serialized cache file
|
|
310
|
+
.idea/caches/build_file_checksums.ser
|
|
311
|
+
|
|
312
|
+
# Apifox Helper cache
|
|
313
|
+
.idea/.cache/.Apifox_Helper
|
|
314
|
+
.idea/ApifoxUploaderProjectSetting.xml
|
|
315
|
+
|
|
316
|
+
# Github Copilot persisted session migrations, see: https://github.com/microsoft/copilot-intellij-feedback/issues/712#issuecomment-3322062215
|
|
317
|
+
.idea/**/copilot.data.migration.*.xml
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: python-tty
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.5
|
|
4
4
|
Summary: A multi-console TTY framework for complex CLI/TTY apps
|
|
5
5
|
Home-page: https://github.com/ROOKIEMIE/python-tty
|
|
6
6
|
Author: ROOKIEMIE
|
|
@@ -12,8 +12,12 @@ Requires-Python: >=3.10
|
|
|
12
12
|
Description-Content-Type: text/markdown
|
|
13
13
|
License-File: LICENSE
|
|
14
14
|
License-File: NOTICE
|
|
15
|
+
Requires-Dist: fastapi>=0.110.0
|
|
16
|
+
Requires-Dist: grpcio>=1.60.0
|
|
15
17
|
Requires-Dist: prompt_toolkit>=3.0.32
|
|
18
|
+
Requires-Dist: protobuf>=4.25.0
|
|
16
19
|
Requires-Dist: tqdm
|
|
20
|
+
Requires-Dist: uvicorn>=0.27.0
|
|
17
21
|
Dynamic: author
|
|
18
22
|
Dynamic: classifier
|
|
19
23
|
Dynamic: description
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
def injector(service):
|
|
2
|
+
def class_decorator(cls):
|
|
3
|
+
original_init = cls.__init__
|
|
4
|
+
|
|
5
|
+
def modified_init(self, *args, **kwargs):
|
|
6
|
+
self.service = service
|
|
7
|
+
original_init(self, *args, **kwargs)
|
|
8
|
+
|
|
9
|
+
cls.__init__ = modified_init
|
|
10
|
+
return cls
|
|
11
|
+
|
|
12
|
+
return class_decorator
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
import enum
|
|
2
|
+
import inspect
|
|
3
|
+
import re
|
|
4
|
+
import shlex
|
|
5
|
+
from abc import ABC
|
|
6
|
+
from functools import wraps
|
|
7
|
+
|
|
8
|
+
from prompt_toolkit.completion import NestedCompleter
|
|
9
|
+
from prompt_toolkit.document import Document
|
|
10
|
+
from prompt_toolkit.validation import DummyValidator, Validator, ValidationError
|
|
11
|
+
from demos.file_manager.consoles import proxy_print
|
|
12
|
+
from demos.file_manager.exceptions.console_exception import ConsoleExit, ConsoleInitException
|
|
13
|
+
from demos.file_manager.utils.table import Table
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class CommandStyle(enum.Enum):
|
|
17
|
+
NONE = 0 # ClassName => ClassName
|
|
18
|
+
LOWERCASE = 1 # ClassName => classname
|
|
19
|
+
UPPERCASE = 2 # ClassName => CLASSNAME
|
|
20
|
+
POWERSHELL = 3 # ClassName => Class-Name
|
|
21
|
+
SLUGIFIED = 4 # ClassName => class-name
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class CommandInfo:
|
|
25
|
+
def __init__(self, func_name, func_description,
|
|
26
|
+
completer=None, validator=None,
|
|
27
|
+
command_alias=None):
|
|
28
|
+
self.func_name = func_name
|
|
29
|
+
self.func_description = func_description
|
|
30
|
+
self.completer = completer
|
|
31
|
+
self.validator = validator
|
|
32
|
+
if command_alias is None:
|
|
33
|
+
self.alias = []
|
|
34
|
+
else:
|
|
35
|
+
if type(command_alias) == str:
|
|
36
|
+
self.alias = [command_alias]
|
|
37
|
+
elif type(command_alias) == list:
|
|
38
|
+
self.alias = command_alias
|
|
39
|
+
else:
|
|
40
|
+
self.alias = []
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def define_command_style(command_name, style):
|
|
44
|
+
if style == CommandStyle.NONE:
|
|
45
|
+
return command_name
|
|
46
|
+
elif style == CommandStyle.LOWERCASE:
|
|
47
|
+
return command_name.lower()
|
|
48
|
+
elif style == CommandStyle.UPPERCASE:
|
|
49
|
+
return command_name.upper()
|
|
50
|
+
command_name = re.sub(r'(.)([A-Z][a-z]+)', r'\1-\2', command_name)
|
|
51
|
+
command_name = re.sub(r'([a-z0-9])([A-Z])', r'\1-\2', command_name)
|
|
52
|
+
if style == CommandStyle.POWERSHELL:
|
|
53
|
+
return command_name
|
|
54
|
+
elif style == CommandStyle.SLUGIFIED:
|
|
55
|
+
return command_name.lower()
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def register_command(command_name: str, command_description: str, command_alias=None,
|
|
59
|
+
command_style=CommandStyle.LOWERCASE,
|
|
60
|
+
completer=None, validator=None):
|
|
61
|
+
def inner_wrapper(func):
|
|
62
|
+
func.info = CommandInfo(define_command_style(command_name, command_style), command_description,
|
|
63
|
+
completer, validator, command_alias)
|
|
64
|
+
func.type = None
|
|
65
|
+
|
|
66
|
+
@wraps(func)
|
|
67
|
+
def wrapper(*args, **kwargs):
|
|
68
|
+
result = func(*args, **kwargs)
|
|
69
|
+
return result
|
|
70
|
+
|
|
71
|
+
return wrapper
|
|
72
|
+
|
|
73
|
+
return inner_wrapper
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
class GeneralValidator(Validator, ABC):
|
|
77
|
+
def __init__(self, console, func):
|
|
78
|
+
self.console = console
|
|
79
|
+
self.func = func
|
|
80
|
+
super().__init__()
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
class NoneArgumentValidator(GeneralValidator):
|
|
84
|
+
def __init__(self, console, func):
|
|
85
|
+
super().__init__(console, func)
|
|
86
|
+
|
|
87
|
+
def validate(self, document: Document) -> None:
|
|
88
|
+
sig = inspect.signature(self.func)
|
|
89
|
+
name_list = []
|
|
90
|
+
for name, param in sig.parameters.items():
|
|
91
|
+
name_list.append(name)
|
|
92
|
+
args = shlex.split(document.text)
|
|
93
|
+
if len(args) != (len(name_list) - 1):
|
|
94
|
+
raise ValidationError(message="Too many arguments!")
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
class CommandValidator(Validator):
|
|
98
|
+
def __init__(self, command_validators: dict, enable_undefined_command=False):
|
|
99
|
+
self.command_validators = command_validators
|
|
100
|
+
self.enable_undefined_command = enable_undefined_command
|
|
101
|
+
super().__init__()
|
|
102
|
+
|
|
103
|
+
def validate(self, document: Document) -> None:
|
|
104
|
+
args_l = shlex.split(document.text.strip())
|
|
105
|
+
if len(args_l) <= 0:
|
|
106
|
+
return
|
|
107
|
+
cmd = args_l[0]
|
|
108
|
+
if cmd in self.command_validators.keys():
|
|
109
|
+
cmd_validator = self.command_validators[cmd]
|
|
110
|
+
cmd_validator.validate(Document(text=' '.join(args_l[1:])))
|
|
111
|
+
else:
|
|
112
|
+
if not self.enable_undefined_command:
|
|
113
|
+
raise ValidationError(message="Bad command")
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
class BaseCommands:
|
|
117
|
+
def __init__(self, console):
|
|
118
|
+
self.console = console
|
|
119
|
+
self.command_completers = {}
|
|
120
|
+
self.command_validators = {}
|
|
121
|
+
self.command_funcs = {}
|
|
122
|
+
self._init_funcs()
|
|
123
|
+
self.completer = NestedCompleter.from_nested_dict(self.command_completers)
|
|
124
|
+
self.validator = CommandValidator(self.command_validators, self.enable_undefined_command)
|
|
125
|
+
|
|
126
|
+
@property
|
|
127
|
+
def enable_undefined_command(self):
|
|
128
|
+
return False
|
|
129
|
+
|
|
130
|
+
def _init_funcs(self):
|
|
131
|
+
# Separate function and inner class
|
|
132
|
+
funcs = self._get_funcs()
|
|
133
|
+
self._collect_completer_and_validator(funcs)
|
|
134
|
+
|
|
135
|
+
def _get_funcs(self):
|
|
136
|
+
cls = self.__class__
|
|
137
|
+
funcs = []
|
|
138
|
+
for member_name in dir(cls):
|
|
139
|
+
# Skip all include '_' method
|
|
140
|
+
if member_name.startswith("_"):
|
|
141
|
+
continue
|
|
142
|
+
member = getattr(cls, member_name)
|
|
143
|
+
# Include 'type' attr should be collected
|
|
144
|
+
if (inspect.ismethod(member) or inspect.isfunction(member)) and hasattr(member, "type"):
|
|
145
|
+
funcs.append(member)
|
|
146
|
+
return funcs
|
|
147
|
+
|
|
148
|
+
def _collect_completer_and_validator(self, funcs):
|
|
149
|
+
if self.console is None:
|
|
150
|
+
raise ConsoleInitException("Console is None")
|
|
151
|
+
for func in funcs:
|
|
152
|
+
command_info: CommandInfo = func.info
|
|
153
|
+
self._map_components(command_info.func_name, func, command_info.completer, command_info.validator)
|
|
154
|
+
if len(command_info.alias) > 0:
|
|
155
|
+
for alia in command_info.alias:
|
|
156
|
+
self._map_components(alia, func, command_info.completer, command_info.validator)
|
|
157
|
+
|
|
158
|
+
def _map_components(self, command_name, func, completer, validator):
|
|
159
|
+
self.command_funcs[command_name] = func
|
|
160
|
+
if completer is None:
|
|
161
|
+
self.command_completers[command_name] = None
|
|
162
|
+
else:
|
|
163
|
+
self.command_completers[command_name] = completer(self.console)
|
|
164
|
+
if validator is None:
|
|
165
|
+
self.command_validators[command_name] = DummyValidator()
|
|
166
|
+
else:
|
|
167
|
+
self.command_validators[command_name] = validator(self.console, func)
|
|
168
|
+
|
|
169
|
+
@register_command("quit", "Quit Console", "exit", validator=NoneArgumentValidator)
|
|
170
|
+
def run_quit(self):
|
|
171
|
+
raise ConsoleExit
|
|
172
|
+
|
|
173
|
+
@register_command("help", "Display help information", ["?"], validator=NoneArgumentValidator)
|
|
174
|
+
def run_help(self):
|
|
175
|
+
header = ["Command", "Description"]
|
|
176
|
+
base_funcs = []
|
|
177
|
+
customer_funcs = []
|
|
178
|
+
base_commands_funcs = [member[1] for member in inspect.getmembers(BaseCommands, inspect.isfunction)]
|
|
179
|
+
for name, func in self.command_funcs.items():
|
|
180
|
+
if func in base_commands_funcs:
|
|
181
|
+
base_funcs.append([name, func.info.func_description])
|
|
182
|
+
else:
|
|
183
|
+
customer_funcs.append([name, func.info.func_description])
|
|
184
|
+
proxy_print("")
|
|
185
|
+
proxy_print(Table(header, base_funcs, "Core Commands"))
|
|
186
|
+
proxy_print("")
|
|
187
|
+
proxy_print(Table(header, customer_funcs, "Customer Commands"))
|
|
188
|
+
proxy_print("")
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import inspect
|
|
2
|
+
import shlex
|
|
3
|
+
|
|
4
|
+
from prompt_toolkit.completion import WordCompleter
|
|
5
|
+
from prompt_toolkit.document import Document
|
|
6
|
+
from prompt_toolkit.validation import ValidationError
|
|
7
|
+
|
|
8
|
+
from demos.file_manager.commands import BaseCommands, register_command, GeneralValidator
|
|
9
|
+
from demos.file_manager.consoles import proxy_print
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class RootCommands(BaseCommands):
|
|
13
|
+
# def enable_undefined_command(self):
|
|
14
|
+
# return True
|
|
15
|
+
|
|
16
|
+
class EnvValidator(GeneralValidator):
|
|
17
|
+
def __init__(self, console, func):
|
|
18
|
+
super().__init__(console, func)
|
|
19
|
+
|
|
20
|
+
def validate(self, document: Document) -> None:
|
|
21
|
+
sig = inspect.signature(self.func)
|
|
22
|
+
name_list = []
|
|
23
|
+
for name, param in sig.parameters.items():
|
|
24
|
+
name_list.append(name)
|
|
25
|
+
name_list = name_list[1:]
|
|
26
|
+
args = shlex.split(document.text)
|
|
27
|
+
if len(args) <= 0:
|
|
28
|
+
raise ValidationError(message="At least one parameter is missing")
|
|
29
|
+
elif len(args) > len(name_list):
|
|
30
|
+
raise ValidationError(message="Too many parameter to get")
|
|
31
|
+
|
|
32
|
+
class EnvCompleter(WordCompleter):
|
|
33
|
+
def __init__(self, console):
|
|
34
|
+
super().__init__(console.service.env_keys)
|
|
35
|
+
|
|
36
|
+
@register_command("env", "Display env information", [], completer=EnvCompleter, validator=EnvValidator)
|
|
37
|
+
def run_env(self, env_key):
|
|
38
|
+
proxy_print()
|
|
39
|
+
table = ""
|
|
40
|
+
if env_key == "disk":
|
|
41
|
+
table = self.console.service.display_disks()
|
|
42
|
+
elif env_key == "os":
|
|
43
|
+
table = self.console.service.display_os()
|
|
44
|
+
elif env_key == "network":
|
|
45
|
+
table = self.console.service.display_network()
|
|
46
|
+
proxy_print(table)
|
|
47
|
+
proxy_print()
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
if __name__ == '__main__':
|
|
51
|
+
pass
|