Compare commits

...

8 Commits
main ... v3.6.1

Author SHA1 Message Date
qutebrowser bot 2e5f805cce Release v3.6.1 2025-11-03 15:29:59 +00:00
Florian Bruhin 155b5cb241 Fix changelog
(cherry picked from commit 6e8e24050d)
2025-11-03 16:27:06 +01:00
Florian Bruhin 0deadea17f Adjust stack trace parsing for newer Python
(cherry picked from commit aa93eb1614)
2025-11-03 16:26:26 +01:00
Florian Bruhin b3377fccff Fix releasing focus when leaving command mode
The fix for #8223 in 6f21accfae
was misguided: We don't really care about the statusbar being hidden,
controlled release of keyboard focus needs to happen in any case where
we're hiding the command widget (as that's when we lose keyboard focus).

Fixes #8750.

(cherry picked from commit b646d606d7)
2025-10-25 16:45:13 +02:00
Florian Bruhin 11acdd2fdf ci: Fix finding existing draft release
(cherry picked from commit 1e4ddc2c6b)
2025-10-24 17:03:00 +02:00
Florian Bruhin 8f4e6ec06e scripts: Avoid showing entire file tree diff in CI log
(cherry picked from commit 3fce0518bd)
2025-10-24 17:02:59 +02:00
Florian Bruhin 52fd43c95e ci: Find existing draft release for reuploads
(cherry picked from commit 3808ebfdb3)
2025-10-24 16:23:37 +02:00
Florian Bruhin 26df4ce7e3 ci: Check out release branch for reuploads 2025-10-24 15:44:26 +02:00
10 changed files with 103 additions and 18 deletions

View File

@ -1,5 +1,5 @@
[tool.bumpversion]
current_version = "3.6.0"
current_version = "3.6.1"
commit = true
message = "Release v{new_version}"
tag = true

View File

@ -32,7 +32,8 @@ jobs:
timeout-minutes: 5
outputs:
version: ${{ steps.bump.outputs.version }}
release_id: ${{ steps.create-release.outputs.id }}
version_x: ${{ steps.bump.outputs.version_x }}
release_id: ${{ inputs.release_type == 'reupload' && steps.find-release.outputs.result || steps.create-release.outputs.id }}
permissions:
contents: write # To push release commit/tag
steps:
@ -126,6 +127,28 @@ jobs:
tag_name: v${{ steps.bump.outputs.version }}
draft: true
body: "*Release artifacts for this release are currently being uploaded...*"
- name: Find GitHub draft release
if: ${{ inputs.release_type == 'reupload' }}
id: find-release
uses: actions/github-script@v8
with:
script: |
const releases = await github.paginate(github.rest.repos.listReleases, {
owner: context.repo.owner,
repo: context.repo.repo,
});
const names = releases.map(release => release.name);
console.log(`releases: ${names}`);
const release = releases.find(release => release.tag_name === "v${{ steps.bump.outputs.version }}");
if (release === undefined) {
core.setFailed(`No release found with tag v${{ steps.bump.outputs.version }}!`);
}
if (!release.draft) {
core.setFailed(`Release ${release.tag_name} is not a draft release!`);
}
return release.id;
result-encoding: string
release:
strategy:
matrix:
@ -142,7 +165,7 @@ jobs:
steps:
- uses: actions/checkout@v5
with:
ref: v${{ needs.prepare.outputs.version }}
ref: v${{ inputs.release_type == 'reupload' && needs.prepare.outputs.version_x || needs.prepare.outputs.version }}
- name: Set up Python
uses: actions/setup-python@v6
with:

View File

@ -15,6 +15,17 @@ breaking changes (such as renamed commands) can happen in minor releases.
// `Fixed` for any bug fixes.
// `Security` to invite users to upgrade in case of vulnerabilities.
[[v3.6.1]]
v3.6.1 (2025-11-03)
-------------------
Fixed
~~~~~
- A regression in v3.6.0 where the page didn't have keyboard focus after closing
the completion, so e.g. typing in an input field after hinting didn't work.
(#8750)
[[v3.6.0]]
v3.6.0 (2025-10-24)
-------------------

View File

@ -44,6 +44,7 @@
</content_rating>
<releases>
<!-- Add new releases here -->
<release version='3.6.1' date='2025-11-03'/>
<release version='3.6.0' date='2025-10-24'/>
<release version='3.5.1' date='2025-06-05'/>
<release version='3.5.0' date='2025-04-12'/>

View File

@ -14,7 +14,7 @@ __copyright__ = "Copyright 2013-{} Florian Bruhin (The Compiler)".format(_year)
__license__ = "GPL-3.0-or-later"
__maintainer__ = __author__
__email__ = "mail@qutebrowser.org"
__version__ = "3.6.0"
__version__ = "3.6.1"
__version_info__ = tuple(int(part) for part in __version__.split('.'))
__description__ = "A keyboard-driven, vim-like browser based on Python and Qt."

View File

@ -286,20 +286,16 @@ class StatusBar(QWidget):
strategy = config.val.statusbar.show
tab = self._current_tab()
if tab is not None and tab.data.fullscreen:
self.release_focus.emit()
self.hide()
elif strategy == 'never':
self.release_focus.emit()
self.hide()
elif strategy == 'in-mode':
try:
mode_manager = modeman.instance(self._win_id)
except modeman.UnavailableError:
self.release_focus.emit()
self.hide()
else:
if mode_manager.mode == usertypes.KeyMode.normal:
self.release_focus.emit()
self.hide()
else:
self.show()
@ -371,6 +367,7 @@ class StatusBar(QWidget):
def _hide_cmd_widget(self):
"""Show temporary text instead of command widget."""
log.statusbar.debug("Hiding cmd widget")
self.release_focus.emit()
self._stack.setCurrentWidget(self.txt)
self.maybe_hide()

View File

@ -48,8 +48,8 @@ def parse_fatal_stacktrace(text):
lines = [
r'(?P<type>Fatal Python error|Windows fatal exception): (?P<msg>.*)',
r' *',
r'(Current )?[Tt]hread [^ ]* \(most recent call first\): *',
r' File ".*", line \d+ in (?P<func>.*)',
r'(Current )?[Tt]hread .* \(most recent call first\): *',
r' (File ".*", line \d+ in (?P<func>.*)|<no Python frame>)',
]
m = re.search('\n'.join(lines), text)
if m is None:
@ -58,7 +58,7 @@ def parse_fatal_stacktrace(text):
else:
msg = m.group('msg')
typ = m.group('type')
func = m.group('func')
func = m.group('func') or ''
if typ == 'Windows fatal exception':
msg = 'Windows ' + msg
return msg, func

View File

@ -54,6 +54,7 @@ def show_commit():
git_args = ['git', 'show']
if utils.ON_CI:
git_args.append("--color")
git_args.append("--no-patch") # shows entire git tree on CI (shallow clone)
subprocess.run(git_args, check=True)

View File

@ -103,3 +103,11 @@ Feature: Using completion
And I run :completion-item-focus next
And I run :cmd-set-text -s :set
Then the completion model should be option
Scenario: Page focus after using completion (#8750)
When I open data/insert_mode_settings/html/input.html
And I run :cmd-set-text :
And I run :mode-leave
And I run :click-element id qute-input
And I run :fake-key -g someinput
Then the javascript message "contents: someinput" should be logged

View File

@ -32,6 +32,31 @@ Thread 0x00007fa135ac7700 (most recent call first):
File "", line 1 in testfunc
"""
VALID_CRASH_TEXT_PY314 = """
Fatal Python error: Segmentation fault
_
Current thread 0x00000001fe53e140 [CrBrowserMain] (most recent call first):
File "qutebrowser/app.py", line 126 in qt_mainloop
File "qutebrowser/app.py", line 116 in run
File "qutebrowser/qutebrowser.py", line 234 in main
File "__main__.py", line 15 in <module>
_
Current thread's C stack trace (most recent call first):
Binary file "...", at _Py_DumpStack+0x48 [0x10227cc9c]
<truncated rest of calls>
"""
VALID_CRASH_TEXT_PY314_NO_PY = """
Fatal Python error: Segmentation fault
_
Current thread 0x00007f0dc805cbc0 [qutebrowser] (most recent call first):
<no Python frame>
_
Current thread's C stack trace (most recent call first):
Binary file "/lib64/libpython3.14.so.1.0", at _Py_DumpStack+0x4c [0x7f0dc7b2127b]
<truncated rest of calls>
"""
WINDOWS_CRASH_TEXT = r"""
Windows fatal exception: access violation
_
@ -45,13 +70,32 @@ Hello world!
"""
@pytest.mark.parametrize('text, typ, func', [
(VALID_CRASH_TEXT, 'Segmentation fault', 'testfunc'),
(VALID_CRASH_TEXT_THREAD, 'Segmentation fault', 'testfunc'),
(VALID_CRASH_TEXT_EMPTY, 'Aborted', ''),
(WINDOWS_CRASH_TEXT, 'Windows access violation', 'tabopen'),
(INVALID_CRASH_TEXT, '', ''),
])
@pytest.mark.parametrize(
"text, typ, func",
[
pytest.param(VALID_CRASH_TEXT, "Segmentation fault", "testfunc", id="valid"),
pytest.param(
VALID_CRASH_TEXT_THREAD, "Segmentation fault", "testfunc", id="valid-thread"
),
pytest.param(
VALID_CRASH_TEXT_PY314,
"Segmentation fault",
"qt mainloop",
id="valid-py314",
),
pytest.param(
VALID_CRASH_TEXT_PY314_NO_PY,
"Segmentation fault",
"",
id="valid-py314-no-py",
),
pytest.param(VALID_CRASH_TEXT_EMPTY, "Aborted", "", id="valid-empty"),
pytest.param(
WINDOWS_CRASH_TEXT, "Windows access violation", "tabopen", id="windows"
),
pytest.param(INVALID_CRASH_TEXT, "", "", id="invalid"),
],
)
def test_parse_fatal_stacktrace(text, typ, func):
text = text.strip().replace('_', ' ')
assert crashdialog.parse_fatal_stacktrace(text) == (typ, func)