qonsole 2.0.0__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.
- qonsole-2.0.0/.flake8 +4 -0
- qonsole-2.0.0/.gitattributes +2 -0
- qonsole-2.0.0/.github/workflows/lint.yml +22 -0
- qonsole-2.0.0/.github/workflows/publish.yml +28 -0
- qonsole-2.0.0/.github/workflows/tests.yml +51 -0
- qonsole-2.0.0/.gitignore +224 -0
- qonsole-2.0.0/LICENSE +46 -0
- qonsole-2.0.0/PKG-INFO +178 -0
- qonsole-2.0.0/README.md +150 -0
- qonsole-2.0.0/examples/_gevent.py +55 -0
- qonsole-2.0.0/examples/inuithread.py +23 -0
- qonsole-2.0.0/examples/threaded.py +98 -0
- qonsole-2.0.0/media/qonsole.png +0 -0
- qonsole-2.0.0/media/qonsole.svg +72 -0
- qonsole-2.0.0/pixi.lock +4834 -0
- qonsole-2.0.0/pyproject.toml +84 -0
- qonsole-2.0.0/qonsole/__init__.py +14 -0
- qonsole-2.0.0/qonsole/autocomplete.py +368 -0
- qonsole-2.0.0/qonsole/commandhistory.py +90 -0
- qonsole-2.0.0/qonsole/console.py +1291 -0
- qonsole-2.0.0/qonsole/highlighter.py +399 -0
- qonsole-2.0.0/qonsole/interpreter.py +285 -0
- qonsole-2.0.0/qonsole/magic.py +264 -0
- qonsole-2.0.0/qonsole/prompt.py +143 -0
- qonsole-2.0.0/qonsole/stream.py +136 -0
- qonsole-2.0.0/qonsole/text.py +272 -0
- qonsole-2.0.0/qonsole.code-workspace +23 -0
- qonsole-2.0.0/tests/test_autocomplete.py +79 -0
- qonsole-2.0.0/tests/test_commandhistory.py +60 -0
- qonsole-2.0.0/tests/test_console.py +140 -0
- qonsole-2.0.0/tests/test_interpreter.py +45 -0
- qonsole-2.0.0/tests/test_magic.py +72 -0
- qonsole-2.0.0/tests/test_stream.py +69 -0
- qonsole-2.0.0/tests/test_text.py +207 -0
qonsole-2.0.0/.flake8
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Test the source for formatting and code check (pass/fail).
|
|
3
|
+
#
|
|
4
|
+
|
|
5
|
+
name: Linting
|
|
6
|
+
|
|
7
|
+
on: [push, pull_request]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
|
|
11
|
+
linting:
|
|
12
|
+
runs-on: ubuntu-latest
|
|
13
|
+
name: Ruff code check
|
|
14
|
+
steps:
|
|
15
|
+
- uses: actions/checkout@v6
|
|
16
|
+
- uses: actions/setup-python@v6
|
|
17
|
+
with:
|
|
18
|
+
python-version: "3.13"
|
|
19
|
+
- run: pip install ruff
|
|
20
|
+
- run: |
|
|
21
|
+
ruff format --check
|
|
22
|
+
ruff check
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
name: Upload to PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [created]
|
|
6
|
+
|
|
7
|
+
jobs:
|
|
8
|
+
pypi-publish:
|
|
9
|
+
name: Publish release to PyPI
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
environment:
|
|
12
|
+
name: pypi
|
|
13
|
+
url: https://pypi.org/p/qonsole
|
|
14
|
+
permissions:
|
|
15
|
+
id-token: write
|
|
16
|
+
steps:
|
|
17
|
+
- uses: actions/checkout@v6.0.2
|
|
18
|
+
- name: Set up pixi
|
|
19
|
+
uses: prefix-dev/setup-pixi@v0.9.4
|
|
20
|
+
with:
|
|
21
|
+
pixi-version: v0.63.2
|
|
22
|
+
cache: true
|
|
23
|
+
manifest-path: pyproject.toml
|
|
24
|
+
- name: Build package
|
|
25
|
+
run: |
|
|
26
|
+
pixi run --manifest-path ./pyproject.toml hatch build
|
|
27
|
+
- name: Publish package distributions to PyPI
|
|
28
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
#
|
|
2
|
+
# This workflow will install the package and run the unittests.
|
|
3
|
+
#
|
|
4
|
+
|
|
5
|
+
name: PyTest tests
|
|
6
|
+
|
|
7
|
+
on: [push, pull_request]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
|
|
11
|
+
tests:
|
|
12
|
+
|
|
13
|
+
strategy:
|
|
14
|
+
fail-fast: false
|
|
15
|
+
matrix:
|
|
16
|
+
python: ["3.9", "3.10", "3.11", "3.12", "3.13", "3.14"]
|
|
17
|
+
# On MacOS the tests are the fastest because no Qt dependencies need to be installed
|
|
18
|
+
os: [macos-latest]
|
|
19
|
+
qt: ["PySide6"]
|
|
20
|
+
include:
|
|
21
|
+
# Also try Ubuntu and Windows, but just with the most common options:
|
|
22
|
+
- { os: ubuntu-latest, python: "3.13", qt: "PySide6" }
|
|
23
|
+
- { os: windows-latest, python: "3.13", qt: "PySide6" }
|
|
24
|
+
# Also try other Qt packages, but just with the easiest OS and common Python version:
|
|
25
|
+
- { os: macos-latest, python: "3.13", qt: "PyQt6" }
|
|
26
|
+
- { os: macos-latest, python: "3.13", qt: "PyQt5" }
|
|
27
|
+
|
|
28
|
+
runs-on: ${{matrix.os}}
|
|
29
|
+
|
|
30
|
+
env:
|
|
31
|
+
# Allow Qt to run without rendering anything:
|
|
32
|
+
QT_QPA_PLATFORM: "offscreen"
|
|
33
|
+
XDG_RUNTIME_DIR: "/tmp/runtime-root"
|
|
34
|
+
# Force Qt test with a particular version:
|
|
35
|
+
PYTEST_QT_API: ${{ matrix.qt }}
|
|
36
|
+
|
|
37
|
+
steps:
|
|
38
|
+
- uses: actions/checkout@v6
|
|
39
|
+
- uses: actions/setup-python@v6
|
|
40
|
+
with:
|
|
41
|
+
python-version: ${{matrix.python}}
|
|
42
|
+
|
|
43
|
+
- run: pip install coverage pytest pytest-qt ${{ matrix.qt }}
|
|
44
|
+
- run: pip install -e .
|
|
45
|
+
|
|
46
|
+
- name: Install Qt system dependencies
|
|
47
|
+
if: matrix.os == 'ubuntu-latest'
|
|
48
|
+
run: sudo apt-get update && sudo apt-get install -y libegl1 libxkbcommon-x11-0
|
|
49
|
+
# We need quite some packages for `pytest-qt` to run without problems
|
|
50
|
+
|
|
51
|
+
- run: coverage run -m pytest tests/ -v && coverage report
|
qonsole-2.0.0/.gitignore
ADDED
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
# From: https://github.com/github/gitignore/blob/main/Python.gitignore
|
|
2
|
+
|
|
3
|
+
# Byte-compiled / optimized / DLL files
|
|
4
|
+
__pycache__/
|
|
5
|
+
*.py[codz]
|
|
6
|
+
*$py.class
|
|
7
|
+
|
|
8
|
+
# C extensions
|
|
9
|
+
*.so
|
|
10
|
+
|
|
11
|
+
# Distribution / packaging
|
|
12
|
+
.Python
|
|
13
|
+
build/
|
|
14
|
+
develop-eggs/
|
|
15
|
+
dist/
|
|
16
|
+
downloads/
|
|
17
|
+
eggs/
|
|
18
|
+
.eggs/
|
|
19
|
+
lib/
|
|
20
|
+
lib64/
|
|
21
|
+
parts/
|
|
22
|
+
sdist/
|
|
23
|
+
var/
|
|
24
|
+
wheels/
|
|
25
|
+
share/python-wheels/
|
|
26
|
+
*.egg-info/
|
|
27
|
+
.installed.cfg
|
|
28
|
+
*.egg
|
|
29
|
+
MANIFEST
|
|
30
|
+
|
|
31
|
+
# PyInstaller
|
|
32
|
+
# Usually these files are written by a python script from a template
|
|
33
|
+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
|
34
|
+
*.manifest
|
|
35
|
+
*.spec
|
|
36
|
+
|
|
37
|
+
# Installer logs
|
|
38
|
+
pip-log.txt
|
|
39
|
+
pip-delete-this-directory.txt
|
|
40
|
+
|
|
41
|
+
# Unit test / coverage reports
|
|
42
|
+
htmlcov/
|
|
43
|
+
.tox/
|
|
44
|
+
.nox/
|
|
45
|
+
.coverage
|
|
46
|
+
.coverage.*
|
|
47
|
+
.cache
|
|
48
|
+
nosetests.xml
|
|
49
|
+
coverage.xml
|
|
50
|
+
*.cover
|
|
51
|
+
*.py.cover
|
|
52
|
+
.hypothesis/
|
|
53
|
+
.pytest_cache/
|
|
54
|
+
cover/
|
|
55
|
+
|
|
56
|
+
# Translations
|
|
57
|
+
*.mo
|
|
58
|
+
*.pot
|
|
59
|
+
|
|
60
|
+
# Django stuff:
|
|
61
|
+
*.log
|
|
62
|
+
local_settings.py
|
|
63
|
+
db.sqlite3
|
|
64
|
+
db.sqlite3-journal
|
|
65
|
+
|
|
66
|
+
# Flask stuff:
|
|
67
|
+
instance/
|
|
68
|
+
.webassets-cache
|
|
69
|
+
|
|
70
|
+
# Scrapy stuff:
|
|
71
|
+
.scrapy
|
|
72
|
+
|
|
73
|
+
# Sphinx documentation
|
|
74
|
+
docs/_build/
|
|
75
|
+
|
|
76
|
+
# PyBuilder
|
|
77
|
+
.pybuilder/
|
|
78
|
+
target/
|
|
79
|
+
|
|
80
|
+
# Jupyter Notebook
|
|
81
|
+
.ipynb_checkpoints
|
|
82
|
+
|
|
83
|
+
# IPython
|
|
84
|
+
profile_default/
|
|
85
|
+
ipython_config.py
|
|
86
|
+
|
|
87
|
+
# pyenv
|
|
88
|
+
# For a library or package, you might want to ignore these files since the code is
|
|
89
|
+
# intended to run in multiple environments; otherwise, check them in:
|
|
90
|
+
# .python-version
|
|
91
|
+
|
|
92
|
+
# pipenv
|
|
93
|
+
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
|
94
|
+
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
|
95
|
+
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
|
96
|
+
# install all needed dependencies.
|
|
97
|
+
# Pipfile.lock
|
|
98
|
+
|
|
99
|
+
# UV
|
|
100
|
+
# Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
|
|
101
|
+
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
|
102
|
+
# commonly ignored for libraries.
|
|
103
|
+
# uv.lock
|
|
104
|
+
|
|
105
|
+
# poetry
|
|
106
|
+
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
|
107
|
+
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
|
108
|
+
# commonly ignored for libraries.
|
|
109
|
+
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
|
110
|
+
# poetry.lock
|
|
111
|
+
# poetry.toml
|
|
112
|
+
|
|
113
|
+
# pdm
|
|
114
|
+
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
|
115
|
+
# pdm recommends including project-wide configuration in pdm.toml, but excluding .pdm-python.
|
|
116
|
+
# https://pdm-project.org/en/latest/usage/project/#working-with-version-control
|
|
117
|
+
# pdm.lock
|
|
118
|
+
# pdm.toml
|
|
119
|
+
.pdm-python
|
|
120
|
+
.pdm-build/
|
|
121
|
+
|
|
122
|
+
# pixi
|
|
123
|
+
# Similar to Pipfile.lock, it is generally recommended to include pixi.lock in version control.
|
|
124
|
+
# pixi.lock
|
|
125
|
+
# Pixi creates a virtual environment in the .pixi directory, just like venv module creates one
|
|
126
|
+
# in the .venv directory. It is recommended not to include this directory in version control.
|
|
127
|
+
.pixi
|
|
128
|
+
|
|
129
|
+
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
|
130
|
+
__pypackages__/
|
|
131
|
+
|
|
132
|
+
# Celery stuff
|
|
133
|
+
celerybeat-schedule
|
|
134
|
+
celerybeat.pid
|
|
135
|
+
|
|
136
|
+
# Redis
|
|
137
|
+
*.rdb
|
|
138
|
+
*.aof
|
|
139
|
+
*.pid
|
|
140
|
+
|
|
141
|
+
# RabbitMQ
|
|
142
|
+
mnesia/
|
|
143
|
+
rabbitmq/
|
|
144
|
+
rabbitmq-data/
|
|
145
|
+
|
|
146
|
+
# ActiveMQ
|
|
147
|
+
activemq-data/
|
|
148
|
+
|
|
149
|
+
# SageMath parsed files
|
|
150
|
+
*.sage.py
|
|
151
|
+
|
|
152
|
+
# Environments
|
|
153
|
+
.env
|
|
154
|
+
.envrc
|
|
155
|
+
.venv
|
|
156
|
+
env/
|
|
157
|
+
venv/
|
|
158
|
+
ENV/
|
|
159
|
+
env.bak/
|
|
160
|
+
venv.bak/
|
|
161
|
+
|
|
162
|
+
# Spyder project settings
|
|
163
|
+
.spyderproject
|
|
164
|
+
.spyproject
|
|
165
|
+
|
|
166
|
+
# Rope project settings
|
|
167
|
+
.ropeproject
|
|
168
|
+
|
|
169
|
+
# mkdocs documentation
|
|
170
|
+
/site
|
|
171
|
+
|
|
172
|
+
# mypy
|
|
173
|
+
.mypy_cache/
|
|
174
|
+
.dmypy.json
|
|
175
|
+
dmypy.json
|
|
176
|
+
|
|
177
|
+
# Pyre type checker
|
|
178
|
+
.pyre/
|
|
179
|
+
|
|
180
|
+
# pytype static type analyzer
|
|
181
|
+
.pytype/
|
|
182
|
+
|
|
183
|
+
# Cython debug symbols
|
|
184
|
+
cython_debug/
|
|
185
|
+
|
|
186
|
+
# PyCharm
|
|
187
|
+
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
|
188
|
+
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
|
189
|
+
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
|
190
|
+
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
|
191
|
+
.idea/
|
|
192
|
+
|
|
193
|
+
# Abstra
|
|
194
|
+
# Abstra is an AI-powered process automation framework.
|
|
195
|
+
# Ignore directories containing user credentials, local state, and settings.
|
|
196
|
+
# Learn more at https://abstra.io/docs
|
|
197
|
+
.abstra/
|
|
198
|
+
|
|
199
|
+
# Visual Studio Code
|
|
200
|
+
# Visual Studio Code specific template is maintained in a separate VisualStudioCode.gitignore
|
|
201
|
+
# that can be found at https://github.com/github/gitignore/blob/main/Global/VisualStudioCode.gitignore
|
|
202
|
+
# and can be added to the global gitignore or merged into this file. However, if you prefer,
|
|
203
|
+
# you could uncomment the following to ignore the entire vscode folder
|
|
204
|
+
.vscode/
|
|
205
|
+
|
|
206
|
+
# Ruff stuff:
|
|
207
|
+
.ruff_cache/
|
|
208
|
+
|
|
209
|
+
# PyPI configuration file
|
|
210
|
+
.pypirc
|
|
211
|
+
|
|
212
|
+
# Marimo
|
|
213
|
+
marimo/_static/
|
|
214
|
+
marimo/_lsp/
|
|
215
|
+
__marimo__/
|
|
216
|
+
|
|
217
|
+
# Streamlit
|
|
218
|
+
.streamlit/secrets.toml
|
|
219
|
+
|
|
220
|
+
.DS_Store# pixi environments
|
|
221
|
+
.pixi/*
|
|
222
|
+
!.pixi/config.toml
|
|
223
|
+
|
|
224
|
+
.DS_Store
|
qonsole-2.0.0/LICENSE
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Jacob Williams
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
22
|
+
|
|
23
|
+
-------------------------------------------------------------------------
|
|
24
|
+
Pyqtconsole license:
|
|
25
|
+
|
|
26
|
+
MIT License
|
|
27
|
+
|
|
28
|
+
Copyright (c) 2015 Marcus Oscarsson
|
|
29
|
+
|
|
30
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
31
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
32
|
+
in the Software without restriction, including without limitation the rights
|
|
33
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
34
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
35
|
+
furnished to do so, subject to the following conditions:
|
|
36
|
+
|
|
37
|
+
The above copyright notice and this permission notice shall be included in all
|
|
38
|
+
copies or substantial portions of the Software.
|
|
39
|
+
|
|
40
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
41
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
42
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
43
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
44
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
45
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
46
|
+
SOFTWARE.
|
qonsole-2.0.0/PKG-INFO
ADDED
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: qonsole
|
|
3
|
+
Version: 2.0.0
|
|
4
|
+
Summary: Light-weight python interpreter, easy to embed into Qt applications
|
|
5
|
+
Project-URL: Homepage, https://github.com/jacobwilliams/qonsole
|
|
6
|
+
Author-email: Jacob Williams <jacobwilliams@users.noreply.github.com>
|
|
7
|
+
License-Expression: MIT
|
|
8
|
+
License-File: LICENSE
|
|
9
|
+
Keywords: autocompletion,console,interactive,interpreter,jedi,qt,shell
|
|
10
|
+
Classifier: Environment :: X11 Applications :: Qt
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: Operating System :: OS Independent
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Topic :: Software Development :: Interpreters
|
|
15
|
+
Classifier: Topic :: Software Development :: User Interfaces
|
|
16
|
+
Requires-Python: <4.0,>=3.9
|
|
17
|
+
Requires-Dist: ipython-pygments-lexers
|
|
18
|
+
Requires-Dist: jedi
|
|
19
|
+
Requires-Dist: pygments
|
|
20
|
+
Requires-Dist: qtpy
|
|
21
|
+
Provides-Extra: dev
|
|
22
|
+
Requires-Dist: hatch; extra == 'dev'
|
|
23
|
+
Requires-Dist: pytest; extra == 'dev'
|
|
24
|
+
Requires-Dist: pytest-cov; extra == 'dev'
|
|
25
|
+
Requires-Dist: pytest-qt; extra == 'dev'
|
|
26
|
+
Requires-Dist: ruff; extra == 'dev'
|
|
27
|
+
Description-Content-Type: text/markdown
|
|
28
|
+
|
|
29
|
+
<h1 align="center">
|
|
30
|
+
<img src="https://raw.githubusercontent.com/jacobwilliams/qonsole/master/media/qonsole.png" width=400">
|
|
31
|
+
</h1>
|
|
32
|
+
|
|
33
|
+
<!-- Badges -->
|
|
34
|
+
<p align="left">
|
|
35
|
+
<!-- Python version badge -->
|
|
36
|
+
<a href="https://www.python.org/"><img src="https://img.shields.io/badge/language-python-blue.svg" alt="Python"></a>
|
|
37
|
+
<!-- PyPI badge -->
|
|
38
|
+
<a href="https://pypi.org/project/qonsole/"><img src="https://img.shields.io/pypi/v/qonsole.svg" alt="PyPI"></a>
|
|
39
|
+
<!-- conda-forge badge -->
|
|
40
|
+
<a href="https://anaconda.org/conda-forge/qonsole"><img src="https://img.shields.io/conda/vn/conda-forge/qonsole.svg" alt="Conda-Forge"></a>
|
|
41
|
+
<!-- GitHub Actions CI badge -->
|
|
42
|
+
<a href="https://github.com/jacobwilliams/qonsole/actions"><img src="https://github.com/jacobwilliams/qonsole/actions/workflows/docs.yml/badge.svg" alt="GitHub CI Status"></a>
|
|
43
|
+
<a href="https://github.com/jacobwilliams/qonsole/actions"><img src="https://github.com/jacobwilliams/qonsole/actions/workflows/publish.yml/badge.svg" alt="GitHub CI Status"></a>
|
|
44
|
+
</p>
|
|
45
|
+
|
|
46
|
+
# qonsole
|
|
47
|
+
|
|
48
|
+
Qonsole is a lightweight Python console for Qt applications. It's made to
|
|
49
|
+
be easy to embed in other PySide/PyQt applications and comes with some examples that
|
|
50
|
+
show how this can be done. The interpreter can run in a separate thread, in
|
|
51
|
+
the UI main thread or in a gevent task. Qonsole is a fork of [pyqtconsole](https://github.com/pyqtconsole/pyqtconsole). The two diverged at pyqtconsole v1.3.0, and it is not quite a drop-in replacement, but does implement new features and has various improvements.
|
|
52
|
+
|
|
53
|
+
## Simple usage
|
|
54
|
+
|
|
55
|
+
The following snippet shows how to create a console that will execute user
|
|
56
|
+
input in a separate thread. Be aware that long running tasks will still block
|
|
57
|
+
the main thread due to the GIL. See the ``examples`` directory for more
|
|
58
|
+
examples.
|
|
59
|
+
|
|
60
|
+
```python
|
|
61
|
+
import sys
|
|
62
|
+
from threading import Thread
|
|
63
|
+
from PyQt5.QtWidgets import QApplication
|
|
64
|
+
|
|
65
|
+
from qonsole import PythonConsole
|
|
66
|
+
|
|
67
|
+
app = QApplication([])
|
|
68
|
+
console = PythonConsole()
|
|
69
|
+
console.show()
|
|
70
|
+
console.eval_in_thread()
|
|
71
|
+
|
|
72
|
+
sys.exit(app.exec_())
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## Embedding
|
|
76
|
+
|
|
77
|
+
* *Separate thread* - Runs the interpreter in a separate thread, see the
|
|
78
|
+
example `threaded.py`. Running the interpreter in a separate thread obviously
|
|
79
|
+
limits the interaction with the Qt application. The parts of Qt that needs
|
|
80
|
+
to be called from the main thread will not work properly, but is excellent
|
|
81
|
+
way for having a 'plain' python console in your Qt app.
|
|
82
|
+
|
|
83
|
+
* *main thread* - Runs the interpreter in the main thread, see the example
|
|
84
|
+
`inuithread.py`. Makes full interaction with Qt possible, lenghty operations
|
|
85
|
+
will of course freeze the UI (as any lenghty operation that is called from
|
|
86
|
+
the main thread). This is a great alternative for people who does not want
|
|
87
|
+
to use the gevent based approach but still wants full interactivity with Qt.
|
|
88
|
+
|
|
89
|
+
* *gevent* - Runs the interpreter in a gevent task, see the example
|
|
90
|
+
`_gevent.py`. Allows for full interactivity with Qt without special
|
|
91
|
+
consideration (at least to some extent) for longer running processes. The
|
|
92
|
+
best method if you want to use pyQtgraph, Matplotlib, PyMca or similar.
|
|
93
|
+
|
|
94
|
+
## Features
|
|
95
|
+
|
|
96
|
+
### Syntax highlighting
|
|
97
|
+
|
|
98
|
+
Syntax highlighting is provided by the [https://pygments.org](pygments) library.
|
|
99
|
+
Simply pass the Pygments style string to the ``PythonConsole`` constructer like so:
|
|
100
|
+
|
|
101
|
+
```python
|
|
102
|
+
console = PythonConsole(pygments_style='github-dark')
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### Magic commands
|
|
106
|
+
|
|
107
|
+
Commands that start with `%` are magic commands.
|
|
108
|
+
This features provides IPython-like [magic commands](https://ipython.readthedocs.io/en/stable/interactive/magics.html) such as:
|
|
109
|
+
|
|
110
|
+
* `%pwd` -- Print current working directory
|
|
111
|
+
* `%cd` -- Change directory
|
|
112
|
+
* `%ls` -- List directory contents
|
|
113
|
+
* `%who` -- List variable names in the current namespace
|
|
114
|
+
* `%whos` -- Display detailed variable information
|
|
115
|
+
* `%timeit` -- Time the execution of a Python statement
|
|
116
|
+
* `%run` -- Execute a Python script file
|
|
117
|
+
* `%clear` -- Clear the console display
|
|
118
|
+
* `%help` -- Display help message for magic commands
|
|
119
|
+
|
|
120
|
+
In addition, custom magic commands can be defined by using the `add_magic_command()` method. Example:
|
|
121
|
+
|
|
122
|
+
```python
|
|
123
|
+
def version(args=None):
|
|
124
|
+
return '2.0.0'
|
|
125
|
+
|
|
126
|
+
console = PythonConsole()
|
|
127
|
+
console.add_magic_command("version", version)
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
Which can be used like so:
|
|
131
|
+
|
|
132
|
+
```
|
|
133
|
+
IN [0]: %version
|
|
134
|
+
2.0.0
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
### Clear console
|
|
138
|
+
|
|
139
|
+
A local method, named `clear()`, is available to clear the input screen and reset the line numbering.
|
|
140
|
+
Enable it by pushing the method into the available namespace in the console:
|
|
141
|
+
|
|
142
|
+
```python
|
|
143
|
+
console.interpreter.locals["clear"] = console.clear
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
### Shell commands
|
|
147
|
+
|
|
148
|
+
Commands entered in the console that start with `!` will be executed as shell commands.
|
|
149
|
+
The output of the command will be printed in the console.
|
|
150
|
+
For example, on a Linux or macOS system, entering `!ls -l` will list the files in the current directory. Example:
|
|
151
|
+
|
|
152
|
+
```
|
|
153
|
+
IN [0]: !ls -l
|
|
154
|
+
OUT[0]: total 16546
|
|
155
|
+
-rw-r--r-- 1 user user 18741 Fen 6 2026 file1.txt
|
|
156
|
+
-rw-r--r-- 1 user user 18741 Feb 6 2026 file2.txt
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### Prompt String
|
|
160
|
+
|
|
161
|
+
By default ``IN [n]:`` and ``OUT [n]:`` are displayed before each input and output line.
|
|
162
|
+
You can customize this through constructor arguments:
|
|
163
|
+
|
|
164
|
+
```python
|
|
165
|
+
# Including the line numbers:
|
|
166
|
+
console = PythonConsole(inprompt="%d >", outprompt="%d <")
|
|
167
|
+
# Or just static:
|
|
168
|
+
console = PythonConsole(inprompt=">>>", outprompt="<<<")
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
## Credits
|
|
172
|
+
|
|
173
|
+
This module depends on [QtPy](https://github.com/spyder-ide/qtpy) which provides a compatibility layer for
|
|
174
|
+
Qt. The console is tested under both Qt5 and Qt6.
|
|
175
|
+
|
|
176
|
+
## Development
|
|
177
|
+
|
|
178
|
+
To generate coverage information for the unit tests, run `coverage run -m pytest tests/ && coverage report -m && coverage html`
|