linux-browser 0.1.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.
- linux_browser-0.1.0/PKG-INFO +63 -0
- linux_browser-0.1.0/README.md +52 -0
- linux_browser-0.1.0/pyproject.toml +28 -0
- linux_browser-0.1.0/setup.cfg +4 -0
- linux_browser-0.1.0/src/linux_browser/__init__.py +3 -0
- linux_browser-0.1.0/src/linux_browser/app.py +81 -0
- linux_browser-0.1.0/src/linux_browser.egg-info/PKG-INFO +63 -0
- linux_browser-0.1.0/src/linux_browser.egg-info/SOURCES.txt +12 -0
- linux_browser-0.1.0/src/linux_browser.egg-info/dependency_links.txt +1 -0
- linux_browser-0.1.0/src/linux_browser.egg-info/entry_points.txt +2 -0
- linux_browser-0.1.0/src/linux_browser.egg-info/requires.txt +2 -0
- linux_browser-0.1.0/src/linux_browser.egg-info/top_level.txt +1 -0
- linux_browser-0.1.0/tests/test_package.py +8 -0
- linux_browser-0.1.0/tests/test_webengine.py +46 -0
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: linux-browser
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: A small Chromium-powered graphical web browser for Linux
|
|
5
|
+
Author: linux-browser contributors
|
|
6
|
+
License: MIT
|
|
7
|
+
Requires-Python: >=3.9
|
|
8
|
+
Description-Content-Type: text/markdown
|
|
9
|
+
Requires-Dist: PySide6>=6.6
|
|
10
|
+
Requires-Dist: PySide6-WebEngine>=6.6
|
|
11
|
+
|
|
12
|
+
# Linux Browser
|
|
13
|
+
|
|
14
|
+
A small graphical browser for Linux, packaged as a normal Python application. It uses Qt WebEngine, which embeds Chromium, so pages are rendered with their real HTML, CSS, JavaScript, images, and network behavior rather than being converted to terminal text.
|
|
15
|
+
|
|
16
|
+
## Debian 12
|
|
17
|
+
|
|
18
|
+
Install a display server (a desktop session is fine) and the runtime libraries used by Qt:
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
sudo apt update
|
|
22
|
+
sudo apt install libegl1 libgl1 libnss3 libxkbcommon-x11-0 libxcb-cursor0 \
|
|
23
|
+
libxcomposite1 libxdamage1 libxrandr2 libasound2 xdg-utils
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
The PyPI wheels provide the Qt and Chromium components. A working graphical session and graphics driver are still required to show the window. On a headless machine, run it inside a desktop container or an X server such as Xvfb.
|
|
27
|
+
|
|
28
|
+
## Install and run
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
python3 -m venv .venv
|
|
32
|
+
.venv/bin/python -m pip install linux-browser
|
|
33
|
+
.venv/bin/linux-browser
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Open a specific page directly:
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
linux-browser https://example.com
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
The address bar accepts URLs and search terms. Back, forward, reload, and common keyboard shortcuts are available in the toolbar.
|
|
43
|
+
|
|
44
|
+
## Development
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
python3 -m venv .venv
|
|
48
|
+
.venv/bin/python -m pip install -e . pytest build
|
|
49
|
+
.venv/bin/python -m pytest
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
The WebEngine test loads an in-memory page and checks that CSS and JavaScript execute. It is skipped when PySide6 is not installed, which keeps package metadata checks usable in minimal build environments.
|
|
53
|
+
|
|
54
|
+
## Build and publish
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
.venv/bin/python -m build
|
|
58
|
+
.venv/bin/python -m pip install twine
|
|
59
|
+
.venv/bin/twine check dist/*
|
|
60
|
+
.venv/bin/twine upload dist/*
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Publishing requires a PyPI account and credentials configured for `twine`.
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# Linux Browser
|
|
2
|
+
|
|
3
|
+
A small graphical browser for Linux, packaged as a normal Python application. It uses Qt WebEngine, which embeds Chromium, so pages are rendered with their real HTML, CSS, JavaScript, images, and network behavior rather than being converted to terminal text.
|
|
4
|
+
|
|
5
|
+
## Debian 12
|
|
6
|
+
|
|
7
|
+
Install a display server (a desktop session is fine) and the runtime libraries used by Qt:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
sudo apt update
|
|
11
|
+
sudo apt install libegl1 libgl1 libnss3 libxkbcommon-x11-0 libxcb-cursor0 \
|
|
12
|
+
libxcomposite1 libxdamage1 libxrandr2 libasound2 xdg-utils
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
The PyPI wheels provide the Qt and Chromium components. A working graphical session and graphics driver are still required to show the window. On a headless machine, run it inside a desktop container or an X server such as Xvfb.
|
|
16
|
+
|
|
17
|
+
## Install and run
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
python3 -m venv .venv
|
|
21
|
+
.venv/bin/python -m pip install linux-browser
|
|
22
|
+
.venv/bin/linux-browser
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Open a specific page directly:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
linux-browser https://example.com
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
The address bar accepts URLs and search terms. Back, forward, reload, and common keyboard shortcuts are available in the toolbar.
|
|
32
|
+
|
|
33
|
+
## Development
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
python3 -m venv .venv
|
|
37
|
+
.venv/bin/python -m pip install -e . pytest build
|
|
38
|
+
.venv/bin/python -m pytest
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
The WebEngine test loads an in-memory page and checks that CSS and JavaScript execute. It is skipped when PySide6 is not installed, which keeps package metadata checks usable in minimal build environments.
|
|
42
|
+
|
|
43
|
+
## Build and publish
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
.venv/bin/python -m build
|
|
47
|
+
.venv/bin/python -m pip install twine
|
|
48
|
+
.venv/bin/twine check dist/*
|
|
49
|
+
.venv/bin/twine upload dist/*
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Publishing requires a PyPI account and credentials configured for `twine`.
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "linux-browser"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "A small Chromium-powered graphical web browser for Linux"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.9"
|
|
11
|
+
license = { text = "MIT" }
|
|
12
|
+
authors = [{ name = "linux-browser contributors" }]
|
|
13
|
+
dependencies = [
|
|
14
|
+
"PySide6>=6.6",
|
|
15
|
+
"PySide6-WebEngine>=6.6",
|
|
16
|
+
]
|
|
17
|
+
|
|
18
|
+
[project.scripts]
|
|
19
|
+
linux-browser = "linux_browser.app:main"
|
|
20
|
+
|
|
21
|
+
[tool.setuptools]
|
|
22
|
+
package-dir = {"" = "src"}
|
|
23
|
+
|
|
24
|
+
[tool.setuptools.packages.find]
|
|
25
|
+
where = ["src"]
|
|
26
|
+
|
|
27
|
+
[tool.pytest.ini_options]
|
|
28
|
+
testpaths = ["tests"]
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
"""Graphical browser application powered by Qt WebEngine."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import sys
|
|
6
|
+
from urllib.parse import quote
|
|
7
|
+
|
|
8
|
+
from PySide6.QtCore import QUrl
|
|
9
|
+
from PySide6.QtGui import QAction, QKeySequence
|
|
10
|
+
from PySide6.QtWidgets import QApplication, QLineEdit, QMainWindow, QToolBar
|
|
11
|
+
from PySide6.QtWebEngineWidgets import QWebEngineView
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class BrowserWindow(QMainWindow):
|
|
15
|
+
"""A minimal browser window with real Chromium page rendering."""
|
|
16
|
+
|
|
17
|
+
def __init__(self, start_url: str = "https://duckduckgo.com") -> None:
|
|
18
|
+
super().__init__()
|
|
19
|
+
self.setWindowTitle("Linux Browser")
|
|
20
|
+
self.resize(1280, 800)
|
|
21
|
+
|
|
22
|
+
toolbar = QToolBar("Navigation")
|
|
23
|
+
toolbar.setMovable(False)
|
|
24
|
+
self.addToolBar(toolbar)
|
|
25
|
+
|
|
26
|
+
back_action = QAction("Back", self)
|
|
27
|
+
back_action.setShortcut(QKeySequence("Alt+Left"))
|
|
28
|
+
back_action.triggered.connect(lambda: self.web_view.back())
|
|
29
|
+
toolbar.addAction(back_action)
|
|
30
|
+
|
|
31
|
+
forward_action = QAction("Forward", self)
|
|
32
|
+
forward_action.setShortcut(QKeySequence("Alt+Right"))
|
|
33
|
+
forward_action.triggered.connect(lambda: self.web_view.forward())
|
|
34
|
+
toolbar.addAction(forward_action)
|
|
35
|
+
|
|
36
|
+
reload_action = QAction("Reload", self)
|
|
37
|
+
reload_action.setShortcut(QKeySequence("Ctrl+R"))
|
|
38
|
+
reload_action.triggered.connect(lambda: self.web_view.reload())
|
|
39
|
+
toolbar.addAction(reload_action)
|
|
40
|
+
|
|
41
|
+
self.address_bar = QLineEdit()
|
|
42
|
+
self.address_bar.setPlaceholderText("Enter a web address or search term")
|
|
43
|
+
self.address_bar.setClearButtonEnabled(True)
|
|
44
|
+
self.address_bar.returnPressed.connect(self.navigate)
|
|
45
|
+
toolbar.addWidget(self.address_bar)
|
|
46
|
+
|
|
47
|
+
self.web_view = QWebEngineView()
|
|
48
|
+
self.web_view.urlChanged.connect(self.update_address)
|
|
49
|
+
self.web_view.titleChanged.connect(self.update_title)
|
|
50
|
+
self.setCentralWidget(self.web_view)
|
|
51
|
+
self.navigate(start_url)
|
|
52
|
+
|
|
53
|
+
def navigate(self, text: str | None = None) -> None:
|
|
54
|
+
address = (text if text is not None else self.address_bar.text()).strip()
|
|
55
|
+
if not address:
|
|
56
|
+
return
|
|
57
|
+
if " " in address or "." not in address and not address.startswith(("http://", "https://", "file:", "data:")):
|
|
58
|
+
address = f"https://duckduckgo.com/?q={quote(address)}"
|
|
59
|
+
elif not address.startswith(("http://", "https://", "file:", "data:")):
|
|
60
|
+
address = f"https://{address}"
|
|
61
|
+
self.web_view.setUrl(QUrl(address))
|
|
62
|
+
|
|
63
|
+
def update_address(self, url: QUrl) -> None:
|
|
64
|
+
self.address_bar.setText(url.toString())
|
|
65
|
+
self.address_bar.setCursorPosition(0)
|
|
66
|
+
|
|
67
|
+
def update_title(self, title: str) -> None:
|
|
68
|
+
self.setWindowTitle(f"{title} - Linux Browser" if title else "Linux Browser")
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def main(argv: list[str] | None = None) -> int:
|
|
72
|
+
args = sys.argv[1:] if argv is None else argv
|
|
73
|
+
app = QApplication([sys.argv[0], *args])
|
|
74
|
+
app.setApplicationName("Linux Browser")
|
|
75
|
+
window = BrowserWindow(args[0] if args else "https://duckduckgo.com")
|
|
76
|
+
window.show()
|
|
77
|
+
return app.exec()
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
if __name__ == "__main__":
|
|
81
|
+
raise SystemExit(main())
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: linux-browser
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: A small Chromium-powered graphical web browser for Linux
|
|
5
|
+
Author: linux-browser contributors
|
|
6
|
+
License: MIT
|
|
7
|
+
Requires-Python: >=3.9
|
|
8
|
+
Description-Content-Type: text/markdown
|
|
9
|
+
Requires-Dist: PySide6>=6.6
|
|
10
|
+
Requires-Dist: PySide6-WebEngine>=6.6
|
|
11
|
+
|
|
12
|
+
# Linux Browser
|
|
13
|
+
|
|
14
|
+
A small graphical browser for Linux, packaged as a normal Python application. It uses Qt WebEngine, which embeds Chromium, so pages are rendered with their real HTML, CSS, JavaScript, images, and network behavior rather than being converted to terminal text.
|
|
15
|
+
|
|
16
|
+
## Debian 12
|
|
17
|
+
|
|
18
|
+
Install a display server (a desktop session is fine) and the runtime libraries used by Qt:
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
sudo apt update
|
|
22
|
+
sudo apt install libegl1 libgl1 libnss3 libxkbcommon-x11-0 libxcb-cursor0 \
|
|
23
|
+
libxcomposite1 libxdamage1 libxrandr2 libasound2 xdg-utils
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
The PyPI wheels provide the Qt and Chromium components. A working graphical session and graphics driver are still required to show the window. On a headless machine, run it inside a desktop container or an X server such as Xvfb.
|
|
27
|
+
|
|
28
|
+
## Install and run
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
python3 -m venv .venv
|
|
32
|
+
.venv/bin/python -m pip install linux-browser
|
|
33
|
+
.venv/bin/linux-browser
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Open a specific page directly:
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
linux-browser https://example.com
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
The address bar accepts URLs and search terms. Back, forward, reload, and common keyboard shortcuts are available in the toolbar.
|
|
43
|
+
|
|
44
|
+
## Development
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
python3 -m venv .venv
|
|
48
|
+
.venv/bin/python -m pip install -e . pytest build
|
|
49
|
+
.venv/bin/python -m pytest
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
The WebEngine test loads an in-memory page and checks that CSS and JavaScript execute. It is skipped when PySide6 is not installed, which keeps package metadata checks usable in minimal build environments.
|
|
53
|
+
|
|
54
|
+
## Build and publish
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
.venv/bin/python -m build
|
|
58
|
+
.venv/bin/python -m pip install twine
|
|
59
|
+
.venv/bin/twine check dist/*
|
|
60
|
+
.venv/bin/twine upload dist/*
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Publishing requires a PyPI account and credentials configured for `twine`.
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
README.md
|
|
2
|
+
pyproject.toml
|
|
3
|
+
src/linux_browser/__init__.py
|
|
4
|
+
src/linux_browser/app.py
|
|
5
|
+
src/linux_browser.egg-info/PKG-INFO
|
|
6
|
+
src/linux_browser.egg-info/SOURCES.txt
|
|
7
|
+
src/linux_browser.egg-info/dependency_links.txt
|
|
8
|
+
src/linux_browser.egg-info/entry_points.txt
|
|
9
|
+
src/linux_browser.egg-info/requires.txt
|
|
10
|
+
src/linux_browser.egg-info/top_level.txt
|
|
11
|
+
tests/test_package.py
|
|
12
|
+
tests/test_webengine.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
linux_browser
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
import unittest
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
try:
|
|
6
|
+
from PySide6.QtCore import QEventLoop, QTimer
|
|
7
|
+
from PySide6.QtWidgets import QApplication
|
|
8
|
+
from PySide6.QtWebEngineWidgets import QWebEngineView
|
|
9
|
+
except ImportError:
|
|
10
|
+
QWebEngineView = None
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@unittest.skipUnless(QWebEngineView, "PySide6-WebEngine is not installed")
|
|
14
|
+
class WebEngineSmokeTest(unittest.TestCase):
|
|
15
|
+
@classmethod
|
|
16
|
+
def setUpClass(cls) -> None:
|
|
17
|
+
cls.application = QApplication.instance() or QApplication(sys.argv)
|
|
18
|
+
|
|
19
|
+
def test_renders_css_and_runs_javascript(self) -> None:
|
|
20
|
+
view = QWebEngineView()
|
|
21
|
+
loaded = []
|
|
22
|
+
view.loadFinished.connect(loaded.append)
|
|
23
|
+
view.setHtml(
|
|
24
|
+
"<html><head><style>body { color: rgb(1, 2, 3); }</style></head>"
|
|
25
|
+
"<body><main id='content'>initial</main>"
|
|
26
|
+
"<script>document.title = 'Rendered';"
|
|
27
|
+
"document.querySelector('#content').textContent = 'JavaScript ran';</script>"
|
|
28
|
+
"</body></html>"
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
loop = QEventLoop()
|
|
32
|
+
view.loadFinished.connect(loop.quit)
|
|
33
|
+
QTimer.singleShot(5000, loop.quit)
|
|
34
|
+
loop.exec()
|
|
35
|
+
self.assertTrue(loaded and loaded[-1])
|
|
36
|
+
|
|
37
|
+
result = []
|
|
38
|
+
view.page().runJavaScript(
|
|
39
|
+
"[document.title, document.querySelector('#content').textContent, "
|
|
40
|
+
"getComputedStyle(document.body).color]",
|
|
41
|
+
result.append,
|
|
42
|
+
)
|
|
43
|
+
QTimer.singleShot(1000, loop.quit)
|
|
44
|
+
loop.exec()
|
|
45
|
+
self.assertEqual(result, [["Rendered", "JavaScript ran", "rgb(1, 2, 3)"]])
|
|
46
|
+
view.deleteLater()
|