Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
From 38ca9528ad40988d9b7c0a524c2457cfc345c392 Mon Sep 17 00:00:00 2001
From: midichef <67946319+midichef@users.noreply.github.com>
Date: Wed, 19 Nov 2025 11:52:19 -0800
Subject: [PATCH] [path-] handle filenames ending in . in Python 3.14 (#2887)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* [path-] handle filenames ending in . in Python 3.14

docs for pathlib say: Changed in version 3.14: A single dot (”.”)
is considered a valid suffix.

* [ci] add Python 3.14 test coverage
---
.github/workflows/main.yml | 2 +-
visidata/path.py | 2 +-
visidata/tests/test_path.py | 2 ++
3 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index c0e19cfc..5b4d29bf 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -14,7 +14,7 @@ jobs:

strategy:
matrix:
- python-version: [3.8, 3.9, "3.10", "3.11", "3.12", "3.13"]
+ python-version: [3.8, 3.9, "3.10", "3.11", "3.12", "3.13", "3.14"]

runs-on: ubuntu-latest
timeout-minutes: 20
diff --git a/visidata/path.py b/visidata/path.py
index d5564b62..e7a811d1 100644
--- a/visidata/path.py
+++ b/visidata/path.py
@@ -193,7 +193,7 @@ class Path(os.PathLike):
self._path = pathlib.Path(given)

self.ext = self.suffix[1:]
- if self.suffix: #1450 don't make this a oneliner; [:-0] doesn't work
+ if self.suffix and self.suffix != '.': #1450 don't make this a oneliner; [:-0] doesn't work #2887
self.base_stem = self._path.name[:-len(self.suffix)]
elif self._given == '.': #1768
self.base_stem = self._path.absolute().name
diff --git a/visidata/tests/test_path.py b/visidata/tests/test_path.py
index 4bc39f83..170b28c9 100644
--- a/visidata/tests/test_path.py
+++ b/visidata/tests/test_path.py
@@ -23,6 +23,8 @@ class TestVisidataPath:
assert Path('foo').base_stem == 'foo'
assert Path('foo.').ext == ''
assert Path('foo.').base_stem == 'foo.'
+ assert Path('foo..').ext == ''
+ assert Path('foo..').base_stem == 'foo..'
assert Path('.foo').ext == ''
assert Path('.foo').base_stem == '.foo'

--
2.52.0

66 changes: 66 additions & 0 deletions srcpkgs/visidata/patches/remove-mailcap.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
remove dead mailcap battery

diff --git a/setup.py b/setup.py
index 23d588a0..386c3389 100755
--- a/setup.py
+++ b/setup.py
@@ -29,7 +29,6 @@ __version__ = "3.3"
install_requires = [
"python-dateutil",
'importlib_resources; python_version<"3.9"',
- 'standard-mailcap; python_version>="3.13"',
]

if not sysconfig.get_platform().startswith("mingw"): # 2757
diff --git a/visidata/features/sysopen_mailcap.py b/visidata/features/sysopen_mailcap.py
deleted file mode 100644
index fa1821c1..00000000
--- a/visidata/features/sysopen_mailcap.py
+++ /dev/null
@@ -1,46 +0,0 @@
-''' Plugin for viewing files with appropriate mailcap-specified application.
-Add mailcap-view and mailcap-view-selected commands to DirSheet.
-
-mimetype can be given explicitly with `mimetype` option; will be guessed by filename otherwise.
-
-Usage:
- - add `import experimental.mailcap_view` to .visidatarc
- - on the DirSheet, `Ctrl+V` or `gCtrl+V` to view file(s) using mailcap entry for the guessed (or given via options) mimetype
-'''
-
-import os
-from visidata import vd, DirSheet, SuspendCurses
-
-vd.option('mailcap_mimetype', '', 'force mimetype for sysopen-mailcap')
-vd.optalias('mimetype', 'mailcap_mimetype')
-
-
-@DirSheet.api
-def run_mailcap(sheet, p, key='view'):
- import mailcap
- import mimetypes
-
- mimetype = sheet.options.mailcap_mimetype
- if not mimetype:
- mimetype, encoding = mimetypes.guess_type(str(p))
-
- if not mimetype:
- vd.fail('no mimetype given and no guess')
-
- caps = mailcap.getcaps()
-
- plist = [f'{k}={v}' for k, v in sheet.options.getall('mailcap_').items() if k != 'mailcap_mimetype']
- cmdline, mcap_entry = mailcap.findmatch(caps, mimetype, key=key, filename=str(p), plist=plist)
-
- with SuspendCurses():
- os.system(cmdline)
-
-
-DirSheet.addCommand('', 'sysopen-mailcap', 'run_mailcap(cursorRow)', 'open using mailcap entry for current row, guessing mimetype')
-DirSheet.addCommand('', 'sysopen-mailcap-selected', 'for r in selectedRows: run_mailcap(r)', 'open selected files in succession, using mailcap')
-
-
-vd.addMenuItems('''
- File > Open > using mailcap > file at cursor > sysopen-mailcap
- File > Open > using mailcap > selected files > sysopen-mailcap-selected
-''')
6 changes: 3 additions & 3 deletions srcpkgs/visidata/template
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Template file for 'visidata'
pkgname=visidata
version=3.1.1
revision=4
version=3.3
revision=1
build_style=python3-module
hostmakedepends="python3-setuptools"
depends="python3-dateutil python3-importlib_metadata python3-setuptools"
Expand All @@ -12,4 +12,4 @@ license="GPL-3.0-only"
homepage="https://visidata.org/"
changelog="https://raw.githubusercontent.com/saulpw/visidata/stable/CHANGELOG.md"
distfiles="https://github.com/saulpw/visidata/archive/refs/tags/v${version}.tar.gz"
checksum=9e693d72d516adca2c52348531af98fef099ab6f09e6523976286b555a7599ee
checksum=4d7f93bdcc6da98030df5e3198e4098d9b57b9cae6f0ccaca9820a85e1bef51b